From db04a92499ab4df0774c21cfb089087af752e52f Mon Sep 17 00:00:00 2001 From: KNVx Date: Fri, 17 Nov 2023 17:25:03 +0100 Subject: [PATCH 01/21] [ADD] mrp_production_batch: new module --- mrp_production_batch/README.rst | 63 +++ mrp_production_batch/__init__.py | 2 + mrp_production_batch/__manifest__.py | 22 + .../data/ir_sequence_data.xml | 14 + mrp_production_batch/models/__init__.py | 4 + mrp_production_batch/models/mrp_production.py | 85 ++++ .../models/mrp_production_batch.py | 99 ++++ mrp_production_batch/models/stock_move.py | 28 ++ mrp_production_batch/models/stock_picking.py | 78 ++++ mrp_production_batch/readme/CONTRIBUTORS.rst | 3 + mrp_production_batch/readme/DESCRIPTION.rst | 1 + .../security/ir.model.access.csv | 4 + .../static/description/icon.png | Bin 0 -> 6342 bytes .../static/description/index.html | 422 ++++++++++++++++++ .../views/mrp_production_batch_views.xml | 102 +++++ .../views/mrp_production_views.xml | 66 +++ .../views/stock_picking_views.xml | 37 ++ mrp_production_batch/wizard/__init__.py | 2 + .../wizard/wizard_mrp_production_batch.py | 28 ++ .../wizard/wizard_mrp_production_batch.xml | 41 ++ .../wizard_mrp_production_batch_line.py | 22 + .../odoo/addons/mrp_production_batch | 1 + setup/mrp_production_batch/setup.py | 6 + 23 files changed, 1130 insertions(+) create mode 100644 mrp_production_batch/README.rst create mode 100644 mrp_production_batch/__init__.py create mode 100644 mrp_production_batch/__manifest__.py create mode 100644 mrp_production_batch/data/ir_sequence_data.xml create mode 100644 mrp_production_batch/models/__init__.py create mode 100644 mrp_production_batch/models/mrp_production.py create mode 100644 mrp_production_batch/models/mrp_production_batch.py create mode 100644 mrp_production_batch/models/stock_move.py create mode 100644 mrp_production_batch/models/stock_picking.py create mode 100644 mrp_production_batch/readme/CONTRIBUTORS.rst create mode 100644 mrp_production_batch/readme/DESCRIPTION.rst create mode 100644 mrp_production_batch/security/ir.model.access.csv create mode 100644 mrp_production_batch/static/description/icon.png create mode 100644 mrp_production_batch/static/description/index.html create mode 100644 mrp_production_batch/views/mrp_production_batch_views.xml create mode 100644 mrp_production_batch/views/mrp_production_views.xml create mode 100644 mrp_production_batch/views/stock_picking_views.xml create mode 100644 mrp_production_batch/wizard/__init__.py create mode 100644 mrp_production_batch/wizard/wizard_mrp_production_batch.py create mode 100644 mrp_production_batch/wizard/wizard_mrp_production_batch.xml create mode 100644 mrp_production_batch/wizard/wizard_mrp_production_batch_line.py create mode 120000 setup/mrp_production_batch/odoo/addons/mrp_production_batch create mode 100644 setup/mrp_production_batch/setup.py diff --git a/mrp_production_batch/README.rst b/mrp_production_batch/README.rst new file mode 100644 index 000000000..2d1b93e23 --- /dev/null +++ b/mrp_production_batch/README.rst @@ -0,0 +1,63 @@ +==================== +MRP Production Batch +==================== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:230afdff2552dd582a6157902bb10a837c066ebf7b5fea6caffc644f8e8bc76c + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-NuoBiT%2Fodoo--addons-lightgray.png?logo=github + :target: https://github.com/NuoBiT/odoo-addons/tree/14.0/mrp_production_batch + :alt: NuoBiT/odoo-addons + +|badge1| |badge2| |badge3| + +* Added + +**Table of contents** + +.. contents:: + :local: + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* NuoBiT Solutions +* S.L. + +Contributors +~~~~~~~~~~~~ + +* `NuoBiT `_: + + * Kilian Niubo + +Maintainers +~~~~~~~~~~~ + +This module is part of the `NuoBiT/odoo-addons `_ project on GitHub. + +You are welcome to contribute. diff --git a/mrp_production_batch/__init__.py b/mrp_production_batch/__init__.py new file mode 100644 index 000000000..9b4296142 --- /dev/null +++ b/mrp_production_batch/__init__.py @@ -0,0 +1,2 @@ +from . import models +from . import wizard diff --git a/mrp_production_batch/__manifest__.py b/mrp_production_batch/__manifest__.py new file mode 100644 index 000000000..11e905abe --- /dev/null +++ b/mrp_production_batch/__manifest__.py @@ -0,0 +1,22 @@ +# Copyright NuoBiT Solutions - Kilian Niubo +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) + +{ + "name": "MRP Production Batch", + "summary": "Customizations for Oxigen in MRP Production", + "version": "14.0.1.0.0", + "author": "NuoBiT Solutions, S.L.", + "website": "https://github.com/nuobit/odoo-addons", + "category": "Manufacturing/Manufacturing", + "depends": ["mrp"], + "installable": True, + "license": "AGPL-3", + "data": [ + "security/ir.model.access.csv", + "data/ir_sequence_data.xml", + "views/mrp_production_batch_views.xml", + "views/mrp_production_views.xml", + "views/stock_picking_views.xml", + "wizard/wizard_mrp_production_batch.xml", + ], +} diff --git a/mrp_production_batch/data/ir_sequence_data.xml b/mrp_production_batch/data/ir_sequence_data.xml new file mode 100644 index 000000000..61f827d0f --- /dev/null +++ b/mrp_production_batch/data/ir_sequence_data.xml @@ -0,0 +1,14 @@ + + + + + MRP Production Batch + mrp.production.batch + MOB/ + 5 + + + diff --git a/mrp_production_batch/models/__init__.py b/mrp_production_batch/models/__init__.py new file mode 100644 index 000000000..667931bd5 --- /dev/null +++ b/mrp_production_batch/models/__init__.py @@ -0,0 +1,4 @@ +from . import mrp_production +from . import mrp_production_batch +from . import stock_move +from . import stock_picking diff --git a/mrp_production_batch/models/mrp_production.py b/mrp_production_batch/models/mrp_production.py new file mode 100644 index 000000000..6528f92bc --- /dev/null +++ b/mrp_production_batch/models/mrp_production.py @@ -0,0 +1,85 @@ +# Copyright NuoBiT Solutions - Kilian Niubo +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) +from odoo import _, api, fields, models +from odoo.exceptions import ValidationError + + +class MrpProduction(models.Model): + _inherit = "mrp.production" + + production_batch_id = fields.Many2one( + comodel_name="mrp.production.batch", + string="Production Batch", + readonly=True, + ) + + def _check_production_to_batch_consitency(self, mrp_production_ids): + if not mrp_production_ids: + raise ValidationError(_("No productions selected")) + if mrp_production_ids.mapped("production_batch_id"): + raise ValidationError( + _("Some of the selected productions already have a batch") + ) + if any( + state in ("done", "cancel") for state in mrp_production_ids.mapped("state") + ): + raise ValidationError( + _("Some of the selected productions are already done or cancelled") + ) + picking_type_ids = mrp_production_ids.mapped("picking_type_id") + if len(picking_type_ids) > 1: + raise ValidationError( + _( + "Some of the selected productions have different picking types:%s" + % picking_type_ids.mapped("name") + ) + ) + + def mrp_production_batch_create_wizard_action(self): + model = self.env.context.get("active_model") + mrp_production_ids = self.env[model].browse(self.env.context.get("active_ids")) + self._check_production_to_batch_consitency(mrp_production_ids) + self.env["mrp.production.batch"].create( + { + "creation_date": str(fields.Datetime.now()), + "production_ids": [ + (6, 0, mrp_production_ids.ids), + ], + } + ) + + @api.constrains("state") + def _check_state_batch_creation(self): + for rec in self: + if rec.state == "cancel": + if rec.production_batch_id: + raise ValidationError( + _( + "You can't cancel a production that belongs to a batch %s. " + "Please, delete it from the batch first." + ) + % rec.production_batch_id.name + ) + elif rec.state == "done": + if rec.production_batch_id and not self.env.context.get("batch_create"): + raise ValidationError( + _( + "You can't change the state of a production %s " + "because it belongs to a batch: %s. \n " + "It must be processed from the batch." + ) + % (rec.name, rec.production_batch_id.name) + ) + + def action_view_production_batch(self): + self.ensure_one() + view = self.env.ref("mrp_production_batch.mrp_production_batch_form_view") + return { + "name": _("Detailed Operations"), + "type": "ir.actions.act_window", + "view_mode": "form", + "res_model": "mrp.production.batch", + "views": [(view.id, "form")], + "view_id": view.id, + "res_id": self.production_batch_id.id, + } diff --git a/mrp_production_batch/models/mrp_production_batch.py b/mrp_production_batch/models/mrp_production_batch.py new file mode 100644 index 000000000..96c36f863 --- /dev/null +++ b/mrp_production_batch/models/mrp_production_batch.py @@ -0,0 +1,99 @@ +# Copyright NuoBiT Solutions - Kilian Niubo +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) +from odoo import _, api, fields, models + + +class MrpProductionBatch(models.Model): + _name = "mrp.production.batch" + + @api.model + def _default_name(self): + return self.env["ir.sequence"].next_by_code("mrp.production.batch") + + name = fields.Char( + default=_default_name, + readonly=True, + ) + production_ids = fields.One2many( + comodel_name="mrp.production", + inverse_name="production_batch_id", + string="Manufacturing Orders", + ) + production_qty = fields.Integer( + compute="_compute_production_qty", + ) + + def _compute_production_qty(self): + for rec in self: + rec.production_qty = len(rec.production_ids) + + pending_production_qty = fields.Integer( + compute="_compute_pending_production_qty", + ) + + def _compute_pending_production_qty(self): + for rec in self: + rec.pending_production_qty = len( + rec.production_ids.filtered(lambda r: r.state != "done") + ) + + creation_date = fields.Datetime( + string="Creation Date", + ) + state = fields.Selection( + selection=[ + ("draft", "Draft"), + ("done", "Done"), + ], + default="draft", + ) + product_qty = fields.Float( + compute="_compute_product_qty", + ) + + @api.depends("production_ids") + def _compute_product_qty(self): + for rec in self: + rec.product_qty = sum(rec.production_ids.mapped("product_qty")) + + product_ids = fields.Many2many( + comodel_name="product.product", + compute="_compute_product_ids", + string="Products", + ) + + def _compute_product_ids(self): + for rec in self: + rec.product_ids = rec.production_ids.mapped("product_id") + + def action_done(self): + self.ensure_one() + self.production_ids.with_context(batch_create=True).button_mark_done() + self.state = "done" + + def _get_common_action_view_production(self): + tree_view = self.env.ref("mrp.mrp_production_tree_view") + form_view = self.env.ref("mrp.mrp_production_form_view") + return { + "name": _("Detailed Operations"), + "type": "ir.actions.act_window", + "view_mode": "tree,form", + "res_model": "mrp.production", + "views": [(tree_view.id, "tree"), (form_view.id, "form")], + "view_id": tree_view.id, + } + + def action_view_production(self): + self.ensure_one() + action = self._get_common_action_view_production() + action["domain"] = [("id", "in", self.production_ids.ids)] + return action + + def action_view_production_pending(self): + self.ensure_one() + action = self._get_common_action_view_production() + action["domain"] = [ + ("id", "in", self.production_ids.ids), + ("state", "!=", "done"), + ] + return action diff --git a/mrp_production_batch/models/stock_move.py b/mrp_production_batch/models/stock_move.py new file mode 100644 index 000000000..5b47c7a5b --- /dev/null +++ b/mrp_production_batch/models/stock_move.py @@ -0,0 +1,28 @@ +# Copyright NuoBiT Solutions - Kilian Niubo +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) +from odoo import _, fields, models +from odoo.exceptions import ValidationError + + +class StockMove(models.Model): + _inherit = "stock.move" + + production_batch_id = fields.Many2one( + comodel_name="mrp.production.batch", + string="Batch Production", + readonly=True, + ) + + def mrp_production_batch_create_wizard_action(self): + model = self.env.context.get("active_model") + mrp_production_ids = self.env[model].browse(self.env.context.get("active_ids")) + if not mrp_production_ids: + raise ValidationError(_("No productions selected")) + self.env["mrp.production.batch"].create( + { + "creation_date": str(fields.Datetime.now()), + "production_ids": [ + (6, 0, mrp_production_ids.ids), + ], + } + ) diff --git a/mrp_production_batch/models/stock_picking.py b/mrp_production_batch/models/stock_picking.py new file mode 100644 index 000000000..9ebf7113a --- /dev/null +++ b/mrp_production_batch/models/stock_picking.py @@ -0,0 +1,78 @@ +# Part of Odoo. See LICENSE file for full copyright and licensing details. + + +from odoo import fields, models + + +class PickingType(models.Model): + _inherit = "stock.picking.type" + + mo_todo_wo_batch_count = fields.Integer( + string="Number of Manufacturing Orders to Process", + compute="_compute_mo_count", + ) + + def _compute_mo_count(self): + super()._get_mo_count() + for rec in self: + if rec.count_mo_todo: + domains = { + "count_mo_waiting": [("reservation_state", "=", "waiting")], + "count_mo_todo": [ + ("state", "in", ("confirmed", "draft", "progress", "to_close")) + ], + "count_mo_late": [ + ("date_planned_start", "<", fields.Date.today()), + ("state", "=", "confirmed"), + ], + } + data = self.env["mrp.production"].read_group( + domains["count_mo_todo"] + + [ + ("state", "not in", ("done", "cancel")), + ("picking_type_id", "in", self.ids), + ("production_batch_id", "=", False), + ], + ["picking_type_id"], + ["picking_type_id"], + ) + count = { + x["picking_type_id"] + and x["picking_type_id"][0]: x["picking_type_id_count"] + for x in data + } + rec.mo_todo_wo_batch_count = count.get(rec.id, 0) + else: + rec.mo_todo_wo_batch_count = False + + mo_batch_count = fields.Integer( + compute="_compute_mo_batch_count", + ) + + def _get_production_batch_ids(self): + domains = { + "count_mo_waiting": [("reservation_state", "=", "waiting")], + "count_mo_todo": [ + ("state", "in", ("confirmed", "draft", "progress", "to_close")) + ], + "count_mo_late": [ + ("date_planned_start", "<", fields.Date.today()), + ("state", "=", "confirmed"), + ], + } + return ( + self.env["mrp.production"] + .search( + domains["count_mo_todo"] + + [ + ("state", "not in", ("done", "cancel")), + ("picking_type_id", "in", self.ids), + ("production_batch_id", "!=", False), + ], + ) + .mapped("production_batch_id") + ) + + def _compute_mo_batch_count(self): + for rec in self: + rec.mo_batch_count = len(self._get_production_batch_ids()) or False diff --git a/mrp_production_batch/readme/CONTRIBUTORS.rst b/mrp_production_batch/readme/CONTRIBUTORS.rst new file mode 100644 index 000000000..7e22de318 --- /dev/null +++ b/mrp_production_batch/readme/CONTRIBUTORS.rst @@ -0,0 +1,3 @@ +* `NuoBiT `_: + + * Kilian Niubo diff --git a/mrp_production_batch/readme/DESCRIPTION.rst b/mrp_production_batch/readme/DESCRIPTION.rst new file mode 100644 index 000000000..f0f0f3969 --- /dev/null +++ b/mrp_production_batch/readme/DESCRIPTION.rst @@ -0,0 +1 @@ +* Added diff --git a/mrp_production_batch/security/ir.model.access.csv b/mrp_production_batch/security/ir.model.access.csv new file mode 100644 index 000000000..6c5853f22 --- /dev/null +++ b/mrp_production_batch/security/ir.model.access.csv @@ -0,0 +1,4 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_mrp_production_batch_manager,mrp.production.batch manager,model_mrp_production_batch,base.group_user,1,1,1,1 +access_mrp_production_batch_wizard_manager,mrp.production.batch.wizard manager,model_mrp_production_batch_wizard,base.group_user,1,1,1,1 +access_mrp_production_batch_line_wizard_manager,mrp.production.batch.line.wizard manager,model_mrp_production_batch_line_wizard,base.group_user,1,1,1,1 diff --git a/mrp_production_batch/static/description/icon.png b/mrp_production_batch/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..1cd641e792c30455187ca30940bc0f329ce8bbb0 GIT binary patch literal 6342 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 literal 0 HcmV?d00001 diff --git a/mrp_production_batch/static/description/index.html b/mrp_production_batch/static/description/index.html new file mode 100644 index 000000000..fe31f6551 --- /dev/null +++ b/mrp_production_batch/static/description/index.html @@ -0,0 +1,422 @@ + + + + + + +MRP Production Batch + + + +
+

MRP Production Batch

+ + +

Beta License: AGPL-3 NuoBiT/odoo-addons

+
    +
  • Added
  • +
+

Table of contents

+ +
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • NuoBiT Solutions
  • +
  • S.L.
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is part of the NuoBiT/odoo-addons project on GitHub.

+

You are welcome to contribute.

+
+
+
+ + diff --git a/mrp_production_batch/views/mrp_production_batch_views.xml b/mrp_production_batch/views/mrp_production_batch_views.xml new file mode 100644 index 000000000..b2abf1fb6 --- /dev/null +++ b/mrp_production_batch/views/mrp_production_batch_views.xml @@ -0,0 +1,102 @@ + + + + mrp.production.batch.tree + mrp.production.batch + + + + + + + + + + + + + + mrp.production.batch.form + mrp.production.batch + +
+
+
+ +
+ + +
+ + + + + + + +
+
+
+
+ + Manufacturing Orders + ir.actions.act_window + mrp.production.batch + tree,kanban,form + + [('production_ids.picking_type_id', '=', active_id)] + {'default_picking_type_id': active_id} + + + Batch Production + ir.actions.act_window + mrp.production.batch + tree,form + +

+ No Batch Production order found +

+

+ Batch production is used to group several production orders +

+
+
+
diff --git a/mrp_production_batch/views/mrp_production_views.xml b/mrp_production_batch/views/mrp_production_views.xml new file mode 100644 index 000000000..aa3384bc5 --- /dev/null +++ b/mrp_production_batch/views/mrp_production_views.xml @@ -0,0 +1,66 @@ + + + + + + mrp.production.tree.inherit + mrp.production + + + + + + + + + + mrp.production.form.inherit + mrp.production + + + + + +
+ +
+
+
+ + [('picking_type_id', '=', active_id), ('production_batch_id', '=', False)] + +
+
diff --git a/mrp_production_batch/views/stock_picking_views.xml b/mrp_production_batch/views/stock_picking_views.xml new file mode 100644 index 000000000..2304fba79 --- /dev/null +++ b/mrp_production_batch/views/stock_picking_views.xml @@ -0,0 +1,37 @@ + + + + stock.picking.type.kanban + stock.picking.type + + + + + + + + + + + 1 + + + + + + + diff --git a/mrp_production_batch/wizard/__init__.py b/mrp_production_batch/wizard/__init__.py new file mode 100644 index 000000000..0c5347b96 --- /dev/null +++ b/mrp_production_batch/wizard/__init__.py @@ -0,0 +1,2 @@ +from . import wizard_mrp_production_batch +from . import wizard_mrp_production_batch_line diff --git a/mrp_production_batch/wizard/wizard_mrp_production_batch.py b/mrp_production_batch/wizard/wizard_mrp_production_batch.py new file mode 100644 index 000000000..128d2358d --- /dev/null +++ b/mrp_production_batch/wizard/wizard_mrp_production_batch.py @@ -0,0 +1,28 @@ +# Copyright NuoBiT Solutions - Kilian Niubo +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) + +from odoo import fields, models + + +class MRPProductionBatchWizard(models.TransientModel): + _name = "mrp.production.batch.wizard" + _description = "MRP Production Batch wizard" + + manufacturing_ids = fields.One2many( + comodel_name="mrp.production.batch.line.wizard", + inverse_name="mrp_production_batch_id", + readonly=False, + store=True, + ) + + def action_mrp_production_batch_group(self): + self.ensure_one() + res = self.env["mrp.production.batch"].create( + { + "production_ids": [ + (6, 0, self.manufacturing_ids.ids), + ], + } + ) + for production in self.manufacturing_ids: + production.production_batch_id = res.id diff --git a/mrp_production_batch/wizard/wizard_mrp_production_batch.xml b/mrp_production_batch/wizard/wizard_mrp_production_batch.xml new file mode 100644 index 000000000..b414a97de --- /dev/null +++ b/mrp_production_batch/wizard/wizard_mrp_production_batch.xml @@ -0,0 +1,41 @@ + + + + + mrp.production.batch.wizard.form + mrp.production.batch.wizard + +
+
+ + + + + + +
+
+ + + + + Import partners + mrp.production.batch.wizard + form + new + + diff --git a/mrp_production_batch/wizard/wizard_mrp_production_batch_line.py b/mrp_production_batch/wizard/wizard_mrp_production_batch_line.py new file mode 100644 index 000000000..0adbe88ac --- /dev/null +++ b/mrp_production_batch/wizard/wizard_mrp_production_batch_line.py @@ -0,0 +1,22 @@ +# Copyright NuoBiT Solutions - Kilian Niubo +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) + +from odoo import fields, models + + +class MRPProductionBatchLineWizard(models.TransientModel): + _name = "mrp.production.batch.line.wizard" + _description = "MRP Production Line Batch wizard" + + mrp_production_batch_id = fields.Many2one( + comodel_name="mrp.production.batch.wizard", + required=True, + ondelete="cascade", + ) + production_id = fields.Many2one( + comodel_name="mrp.production", + ) + product_ids = fields.Many2many( + comodel_name="product.product", + string="Products", + ) diff --git a/setup/mrp_production_batch/odoo/addons/mrp_production_batch b/setup/mrp_production_batch/odoo/addons/mrp_production_batch new file mode 120000 index 000000000..f30289c48 --- /dev/null +++ b/setup/mrp_production_batch/odoo/addons/mrp_production_batch @@ -0,0 +1 @@ +../../../../mrp_production_batch \ No newline at end of file diff --git a/setup/mrp_production_batch/setup.py b/setup/mrp_production_batch/setup.py new file mode 100644 index 000000000..28c57bb64 --- /dev/null +++ b/setup/mrp_production_batch/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +) From c60f28e726cd06e848fb72edebd4980dc761d5b1 Mon Sep 17 00:00:00 2001 From: KNVx Date: Tue, 21 Nov 2023 15:25:45 +0100 Subject: [PATCH 02/21] [IMP] mrp_production_batch: new features + improved code --- mrp_production_batch/README.rst | 2 +- mrp_production_batch/__manifest__.py | 4 +- .../data/ir_sequence_data.xml | 14 -- mrp_production_batch/models/__init__.py | 5 +- mrp_production_batch/models/mrp_production.py | 94 ++++++--- .../models/mrp_production_batch.py | 51 +++-- mrp_production_batch/models/stock_move.py | 57 +++--- ...stock_picking.py => stock_picking_type.py} | 58 +++--- .../static/description/index.html | 2 +- .../views/mrp_production_batch_views.xml | 64 +++--- .../views/mrp_production_views.xml | 15 +- .../views/stock_picking_views.xml | 186 ++++++++++++++++-- mrp_production_batch/wizard/__init__.py | 4 +- ...py => mrp_production_batch_line_wizard.py} | 2 +- .../wizard/mrp_production_batch_wizard.py | 46 +++++ ...ch.xml => mrp_production_batch_wizard.xml} | 17 +- .../wizard/wizard_mrp_production_batch.py | 28 --- 17 files changed, 440 insertions(+), 209 deletions(-) delete mode 100644 mrp_production_batch/data/ir_sequence_data.xml rename mrp_production_batch/models/{stock_picking.py => stock_picking_type.py} (57%) rename mrp_production_batch/wizard/{wizard_mrp_production_batch_line.py => mrp_production_batch_line_wizard.py} (92%) create mode 100644 mrp_production_batch/wizard/mrp_production_batch_wizard.py rename mrp_production_batch/wizard/{wizard_mrp_production_batch.xml => mrp_production_batch_wizard.xml} (76%) delete mode 100644 mrp_production_batch/wizard/wizard_mrp_production_batch.py diff --git a/mrp_production_batch/README.rst b/mrp_production_batch/README.rst index 2d1b93e23..fc202c230 100644 --- a/mrp_production_batch/README.rst +++ b/mrp_production_batch/README.rst @@ -7,7 +7,7 @@ MRP Production Batch !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! source digest: sha256:230afdff2552dd582a6157902bb10a837c066ebf7b5fea6caffc644f8e8bc76c + !! source digest: sha256:1924a00a7a430ea70dddb0afa4f5f677fbd5550307a54be384c8a79ddf87faf1 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png diff --git a/mrp_production_batch/__manifest__.py b/mrp_production_batch/__manifest__.py index 11e905abe..baf0f9a46 100644 --- a/mrp_production_batch/__manifest__.py +++ b/mrp_production_batch/__manifest__.py @@ -13,10 +13,10 @@ "license": "AGPL-3", "data": [ "security/ir.model.access.csv", - "data/ir_sequence_data.xml", + # "data/ir_sequence_data.xml", "views/mrp_production_batch_views.xml", "views/mrp_production_views.xml", "views/stock_picking_views.xml", - "wizard/wizard_mrp_production_batch.xml", + "wizard/mrp_production_batch_wizard.xml", ], } diff --git a/mrp_production_batch/data/ir_sequence_data.xml b/mrp_production_batch/data/ir_sequence_data.xml deleted file mode 100644 index 61f827d0f..000000000 --- a/mrp_production_batch/data/ir_sequence_data.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - MRP Production Batch - mrp.production.batch - MOB/ - 5 - - - diff --git a/mrp_production_batch/models/__init__.py b/mrp_production_batch/models/__init__.py index 667931bd5..42b39e3b4 100644 --- a/mrp_production_batch/models/__init__.py +++ b/mrp_production_batch/models/__init__.py @@ -1,4 +1,5 @@ from . import mrp_production from . import mrp_production_batch -from . import stock_move -from . import stock_picking + +# from . import stock_move +from . import stock_picking_type diff --git a/mrp_production_batch/models/mrp_production.py b/mrp_production_batch/models/mrp_production.py index 6528f92bc..3ee93ff62 100644 --- a/mrp_production_batch/models/mrp_production.py +++ b/mrp_production_batch/models/mrp_production.py @@ -10,23 +10,30 @@ class MrpProduction(models.Model): production_batch_id = fields.Many2one( comodel_name="mrp.production.batch", string="Production Batch", + ondelete="restrict", readonly=True, ) - def _check_production_to_batch_consitency(self, mrp_production_ids): - if not mrp_production_ids: + def _check_production_to_batch_consistency(self, mrp_productions): + if not mrp_productions: raise ValidationError(_("No productions selected")) - if mrp_production_ids.mapped("production_batch_id"): + if mrp_productions.production_batch_id: raise ValidationError( _("Some of the selected productions already have a batch") ) - if any( - state in ("done", "cancel") for state in mrp_production_ids.mapped("state") - ): + if {"done", "cancel"} & set(mrp_productions.mapped("state")): raise ValidationError( _("Some of the selected productions are already done or cancelled") ) - picking_type_ids = mrp_production_ids.mapped("picking_type_id") + if len(mrp_productions.mapped("picking_type_id")) > 1: + raise ValidationError( + _("Some of the selected productions have different operation types") + ) + if len(mrp_productions.mapped("picking_type_id").mapped("warehouse_id")) > 1: + raise ValidationError( + _("Some of the selected productions have different warehouses") + ) + picking_type_ids = mrp_productions.picking_type_id if len(picking_type_ids) > 1: raise ValidationError( _( @@ -38,21 +45,59 @@ def _check_production_to_batch_consitency(self, mrp_production_ids): def mrp_production_batch_create_wizard_action(self): model = self.env.context.get("active_model") mrp_production_ids = self.env[model].browse(self.env.context.get("active_ids")) - self._check_production_to_batch_consitency(mrp_production_ids) - self.env["mrp.production.batch"].create( + self._check_production_to_batch_consistency(mrp_production_ids) + ctx = dict(self.env.context, active_ids=self.ids) + + view_form = self.env.ref( + "mrp_production_batch.wizard_mrp_production_batch_view_form" + ) + res_id = self.env["mrp.production.batch.wizard"].create( { - "creation_date": str(fields.Datetime.now()), - "production_ids": [ - (6, 0, mrp_production_ids.ids), - ], + "warehouse_id": mrp_production_ids.mapped("picking_type_id") + .mapped("warehouse_id") + .id, } ) + res = { + "name": _("MRP production Batch"), + "view_mode": "form", + "res_model": "mrp.production.batch.wizard", + "res_id": res_id.id, + "target": "new", + "views": [(view_form.id, "form")], + "view_id": view_form.id, + "type": "ir.actions.act_window", + "context": ctx, + } + return res + + def _action_generate_consumption_wizard(self, consumption_issues): + if not self.env.context.get("mrp_production_batch_create"): + return super()._action_generate_consumption_wizard(consumption_issues) + else: + raise ValidationError( + _( + "Production %s have not recorded produced quantities yet." + % self.mapped("name") + ) + ) + + def _action_generate_immediate_wizard(self): + if not self.env.context.get("mrp_production_batch_create"): + return super()._action_generate_immediate_wizard() + else: + raise ValidationError( + _( + "Production %s have not recorded produced quantities yet." + % self.mapped("name") + ) + ) @api.constrains("state") def _check_state_batch_creation(self): for rec in self: - if rec.state == "cancel": - if rec.production_batch_id: + if rec.production_batch_id: + if rec.state == "cancel": raise ValidationError( _( "You can't cancel a production that belongs to a batch %s. " @@ -60,17 +105,18 @@ def _check_state_batch_creation(self): ) % rec.production_batch_id.name ) - elif rec.state == "done": - if rec.production_batch_id and not self.env.context.get("batch_create"): - raise ValidationError( - _( - "You can't change the state of a production %s " - "because it belongs to a batch: %s. \n " - "It must be processed from the batch." + elif rec.state == "done": + if not self.env.context.get("mrp_production_batch_create"): + raise ValidationError( + _( + "You can't change the state of a production %s " + "because it belongs to a batch: %s. \n " + "It must be processed from the batch." + ) + % (rec.name, rec.production_batch_id.name) ) - % (rec.name, rec.production_batch_id.name) - ) + # TODO: xml action def action_view_production_batch(self): self.ensure_one() view = self.env.ref("mrp_production_batch.mrp_production_batch_form_view") diff --git a/mrp_production_batch/models/mrp_production_batch.py b/mrp_production_batch/models/mrp_production_batch.py index 96c36f863..8631c61c1 100644 --- a/mrp_production_batch/models/mrp_production_batch.py +++ b/mrp_production_batch/models/mrp_production_batch.py @@ -6,38 +6,47 @@ class MrpProductionBatch(models.Model): _name = "mrp.production.batch" - @api.model - def _default_name(self): - return self.env["ir.sequence"].next_by_code("mrp.production.batch") - name = fields.Char( - default=_default_name, readonly=True, + required=True, ) production_ids = fields.One2many( comodel_name="mrp.production", inverse_name="production_batch_id", string="Manufacturing Orders", ) - production_qty = fields.Integer( - compute="_compute_production_qty", + production_wo_lot_producing_id = fields.One2many( + comodel_name="mrp.production", + inverse_name="production_batch_id", + compute="_compute_production_wo_lot_producing_id", + ) + + @api.depends("production_ids.lot_producing_id") + def _compute_production_wo_lot_producing_id(self): + for rec in self: + rec.production_wo_lot_producing_id = rec.production_ids.filtered( + lambda x: not x.lot_producing_id + ) + + production_count = fields.Integer( + compute="_compute_production_count", ) - def _compute_production_qty(self): + def _compute_production_count(self): for rec in self: - rec.production_qty = len(rec.production_ids) + rec.production_count = len(rec.production_ids) - pending_production_qty = fields.Integer( - compute="_compute_pending_production_qty", + pending_production_count = fields.Integer( + compute="_compute_pending_production_count", ) - def _compute_pending_production_qty(self): + def _compute_pending_production_count(self): for rec in self: - rec.pending_production_qty = len( + rec.pending_production_count = len( rec.production_ids.filtered(lambda r: r.state != "done") ) - creation_date = fields.Datetime( + creation_date = fields.Date( string="Creation Date", ) state = fields.Selection( @@ -47,6 +56,11 @@ def _compute_pending_production_qty(self): ], default="draft", ) + operation_type = fields.Many2one( + comodel_name="stock.picking.type", + required=True, + readonly=True, + ) product_qty = fields.Float( compute="_compute_product_qty", ) @@ -68,7 +82,9 @@ def _compute_product_ids(self): def action_done(self): self.ensure_one() - self.production_ids.with_context(batch_create=True).button_mark_done() + self.production_ids.with_context( + mrp_production_batch_create=True + ).button_mark_done() self.state = "done" def _get_common_action_view_production(self): @@ -97,3 +113,8 @@ def action_view_production_pending(self): ("state", "!=", "done"), ] return action + + def action_generate_serial(self): + for rec in self: + for production in rec.production_wo_lot_producing_id: + production.action_generate_serial() diff --git a/mrp_production_batch/models/stock_move.py b/mrp_production_batch/models/stock_move.py index 5b47c7a5b..eb205b74d 100644 --- a/mrp_production_batch/models/stock_move.py +++ b/mrp_production_batch/models/stock_move.py @@ -1,28 +1,29 @@ -# Copyright NuoBiT Solutions - Kilian Niubo -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) -from odoo import _, fields, models -from odoo.exceptions import ValidationError - - -class StockMove(models.Model): - _inherit = "stock.move" - - production_batch_id = fields.Many2one( - comodel_name="mrp.production.batch", - string="Batch Production", - readonly=True, - ) - - def mrp_production_batch_create_wizard_action(self): - model = self.env.context.get("active_model") - mrp_production_ids = self.env[model].browse(self.env.context.get("active_ids")) - if not mrp_production_ids: - raise ValidationError(_("No productions selected")) - self.env["mrp.production.batch"].create( - { - "creation_date": str(fields.Datetime.now()), - "production_ids": [ - (6, 0, mrp_production_ids.ids), - ], - } - ) +# # # Copyright NuoBiT Solutions - Kilian Niubo +# # # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) +# from odoo import _, fields, models +# from odoo.exceptions import ValidationError +# +# +# class StockMove(models.Model): +# _inherit = "stock.move" +# +# production_batch_id = fields.Many2one( +# comodel_name="mrp.production.batch", +# string="Batch Production", +# readonly=True, +# ondelete="restrict", +# ) +# +# def mrp_production_batch_create_wizard_action(self): +# model = self.env.context.get("active_model") +# mrp_productions = self.env[model].browse(self.env.context.get("active_ids")) +# if not mrp_productions: +# raise ValidationError(_("No productions selected")) +# self.env["mrp.production.batch"].create( +# { +# "creation_date": str(fields.Datetime.now()), +# "production_ids": [ +# (6, 0, mrp_productions.ids), +# ], +# } +# ) diff --git a/mrp_production_batch/models/stock_picking.py b/mrp_production_batch/models/stock_picking_type.py similarity index 57% rename from mrp_production_batch/models/stock_picking.py rename to mrp_production_batch/models/stock_picking_type.py index 9ebf7113a..90be6be27 100644 --- a/mrp_production_batch/models/stock_picking.py +++ b/mrp_production_batch/models/stock_picking_type.py @@ -1,13 +1,19 @@ -# Part of Odoo. See LICENSE file for full copyright and licensing details. +# Copyright NuoBiT Solutions - Kilian Niubo +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) from odoo import fields, models -class PickingType(models.Model): +class StockPickingType(models.Model): _inherit = "stock.picking.type" - mo_todo_wo_batch_count = fields.Integer( + code = fields.Selection( + selection_add=[("mrp_operation_batch", "Manufacturing Batch")], + ondelete={"mrp_operation_batch": "cascade"}, + ) + + count_mo_todo_wo_batch = fields.Integer( string="Number of Manufacturing Orders to Process", compute="_compute_mo_count", ) @@ -41,38 +47,30 @@ def _compute_mo_count(self): and x["picking_type_id"][0]: x["picking_type_id_count"] for x in data } - rec.mo_todo_wo_batch_count = count.get(rec.id, 0) + rec.count_mo_todo_wo_batch = count.get(rec.id, 0) else: - rec.mo_todo_wo_batch_count = False + rec.count_mo_todo_wo_batch = False + mo_batches = fields.One2many( + comodel_name="mrp.production.batch", + inverse_name="operation_type", + ) mo_batch_count = fields.Integer( compute="_compute_mo_batch_count", ) - def _get_production_batch_ids(self): - domains = { - "count_mo_waiting": [("reservation_state", "=", "waiting")], - "count_mo_todo": [ - ("state", "in", ("confirmed", "draft", "progress", "to_close")) - ], - "count_mo_late": [ - ("date_planned_start", "<", fields.Date.today()), - ("state", "=", "confirmed"), - ], - } - return ( - self.env["mrp.production"] - .search( - domains["count_mo_todo"] - + [ - ("state", "not in", ("done", "cancel")), - ("picking_type_id", "in", self.ids), - ("production_batch_id", "!=", False), - ], - ) - .mapped("production_batch_id") - ) - def _compute_mo_batch_count(self): for rec in self: - rec.mo_batch_count = len(self._get_production_batch_ids()) or False + rec.mo_batch_count = len(rec.mo_batches) or False + + def mrp_production_batch_action(self): + tree_view = self.env.ref("mrp_production_batch.mrp_production_batch_tree_view") + return { + "name": ("Detailed Operations"), + "type": "ir.actions.act_window", + "view_mode": "tree", + "res_model": "mrp.production.batch", + "views": [(tree_view.id, "tree")], + "view_id": tree_view.id, + "domain": [("id", "in", self.mo_batches.ids)], + } diff --git a/mrp_production_batch/static/description/index.html b/mrp_production_batch/static/description/index.html index fe31f6551..746120282 100644 --- a/mrp_production_batch/static/description/index.html +++ b/mrp_production_batch/static/description/index.html @@ -367,7 +367,7 @@

MRP Production Batch

!! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -!! source digest: sha256:230afdff2552dd582a6157902bb10a837c066ebf7b5fea6caffc644f8e8bc76c +!! source digest: sha256:1924a00a7a430ea70dddb0afa4f5f677fbd5550307a54be384c8a79ddf87faf1 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->

Beta License: AGPL-3 NuoBiT/odoo-addons

    diff --git a/mrp_production_batch/views/mrp_production_batch_views.xml b/mrp_production_batch/views/mrp_production_batch_views.xml index b2abf1fb6..cd9a5556d 100644 --- a/mrp_production_batch/views/mrp_production_batch_views.xml +++ b/mrp_production_batch/views/mrp_production_batch_views.xml @@ -19,15 +19,23 @@ mrp.production.batch.form mrp.production.batch -
    +
    +
    @@ -41,50 +49,43 @@ attrs="{'invisible': [('production_ids', '=', False)]}" > - -
- - + + + + + + + +
- - Manufacturing Orders - ir.actions.act_window - mrp.production.batch - tree,kanban,form - - Manufacturing Orders + ir.actions.act_window + mrp.production.batch + tree,kanban,form + + [('production_ids.picking_type_id', '=', active_id)] - {'default_picking_type_id': active_id} - + {'default_picking_type_id': active_id} + Batch Production ir.actions.act_window @@ -99,4 +100,9 @@

+ + Invoice batches + mrp.production.batch + tree,form +
diff --git a/mrp_production_batch/views/mrp_production_views.xml b/mrp_production_batch/views/mrp_production_views.xml index aa3384bc5..edc992a62 100644 --- a/mrp_production_batch/views/mrp_production_views.xml +++ b/mrp_production_batch/views/mrp_production_views.xml @@ -2,13 +2,13 @@ - + mrp.production.tree.inherit mrp.production @@ -31,12 +31,11 @@ mrp.production - - - + + + + +
+ + + + +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ + + + + + - + 1 - - -
diff --git a/mrp_production_batch/wizard/__init__.py b/mrp_production_batch/wizard/__init__.py index 0c5347b96..52bdd45ca 100644 --- a/mrp_production_batch/wizard/__init__.py +++ b/mrp_production_batch/wizard/__init__.py @@ -1,2 +1,2 @@ -from . import wizard_mrp_production_batch -from . import wizard_mrp_production_batch_line +from . import mrp_production_batch_wizard +from . import mrp_production_batch_line_wizard diff --git a/mrp_production_batch/wizard/wizard_mrp_production_batch_line.py b/mrp_production_batch/wizard/mrp_production_batch_line_wizard.py similarity index 92% rename from mrp_production_batch/wizard/wizard_mrp_production_batch_line.py rename to mrp_production_batch/wizard/mrp_production_batch_line_wizard.py index 0adbe88ac..9b6602a9a 100644 --- a/mrp_production_batch/wizard/wizard_mrp_production_batch_line.py +++ b/mrp_production_batch/wizard/mrp_production_batch_line_wizard.py @@ -8,7 +8,7 @@ class MRPProductionBatchLineWizard(models.TransientModel): _name = "mrp.production.batch.line.wizard" _description = "MRP Production Line Batch wizard" - mrp_production_batch_id = fields.Many2one( + production_batch_wizard_id = fields.Many2one( comodel_name="mrp.production.batch.wizard", required=True, ondelete="cascade", diff --git a/mrp_production_batch/wizard/mrp_production_batch_wizard.py b/mrp_production_batch/wizard/mrp_production_batch_wizard.py new file mode 100644 index 000000000..ebdcfbed9 --- /dev/null +++ b/mrp_production_batch/wizard/mrp_production_batch_wizard.py @@ -0,0 +1,46 @@ +# Copyright NuoBiT Solutions - Kilian Niubo +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) + +from odoo import fields, models + + +class MRPProductionBatchWizard(models.TransientModel): + _name = "mrp.production.batch.wizard" + _description = "MRP Production Batch wizard" + + production_ids = fields.One2many( + comodel_name="mrp.production.batch.line.wizard", + inverse_name="production_batch_wizard_id", + ) + operation_type = fields.Many2one( + comodel_name="stock.picking.type", + ) + warehouse_id = fields.Many2one( + comodel_name="stock.warehouse", + ) + + def action_mrp_production_batch_group(self): + self.ensure_one() + model = self.env.context.get("active_model") + mrp_production_ids = self.env[model].browse(self.env.context.get("active_ids")) + production_batch = self.env["mrp.production.batch"].create( + { + "name": self.operation_type.sequence_id._next(), + "creation_date": fields.Datetime.now(), + "production_ids": [ + (6, 0, mrp_production_ids.ids), + ], + "operation_type": self.operation_type.id, + } + ) + action = self.env["ir.actions.act_window"]._for_xml_id( + "mrp_production_batch.mrp_production_batch_action" + ) + action["views"] = [ + ( + self.env.ref("mrp_production_batch.mrp_production_batch_form_view").id, + "form", + ) + ] + action["res_id"] = production_batch.id + return action diff --git a/mrp_production_batch/wizard/wizard_mrp_production_batch.xml b/mrp_production_batch/wizard/mrp_production_batch_wizard.xml similarity index 76% rename from mrp_production_batch/wizard/wizard_mrp_production_batch.xml rename to mrp_production_batch/wizard/mrp_production_batch_wizard.xml index b414a97de..a7fb0f353 100644 --- a/mrp_production_batch/wizard/wizard_mrp_production_batch.xml +++ b/mrp_production_batch/wizard/mrp_production_batch_wizard.xml @@ -6,18 +6,19 @@ mrp.production.batch.wizard.form mrp.production.batch.wizard -
+
- - - - - - + + + +
+ + +
diff --git a/mrp_production_batch/views/mrp_production_views.xml b/mrp_production_batch/views/mrp_production_views.xml index edc992a62..1074bd84b 100644 --- a/mrp_production_batch/views/mrp_production_views.xml +++ b/mrp_production_batch/views/mrp_production_views.xml @@ -33,7 +33,12 @@ - + + +
From 6eb73fe85d2fb94a9dface89784597545e8c8507 Mon Sep 17 00:00:00 2001 From: FrankC013 Date: Thu, 14 Dec 2023 17:46:58 +0100 Subject: [PATCH 04/21] [IMP] mrp_production_batch: code reviews --- mrp_production_batch/README.rst | 6 ++-- mrp_production_batch/__manifest__.py | 4 +-- mrp_production_batch/models/mrp_production.py | 4 +-- .../models/mrp_production_batch.py | 10 ++++--- mrp_production_batch/models/stock_move.py | 29 ------------------- mrp_production_batch/readme/CONTRIBUTORS.rst | 1 + .../static/description/index.html | 4 +-- 7 files changed, 15 insertions(+), 43 deletions(-) delete mode 100644 mrp_production_batch/models/stock_move.py diff --git a/mrp_production_batch/README.rst b/mrp_production_batch/README.rst index fc202c230..7acc3ae06 100644 --- a/mrp_production_batch/README.rst +++ b/mrp_production_batch/README.rst @@ -2,12 +2,12 @@ MRP Production Batch ==================== -.. +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! source digest: sha256:1924a00a7a430ea70dddb0afa4f5f677fbd5550307a54be384c8a79ddf87faf1 + !! source digest: sha256:f8930a819af69ed12083e16e4aad92d80f4f3c8ae272e327418c18ca6fc9768b !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png @@ -46,7 +46,6 @@ Authors ~~~~~~~ * NuoBiT Solutions -* S.L. Contributors ~~~~~~~~~~~~ @@ -54,6 +53,7 @@ Contributors * `NuoBiT `_: * Kilian Niubo + * Frank Cespedes Maintainers ~~~~~~~~~~~ diff --git a/mrp_production_batch/__manifest__.py b/mrp_production_batch/__manifest__.py index baf0f9a46..1bb155405 100644 --- a/mrp_production_batch/__manifest__.py +++ b/mrp_production_batch/__manifest__.py @@ -5,15 +5,13 @@ "name": "MRP Production Batch", "summary": "Customizations for Oxigen in MRP Production", "version": "14.0.1.0.0", - "author": "NuoBiT Solutions, S.L.", + "author": "NuoBiT Solutions", "website": "https://github.com/nuobit/odoo-addons", "category": "Manufacturing/Manufacturing", "depends": ["mrp"], - "installable": True, "license": "AGPL-3", "data": [ "security/ir.model.access.csv", - # "data/ir_sequence_data.xml", "views/mrp_production_batch_views.xml", "views/mrp_production_views.xml", "views/stock_picking_views.xml", diff --git a/mrp_production_batch/models/mrp_production.py b/mrp_production_batch/models/mrp_production.py index ae47a4867..10ce5aeb8 100644 --- a/mrp_production_batch/models/mrp_production.py +++ b/mrp_production_batch/models/mrp_production.py @@ -25,11 +25,11 @@ def _check_production_to_batch_consistency(self, mrp_productions): raise ValidationError( _("Some of the selected productions are already done or cancelled") ) - if len(mrp_productions.mapped("picking_type_id")) > 1: + if len(mrp_productions.picking_type_id) > 1: raise ValidationError( _("Some of the selected productions have different operation types") ) - if len(mrp_productions.mapped("picking_type_id").mapped("warehouse_id")) > 1: + if len(mrp_productions.picking_type_id.warehouse_id) > 1: raise ValidationError( _("Some of the selected productions have different warehouses") ) diff --git a/mrp_production_batch/models/mrp_production_batch.py b/mrp_production_batch/models/mrp_production_batch.py index e51929569..e773b8516 100644 --- a/mrp_production_batch/models/mrp_production_batch.py +++ b/mrp_production_batch/models/mrp_production_batch.py @@ -3,7 +3,7 @@ import logging from odoo import _, api, fields, models -from odoo.exceptions import UserError +from odoo.exceptions import UserError, ValidationError _logger = logging.getLogger(__name__) @@ -120,11 +120,13 @@ def _compute_product_qty(self): def _compute_product_ids(self): for rec in self: - rec.product_ids = rec.production_ids.mapped("product_id") + rec.product_ids = rec.production_ids.product_id def action_done(self): self.ensure_one() - productions = self.production_ids.filtered(lambda r: r.state != "done") + productions = self.production_ids.filtered( + lambda r: r.state not in ("cancel", "done") + ) len_production = len(productions) productions_display_name = [] for production in productions: @@ -132,7 +134,7 @@ def action_done(self): production.with_context( mrp_production_batch_create=True ).button_mark_done() - except Exception: + except (ValidationError, UserError): productions_display_name.append(production.display_name) if productions_display_name and len(productions_display_name) == len_production: message = "The following productions could not be marked as 'done':\n" diff --git a/mrp_production_batch/models/stock_move.py b/mrp_production_batch/models/stock_move.py deleted file mode 100644 index eb205b74d..000000000 --- a/mrp_production_batch/models/stock_move.py +++ /dev/null @@ -1,29 +0,0 @@ -# # # Copyright NuoBiT Solutions - Kilian Niubo -# # # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) -# from odoo import _, fields, models -# from odoo.exceptions import ValidationError -# -# -# class StockMove(models.Model): -# _inherit = "stock.move" -# -# production_batch_id = fields.Many2one( -# comodel_name="mrp.production.batch", -# string="Batch Production", -# readonly=True, -# ondelete="restrict", -# ) -# -# def mrp_production_batch_create_wizard_action(self): -# model = self.env.context.get("active_model") -# mrp_productions = self.env[model].browse(self.env.context.get("active_ids")) -# if not mrp_productions: -# raise ValidationError(_("No productions selected")) -# self.env["mrp.production.batch"].create( -# { -# "creation_date": str(fields.Datetime.now()), -# "production_ids": [ -# (6, 0, mrp_productions.ids), -# ], -# } -# ) diff --git a/mrp_production_batch/readme/CONTRIBUTORS.rst b/mrp_production_batch/readme/CONTRIBUTORS.rst index 7e22de318..5c0d390af 100644 --- a/mrp_production_batch/readme/CONTRIBUTORS.rst +++ b/mrp_production_batch/readme/CONTRIBUTORS.rst @@ -1,3 +1,4 @@ * `NuoBiT `_: * Kilian Niubo + * Frank Cespedes diff --git a/mrp_production_batch/static/description/index.html b/mrp_production_batch/static/description/index.html index 746120282..c8a583a30 100644 --- a/mrp_production_batch/static/description/index.html +++ b/mrp_production_batch/static/description/index.html @@ -367,7 +367,7 @@

MRP Production Batch

!! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -!! source digest: sha256:1924a00a7a430ea70dddb0afa4f5f677fbd5550307a54be384c8a79ddf87faf1 +!! source digest: sha256:f8930a819af69ed12083e16e4aad92d80f4f3c8ae272e327418c18ca6fc9768b !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->

Beta License: AGPL-3 NuoBiT/odoo-addons

@@ -407,6 +406,7 @@

Contributors

From d8ee3a8cf9f4a97c1ce7c5328a9b078b5bb1c08d Mon Sep 17 00:00:00 2001 From: FrankC013 Date: Mon, 18 Dec 2023 10:05:14 +0100 Subject: [PATCH 05/21] [FIX] mrp_production_batch: Fix to allow the dashboard's tree view to open forms. --- .../models/stock_picking_type.py | 5 +- .../views/stock_picking_views.xml | 55 ++++++++++++------- 2 files changed, 37 insertions(+), 23 deletions(-) diff --git a/mrp_production_batch/models/stock_picking_type.py b/mrp_production_batch/models/stock_picking_type.py index 90be6be27..4cb68cb1d 100644 --- a/mrp_production_batch/models/stock_picking_type.py +++ b/mrp_production_batch/models/stock_picking_type.py @@ -65,12 +65,13 @@ def _compute_mo_batch_count(self): def mrp_production_batch_action(self): tree_view = self.env.ref("mrp_production_batch.mrp_production_batch_tree_view") + form_view = self.env.ref("mrp_production_batch.mrp_production_batch_form_view") return { "name": ("Detailed Operations"), "type": "ir.actions.act_window", - "view_mode": "tree", + "view_mode": "tree,form", "res_model": "mrp.production.batch", - "views": [(tree_view.id, "tree")], + "views": [(tree_view.id, "tree"), (form_view.id, "form")], "view_id": tree_view.id, "domain": [("id", "in", self.mo_batches.ids)], } diff --git a/mrp_production_batch/views/stock_picking_views.xml b/mrp_production_batch/views/stock_picking_views.xml index 378293b0e..50ea90f1a 100644 --- a/mrp_production_batch/views/stock_picking_views.xml +++ b/mrp_production_batch/views/stock_picking_views.xml @@ -25,26 +25,30 @@
- -
+ + +
+
+ /> +
- + + /> +
- - + + To Process + + @@ -105,7 +111,8 @@
-
+
In Progress + > + In Progress +
Planned + > + Planned +
- - From daf75f2d4bb4cdc1f9d168ac6623fdd337766594 Mon Sep 17 00:00:00 2001 From: FrankC013 Date: Mon, 18 Dec 2023 10:59:41 +0100 Subject: [PATCH 06/21] [FIX] mrp_production_batch: Fix to Allow Tree View to Open When Clicking on Picking Type --- mrp_production_batch/models/stock_picking_type.py | 8 ++++++++ mrp_production_batch/views/mrp_production_batch_views.xml | 6 ++---- mrp_production_batch/views/stock_picking_views.xml | 2 +- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/mrp_production_batch/models/stock_picking_type.py b/mrp_production_batch/models/stock_picking_type.py index 4cb68cb1d..cb431453f 100644 --- a/mrp_production_batch/models/stock_picking_type.py +++ b/mrp_production_batch/models/stock_picking_type.py @@ -63,6 +63,14 @@ def _compute_mo_batch_count(self): for rec in self: rec.mo_batch_count = len(rec.mo_batches) or False + def get_mrp_production_batch_stock_picking_action_picking_type(self): + action = self.env["ir.actions.actions"]._for_xml_id( + "mrp_production_batch.mrp_production_batch_action_picking_dashboard" + ) + if self: + action["display_name"] = self.display_name + return action + def mrp_production_batch_action(self): tree_view = self.env.ref("mrp_production_batch.mrp_production_batch_tree_view") form_view = self.env.ref("mrp_production_batch.mrp_production_batch_form_view") diff --git a/mrp_production_batch/views/mrp_production_batch_views.xml b/mrp_production_batch/views/mrp_production_batch_views.xml index 637952ee0..fc2a52b2a 100644 --- a/mrp_production_batch/views/mrp_production_batch_views.xml +++ b/mrp_production_batch/views/mrp_production_batch_views.xml @@ -120,9 +120,7 @@ mrp.production.batch tree,kanban,form - [('production_ids.picking_type_id', '=', active_id)] + [('operation_type', '=', active_id)] {'default_picking_type_id': active_id} @@ -139,7 +137,7 @@

- + Invoice batches mrp.production.batch tree,form diff --git a/mrp_production_batch/views/stock_picking_views.xml b/mrp_production_batch/views/stock_picking_views.xml index 50ea90f1a..943c0d91a 100644 --- a/mrp_production_batch/views/stock_picking_views.xml +++ b/mrp_production_batch/views/stock_picking_views.xml @@ -20,7 +20,7 @@
From 7358f057032a779d0483140dac4f4d2ce75e20b3 Mon Sep 17 00:00:00 2001 From: FrankC013 Date: Thu, 21 Dec 2023 18:03:11 +0100 Subject: [PATCH 07/21] [IMP] mrp_production_batch: add buttons to review/ready in batch & manage error messages in production --- mrp_production_batch/README.rst | 4 +- mrp_production_batch/i18n/es.po | 130 +++++++++++++----- mrp_production_batch/models/mrp_production.py | 35 ++++- .../models/mrp_production_batch.py | 100 +++++++++----- .../models/stock_picking_type.py | 42 ++++-- .../static/description/index.html | 2 +- .../views/mrp_production_batch_views.xml | 48 +++++-- .../views/mrp_production_views.xml | 52 +++++++ .../views/stock_picking_views.xml | 51 ++----- 9 files changed, 332 insertions(+), 132 deletions(-) diff --git a/mrp_production_batch/README.rst b/mrp_production_batch/README.rst index 7acc3ae06..ddece05fb 100644 --- a/mrp_production_batch/README.rst +++ b/mrp_production_batch/README.rst @@ -2,12 +2,12 @@ MRP Production Batch ==================== -.. +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! source digest: sha256:f8930a819af69ed12083e16e4aad92d80f4f3c8ae272e327418c18ca6fc9768b + !! source digest: sha256:700bba545c72b4ff4d40b265cfbea8d46b2552a01a76ce668c2f6e033444f228 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png diff --git a/mrp_production_batch/i18n/es.po b/mrp_production_batch/i18n/es.po index 9ee3ff80e..be0d67fc0 100644 --- a/mrp_production_batch/i18n/es.po +++ b/mrp_production_batch/i18n/es.po @@ -6,8 +6,8 @@ msgid "" msgstr "" "Project-Id-Version: Odoo Server 14.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-12-12 10:45+0000\n" -"PO-Revision-Date: 2023-12-12 10:45+0000\n" +"POT-Creation-Date: 2023-12-21 15:59+0000\n" +"PO-Revision-Date: 2023-12-21 15:59+0000\n" "Last-Translator: \n" "Language-Team: \n" "MIME-Version: 1.0\n" @@ -42,6 +42,7 @@ msgstr "Todo" #. module: mrp_production_batch #: model:ir.actions.act_window,name:mrp_production_batch.mrp_production_batch +#: model:ir.actions.act_window,name:mrp_production_batch.mrp_production_batch_form_action #: model_terms:ir.ui.view,arch_db:mrp_production_batch.mrp_production_tree_view msgid "Batch Production" msgstr "Lote de Producción" @@ -49,7 +50,9 @@ msgstr "Lote de Producción" #. module: mrp_production_batch #: model_terms:ir.actions.act_window,help:mrp_production_batch.mrp_production_batch msgid "Batch production is used to group several production orders" -msgstr "La producción por lotes se utiliza para agrupar varias órdenes de producción." +msgstr "" +"La producción por lotes se utiliza para agrupar varias órdenes de " +"producción." #. module: mrp_production_batch #: model_terms:ir.ui.view,arch_db:mrp_production_batch.wizard_mrp_production_batch_view_form @@ -66,6 +69,16 @@ msgstr "Cancelado" msgid "Cancelled Production Count" msgstr "Conteo de Producción Cancelada" +#. module: mrp_production_batch +#: model_terms:ir.ui.view,arch_db:mrp_production_batch.mrp_production_form_view +msgid "Check Production" +msgstr "Verificar Producción" + +#. module: mrp_production_batch +#: model_terms:ir.ui.view,arch_db:mrp_production_batch.mrp_production_batch_form_view +msgid "Check Productions" +msgstr "Verificar Producciones" + #. module: mrp_production_batch #: model_terms:ir.ui.view,arch_db:mrp_production_batch.stock_production_type_kanban2 msgid "Configuration" @@ -123,15 +136,9 @@ msgstr "Nombre mostrado" #. module: mrp_production_batch #: model:ir.model.fields.selection,name:mrp_production_batch.selection__mrp_production_batch__state__done -#: model_terms:ir.ui.view,arch_db:mrp_production_batch.mrp_production_batch_form_view msgid "Done" msgstr "Hecho" -#. module: mrp_production_batch -#: model:ir.model.fields,field_description:mrp_production_batch.field_mrp_production_batch__done_production_count -msgid "Done Production Count" -msgstr "Conteo de Producción Hecha" - #. module: mrp_production_batch #: model:ir.model.fields.selection,name:mrp_production_batch.selection__mrp_production_batch__state__draft msgid "Draft" @@ -159,6 +166,7 @@ msgstr "Importar socios" #. module: mrp_production_batch #: model:ir.model.fields.selection,name:mrp_production_batch.selection__mrp_production_batch__state__in_progress #: model_terms:ir.ui.view,arch_db:mrp_production_batch.stock_production_type_kanban2 +#: model_terms:ir.ui.view,arch_db:mrp_production_batch.view_mrp_production_batch_filter msgid "In Progress" msgstr "En Progreso" @@ -167,6 +175,13 @@ msgstr "En Progreso" msgid "Invoice batches" msgstr "Facturar lotes" +#. module: mrp_production_batch +#: code:addons/mrp_production_batch/models/mrp_production_batch.py:0 +#: model:ir.model.fields,field_description:mrp_production_batch.field_mrp_production__is_ready_to_produce +#, python-format +msgid "Is Ready To Produce" +msgstr "Está listo para producir" + #. module: mrp_production_batch #: model:ir.model.fields,field_description:mrp_production_batch.field_mrp_production____last_update #: model:ir.model.fields,field_description:mrp_production_batch.field_mrp_production_batch____last_update @@ -190,11 +205,6 @@ msgstr "Última actualización por" msgid "Last Updated on" msgstr "Última actualización el" -#. module: mrp_production_batch -#: model_terms:ir.ui.view,arch_db:mrp_production_batch.stock_production_type_kanban2 -msgid "Late" -msgstr "Tarde" - #. module: mrp_production_batch #: model:ir.model,name:mrp_production_batch.model_mrp_production_batch_wizard msgid "MRP Production Batch wizard" @@ -259,26 +269,11 @@ msgstr "Número de Pedidos de Fabricación a Procesar" msgid "Operation Type" msgstr "Tipo de Operación" -#. module: mrp_production_batch -#: model_terms:ir.ui.view,arch_db:mrp_production_batch.mrp_production_batch_form_view -msgid "Pending" -msgstr "Pendiente" - -#. module: mrp_production_batch -#: model:ir.model.fields,field_description:mrp_production_batch.field_mrp_production_batch__pending_production_count -msgid "Pending Production Count" -msgstr "Contador de Producción Pendiente" - #. module: mrp_production_batch #: model:ir.model,name:mrp_production_batch.model_stock_picking_type msgid "Picking Type" msgstr "Tipo de operación" -#. module: mrp_production_batch -#: model_terms:ir.ui.view,arch_db:mrp_production_batch.stock_production_type_kanban2 -msgid "Planned" -msgstr "Planificado" - #. module: mrp_production_batch #: model:ir.model.fields,field_description:mrp_production_batch.field_mrp_production_batch__product_qty msgid "Product Qty" @@ -299,6 +294,7 @@ msgstr "Producción %s no ha registrado cantidades producidas todavía." #. module: mrp_production_batch #: model:ir.model.fields,field_description:mrp_production_batch.field_mrp_production__production_batch_id +#: model_terms:ir.ui.view,arch_db:mrp_production_batch.stock_production_type_kanban2 msgid "Production Batch" msgstr "Lote de Producción" @@ -329,6 +325,26 @@ msgstr "Produciento Lote de Producción" msgid "Products" msgstr "Productos" +#. module: mrp_production_batch +#: model_terms:ir.ui.view,arch_db:mrp_production_batch.mrp_production_batch_form_view +msgid "Ready" +msgstr "Listo" + +#. module: mrp_production_batch +#: model:ir.model.fields,field_description:mrp_production_batch.field_mrp_production_batch__ready_production_ids +msgid "Ready Production" +msgstr "Producción Lista" + +#. module: mrp_production_batch +#: model:ir.model.fields,field_description:mrp_production_batch.field_mrp_production_batch__ready_production_count +msgid "Ready Production Count" +msgstr "Contador de Producción Lista" + +#. module: mrp_production_batch +#: model_terms:ir.ui.view,arch_db:mrp_production_batch.view_mrp_production_batch_filter +msgid "Search Production Batch" +msgstr "Buscar Lote de Producción" + #. module: mrp_production_batch #: code:addons/mrp_production_batch/models/mrp_production.py:0 #, python-format @@ -339,19 +355,24 @@ msgstr "Algunas de las producciones seleccionadas ya tienen un lote" #: code:addons/mrp_production_batch/models/mrp_production.py:0 #, python-format msgid "Some of the selected productions are already done or cancelled" -msgstr "Algunas de las producciones seleccionadas ya están hechas o canceladas" +msgstr "" +"Algunas de las producciones seleccionadas ya están hechas o canceladas" #. module: mrp_production_batch #: code:addons/mrp_production_batch/models/mrp_production.py:0 #, python-format msgid "Some of the selected productions have different operation types" -msgstr "Algunas de las producciones seleccionadas tienen diferentes tipos de operación" +msgstr "" +"Algunas de las producciones seleccionadas tienen diferentes tipos de " +"operación" #. module: mrp_production_batch #: code:addons/mrp_production_batch/models/mrp_production.py:0 #, python-format msgid "Some of the selected productions have different picking types:%s" -msgstr "Algunas de las producciones seleccionadas tienen diferentes tipos de operación:%s" +msgstr "" +"Algunas de las producciones seleccionadas tienen diferentes tipos de " +"operación:%s" #. module: mrp_production_batch #: code:addons/mrp_production_batch/models/mrp_production.py:0 @@ -364,11 +385,36 @@ msgstr "Algunas de las producciones seleccionadas tienen diferentes almacenes" msgid "State" msgstr "Estado" +#. module: mrp_production_batch +#: model_terms:ir.ui.view,arch_db:mrp_production_batch.mrp_production_form_view +msgid "The location is ready to produce in batch." +msgstr "La ubicación está lista para producir en lote." + +#. module: mrp_production_batch +#: model_terms:ir.ui.view,arch_db:mrp_production_batch.view_mrp_production_batch_filter +msgid "To Do" +msgstr "A Hacer" + #. module: mrp_production_batch #: model_terms:ir.ui.view,arch_db:mrp_production_batch.stock_production_type_kanban2 msgid "To Process" msgstr "A Procesar" +#. module: mrp_production_batch +#: model:ir.model.fields,field_description:mrp_production_batch.field_mrp_production_batch__to_review_production_ids +msgid "To Review Production" +msgstr "Producción a Revisar" + +#. module: mrp_production_batch +#: model:ir.model.fields,field_description:mrp_production_batch.field_mrp_production_batch__to_review_production_count +msgid "To Review Production Count" +msgstr "Conteo de Producción a Revisar" + +#. module: mrp_production_batch +#: model_terms:ir.ui.view,arch_db:mrp_production_batch.mrp_production_batch_form_view +msgid "To review" +msgstr "A revisar" + #. module: mrp_production_batch #: model_terms:ir.ui.view,arch_db:mrp_production_batch.mrp_production_batch_form_view msgid "Total" @@ -393,3 +439,23 @@ msgstr "Esperando" #: model:ir.model.fields,field_description:mrp_production_batch.field_mrp_production_batch_wizard__warehouse_id msgid "Warehouse" msgstr "Almacén" + +#. module: mrp_production_batch +#: code:addons/mrp_production_batch/models/mrp_production.py:0 +#, python-format +msgid "" +"You can't cancel a production that belongs to a batch %s. Please, delete it " +"from the batch first." +msgstr "" +"No se puede cancelar una producción que pertenece a un lote %s. Por favor, " +"primero elimínelo del lote." + +#. module: mrp_production_batch +#: code:addons/mrp_production_batch/models/mrp_production.py:0 +#, python-format +msgid "" +"You can't change the state of a production %s because it belongs to a batch: %s.\n" +"It must be processed from the batch." +msgstr "" +"No puedes cambiar el estado de una producción %s porque pertenece a un lote: %s. \n" +"Debe procesarse desde el lote." diff --git a/mrp_production_batch/models/mrp_production.py b/mrp_production_batch/models/mrp_production.py index 10ce5aeb8..0f130e7ff 100644 --- a/mrp_production_batch/models/mrp_production.py +++ b/mrp_production_batch/models/mrp_production.py @@ -1,12 +1,18 @@ # Copyright NuoBiT Solutions - Kilian Niubo +# Copyright NuoBiT Solutions - Frank Cespedes # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) -from odoo import _, fields, models +from odoo import _, api, fields, models from odoo.exceptions import ValidationError class MrpProduction(models.Model): _inherit = "mrp.production" + is_ready_to_produce = fields.Boolean( + store=True, + readonly=False, + ) + error_message = fields.Char() production_batch_id = fields.Many2one( comodel_name="mrp.production.batch", string="Production Batch", @@ -14,6 +20,29 @@ class MrpProduction(models.Model): domain="[('state', '!=', 'done')]", ) + @api.constrains("state") + def _check_state_batch_creation(self): + for rec in self: + if rec.production_batch_id: + if rec.state == "cancel": + raise ValidationError( + _( + "You can't cancel a production that belongs to a batch %s. " + "Please, delete it from the batch first." + ) + % rec.production_batch_id.name + ) + elif rec.state == "done": + if not self.env.context.get("mrp_production_batch_create"): + raise ValidationError( + _( + "You can't change the state of a production %s " + "because it belongs to a batch: %s.\n" + "It must be processed from the batch." + ) + % (rec.name, rec.production_batch_id.name) + ) + def _check_production_to_batch_consistency(self, mrp_productions): if not mrp_productions: raise ValidationError(_("No productions selected")) @@ -106,3 +135,7 @@ def action_view_production_batch(self): "view_id": view.id, "res_id": self.production_batch_id.id, } + + def action_check_production_with_batch(self): + self.ensure_one() + self.production_batch_id.with_context(mrp_production_check=True).action_check() diff --git a/mrp_production_batch/models/mrp_production_batch.py b/mrp_production_batch/models/mrp_production_batch.py index e773b8516..198f4cb4a 100644 --- a/mrp_production_batch/models/mrp_production_batch.py +++ b/mrp_production_batch/models/mrp_production_batch.py @@ -1,4 +1,5 @@ # Copyright NuoBiT Solutions - Kilian Niubo +# Copyright NuoBiT Solutions - Frank Cespedes # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) import logging @@ -41,24 +42,20 @@ def _compute_total_production_count(self): for rec in self: rec.total_production_count = len(rec.production_ids) - pending_production_count = fields.Integer( - compute="_compute_pending_production_count", + to_review_production_count = fields.Integer( + compute="_compute_production_wo_batch_count", ) - - def _compute_pending_production_count(self): - for rec in self: - rec.pending_production_count = len( - rec.production_ids.filtered(lambda r: r.state not in ("done", "cancel")) - ) - - done_production_count = fields.Integer( - compute="_compute_done_production_count", + ready_production_count = fields.Integer( + compute="_compute_production_wo_batch_count", ) - def _compute_done_production_count(self): + def _compute_production_wo_batch_count(self): for rec in self: - rec.done_production_count = len( - rec.production_ids.filtered(lambda r: r.state == "done") + rec.ready_production_count = len( + rec.production_ids.filtered(lambda r: r.is_ready_to_produce) + ) + rec.to_review_production_count = len( + rec.production_ids.filtered(lambda r: not r.is_ready_to_produce) ) cancelled_production_count = fields.Integer( @@ -124,22 +121,35 @@ def _compute_product_ids(self): def action_done(self): self.ensure_one() - productions = self.production_ids.filtered( - lambda r: r.state not in ("cancel", "done") - ) + productions = self.production_ids.filtered(lambda r: r.state != "cancel") + for production in productions: + production.with_context(mrp_production_batch_create=True).button_mark_done() + + def action_check(self): + self.ensure_one() + productions = self.production_ids.filtered(lambda r: not r.is_ready_to_produce) len_production = len(productions) - productions_display_name = [] + productions_not_ready = [] for production in productions: + raise_msg = _("Is Ready To Produce") try: - production.with_context( - mrp_production_batch_create=True - ).button_mark_done() - except (ValidationError, UserError): - productions_display_name.append(production.display_name) - if productions_display_name and len(productions_display_name) == len_production: - message = "The following productions could not be marked as 'done':\n" - message += "\n".join(productions_display_name) - raise UserError(message) + with self.env.cr.savepoint(): + production.with_context( + mrp_production_batch_create=True + ).button_mark_done() + raise ValidationError(raise_msg) + except (ValidationError, UserError) as e: + production.is_ready_to_produce = bool(e.name == raise_msg) + if not production.is_ready_to_produce: + productions_not_ready.append(production.display_name) + production.error_message = e.name + else: + production.error_message = False + if not self.env.context.get("mrp_production_check"): + if productions_not_ready and len(productions_not_ready) == len_production: + message = "The following productions could not be marked as 'done':\n" + message += "\n".join(productions_not_ready) + raise UserError(message) def _get_common_action_view_production(self): tree_view = self.env.ref("mrp.mrp_production_tree_view") @@ -159,22 +169,38 @@ def action_view_total_production(self): action["domain"] = [("id", "in", self.production_ids.ids)] return action - def action_view_production_pending(self): + def action_view_production_to_review(self): self.ensure_one() action = self._get_common_action_view_production() - action["domain"] = [ - ("id", "in", self.production_ids.ids), - ("state", "not in", ("done", "cancel")), - ] + action["domain"] = [("id", "in", self.to_review_production_ids.ids)] return action - def action_view_production_done(self): + ready_production_ids = fields.Many2many( + comodel_name="mrp.production", + compute="_compute_production_ready_ids", + ) + + def _compute_production_ready_ids(self): + for rec in self: + rec.ready_production_ids = rec.production_ids.filtered( + lambda x: x.is_ready_to_produce + ) + + to_review_production_ids = fields.Many2many( + comodel_name="mrp.production", + compute="_compute_production_to_review_ids", + ) + + def _compute_production_to_review_ids(self): + for rec in self: + rec.to_review_production_ids = rec.production_ids.filtered( + lambda x: not x.is_ready_to_produce + ) + + def action_view_production_ready(self): self.ensure_one() action = self._get_common_action_view_production() - action["domain"] = [ - ("id", "in", self.production_ids.ids), - ("state", "=", "done"), - ] + action["domain"] = [("id", "in", self.ready_production_ids.ids)] return action def action_view_production_cancelled(self): diff --git a/mrp_production_batch/models/stock_picking_type.py b/mrp_production_batch/models/stock_picking_type.py index cb431453f..e7b289a2d 100644 --- a/mrp_production_batch/models/stock_picking_type.py +++ b/mrp_production_batch/models/stock_picking_type.py @@ -51,6 +51,35 @@ def _compute_mo_count(self): else: rec.count_mo_todo_wo_batch = False + count_pb_todo = fields.Integer(compute="_compute_count_pb") + count_pb_waiting = fields.Integer(compute="_compute_count_pb") + + def _compute_count_pb(self): + mrp_picking_types = self.filtered( + lambda picking: picking.code == "mrp_operation_batch" + ) + if not mrp_picking_types: + self.count_pb_waiting = False + self.count_pb_todo = False + return + domains = { + "count_pb_waiting": [("state", "=", "in_progress")], + "count_pb_todo": [("state", "!=", "done")], + } + for field in domains: + data = self.env["mrp.production.batch"].read_group( + domains[field] + [("operation_type", "in", self.ids)], + ["operation_type"], + ["operation_type"], + ) + count = {x["operation_type"][0]: x["operation_type_count"] for x in data} + for picking in mrp_picking_types: + picking[field] = count.get(picking.id, 0) + remaining = self - mrp_picking_types + if remaining: + remaining.count_pb_waiting = False + remaining.count_pb_todo = False + mo_batches = fields.One2many( comodel_name="mrp.production.batch", inverse_name="operation_type", @@ -70,16 +99,3 @@ def get_mrp_production_batch_stock_picking_action_picking_type(self): if self: action["display_name"] = self.display_name return action - - def mrp_production_batch_action(self): - tree_view = self.env.ref("mrp_production_batch.mrp_production_batch_tree_view") - form_view = self.env.ref("mrp_production_batch.mrp_production_batch_form_view") - return { - "name": ("Detailed Operations"), - "type": "ir.actions.act_window", - "view_mode": "tree,form", - "res_model": "mrp.production.batch", - "views": [(tree_view.id, "tree"), (form_view.id, "form")], - "view_id": tree_view.id, - "domain": [("id", "in", self.mo_batches.ids)], - } diff --git a/mrp_production_batch/static/description/index.html b/mrp_production_batch/static/description/index.html index c8a583a30..fa13813ba 100644 --- a/mrp_production_batch/static/description/index.html +++ b/mrp_production_batch/static/description/index.html @@ -367,7 +367,7 @@

MRP Production Batch

!! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -!! source digest: sha256:f8930a819af69ed12083e16e4aad92d80f4f3c8ae272e327418c18ca6fc9768b +!! source digest: sha256:700bba545c72b4ff4d40b265cfbea8d46b2552a01a76ce668c2f6e033444f228 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->

Beta License: AGPL-3 NuoBiT/odoo-addons

    diff --git a/mrp_production_batch/views/mrp_production_batch_views.xml b/mrp_production_batch/views/mrp_production_batch_views.xml index fc2a52b2a..f2fa38630 100644 --- a/mrp_production_batch/views/mrp_production_batch_views.xml +++ b/mrp_production_batch/views/mrp_production_batch_views.xml @@ -14,7 +14,6 @@ - mrp.production.batch.form mrp.production.batch @@ -29,13 +28,21 @@ type="object" attrs="{'invisible': ['|',('state', '=', 'done'),('production_wo_lot_producing_id','=',[])]}" /> +
@@ -111,6 +118,20 @@
+ + mrp.production.batch.select + mrp.production.batch + + + + + + + mrp.production.batch
tree,kanban,form + [('operation_type', '=', active_id)] {'default_picking_type_id': active_id} @@ -142,4 +164,10 @@ mrp.production.batch tree,form + + Batch Production + ir.actions.act_window + mrp.production.batch + form + diff --git a/mrp_production_batch/views/mrp_production_views.xml b/mrp_production_batch/views/mrp_production_views.xml index 1074bd84b..c6a3ee846 100644 --- a/mrp_production_batch/views/mrp_production_views.xml +++ b/mrp_production_batch/views/mrp_production_views.xml @@ -31,6 +31,32 @@ mrp.production + + + + + + + + + {'invisible': [ + '|', + ('production_batch_id', '!=', False), + '|', + ('state', 'in', ('draft', 'cancel', 'done', 'to_close')), + ('qty_producing', '=', 0) + ]} + + + {'invisible': [ + '|', + ('production_batch_id', '!=', False), + '&', + '|', + ('state', 'not in', ('confirmed', 'progress')), + ('qty_producing', '!=', 0), + ('state', '!=', 'to_close') + ]} + + @@ -59,54 +60,35 @@
- - - -
- -
-
-
- -
- +
@@ -139,20 +121,11 @@ In Progress -
New
+
Date: Fri, 22 Dec 2023 15:51:06 +0100 Subject: [PATCH 08/21] [FIX] mrp_production_batch: code reviews --- mrp_production_batch/i18n/es.po | 47 ++----- mrp_production_batch/models/mrp_production.py | 24 ++-- .../models/mrp_production_batch.py | 117 +++++++----------- .../views/mrp_production_batch_views.xml | 13 -- .../views/mrp_production_views.xml | 2 +- 5 files changed, 72 insertions(+), 131 deletions(-) diff --git a/mrp_production_batch/i18n/es.po b/mrp_production_batch/i18n/es.po index be0d67fc0..37e050c38 100644 --- a/mrp_production_batch/i18n/es.po +++ b/mrp_production_batch/i18n/es.po @@ -6,8 +6,8 @@ msgid "" msgstr "" "Project-Id-Version: Odoo Server 14.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-12-21 15:59+0000\n" -"PO-Revision-Date: 2023-12-21 15:59+0000\n" +"POT-Creation-Date: 2023-12-22 14:37+0000\n" +"PO-Revision-Date: 2023-12-22 14:37+0000\n" "Last-Translator: \n" "Language-Team: \n" "MIME-Version: 1.0\n" @@ -59,25 +59,15 @@ msgstr "" msgid "Cancel" msgstr "Cancelar" -#. module: mrp_production_batch -#: model_terms:ir.ui.view,arch_db:mrp_production_batch.mrp_production_batch_form_view -msgid "Cancelled" -msgstr "Cancelado" - -#. module: mrp_production_batch -#: model:ir.model.fields,field_description:mrp_production_batch.field_mrp_production_batch__cancelled_production_count -msgid "Cancelled Production Count" -msgstr "Conteo de Producción Cancelada" - #. module: mrp_production_batch #: model_terms:ir.ui.view,arch_db:mrp_production_batch.mrp_production_form_view msgid "Check Production" -msgstr "Verificar Producción" +msgstr "Validar Producción" #. module: mrp_production_batch #: model_terms:ir.ui.view,arch_db:mrp_production_batch.mrp_production_batch_form_view msgid "Check Productions" -msgstr "Verificar Producciones" +msgstr "Validar Producciones" #. module: mrp_production_batch #: model_terms:ir.ui.view,arch_db:mrp_production_batch.stock_production_type_kanban2 @@ -118,13 +108,6 @@ msgstr "Creado en" msgid "Creation Date" msgstr "Fecha de Creación" -#. module: mrp_production_batch -#: code:addons/mrp_production_batch/models/mrp_production.py:0 -#: code:addons/mrp_production_batch/models/mrp_production_batch.py:0 -#, python-format -msgid "Detailed Operations" -msgstr "Operaciones Detalladas" - #. module: mrp_production_batch #: model:ir.model.fields,field_description:mrp_production_batch.field_mrp_production__display_name #: model:ir.model.fields,field_description:mrp_production_batch.field_mrp_production_batch__display_name @@ -149,15 +132,6 @@ msgstr "Borrador" msgid "Generate Serial Numbers" msgstr "Generar Números de Serie" -#. module: mrp_production_batch -#: model:ir.model.fields,field_description:mrp_production_batch.field_mrp_production__id -#: model:ir.model.fields,field_description:mrp_production_batch.field_mrp_production_batch__id -#: model:ir.model.fields,field_description:mrp_production_batch.field_mrp_production_batch_line_wizard__id -#: model:ir.model.fields,field_description:mrp_production_batch.field_mrp_production_batch_wizard__id -#: model:ir.model.fields,field_description:mrp_production_batch.field_stock_picking_type__id -msgid "ID" -msgstr "ID" - #. module: mrp_production_batch #: model:ir.actions.act_window,name:mrp_production_batch.mrp_production_batch_wizard_action msgid "Import partners" @@ -176,9 +150,7 @@ msgid "Invoice batches" msgstr "Facturar lotes" #. module: mrp_production_batch -#: code:addons/mrp_production_batch/models/mrp_production_batch.py:0 #: model:ir.model.fields,field_description:mrp_production_batch.field_mrp_production__is_ready_to_produce -#, python-format msgid "Is Ready To Produce" msgstr "Está listo para producir" @@ -415,11 +387,6 @@ msgstr "Conteo de Producción a Revisar" msgid "To review" msgstr "A revisar" -#. module: mrp_production_batch -#: model_terms:ir.ui.view,arch_db:mrp_production_batch.mrp_production_batch_form_view -msgid "Total" -msgstr "Total" - #. module: mrp_production_batch #: model:ir.model.fields,field_description:mrp_production_batch.field_mrp_production_batch__total_production_count msgid "Total Production Count" @@ -440,6 +407,12 @@ msgstr "Esperando" msgid "Warehouse" msgstr "Almacén" +#. module: mrp_production_batch +#: code:addons/mrp_production_batch/models/mrp_production_batch.py:0 +#, python-format +msgid "The following productions could not be marked as 'done':" +msgstr "Las siguientes producciones no se pudieron marcar como 'hechas':" + #. module: mrp_production_batch #: code:addons/mrp_production_batch/models/mrp_production.py:0 #, python-format diff --git a/mrp_production_batch/models/mrp_production.py b/mrp_production_batch/models/mrp_production.py index 0f130e7ff..c3b12761f 100644 --- a/mrp_production_batch/models/mrp_production.py +++ b/mrp_production_batch/models/mrp_production.py @@ -5,13 +5,14 @@ from odoo.exceptions import ValidationError +class FakeException(ValidationError): + pass + + class MrpProduction(models.Model): _inherit = "mrp.production" - is_ready_to_produce = fields.Boolean( - store=True, - readonly=False, - ) + is_ready_to_produce = fields.Boolean() error_message = fields.Char() production_batch_id = fields.Many2one( comodel_name="mrp.production.batch", @@ -33,7 +34,7 @@ def _check_state_batch_creation(self): % rec.production_batch_id.name ) elif rec.state == "done": - if not self.env.context.get("mrp_production_batch_create"): + if not self.env.context.get("mrp_production_batch_create", False): raise ValidationError( _( "You can't change the state of a production %s " @@ -136,6 +137,15 @@ def action_view_production_batch(self): "res_id": self.production_batch_id.id, } - def action_check_production_with_batch(self): + def action_check_with_batch(self): self.ensure_one() - self.production_batch_id.with_context(mrp_production_check=True).action_check() + try: + with self.env.cr.savepoint(): + self.with_context(mrp_production_batch_create=True).button_mark_done() + raise FakeException("") + except FakeException: + self.is_ready_to_produce = True + self.error_message = False + except Exception as e: + self.is_ready_to_produce = False + self.error_message = e.name diff --git a/mrp_production_batch/models/mrp_production_batch.py b/mrp_production_batch/models/mrp_production_batch.py index 198f4cb4a..069db555b 100644 --- a/mrp_production_batch/models/mrp_production_batch.py +++ b/mrp_production_batch/models/mrp_production_batch.py @@ -4,7 +4,7 @@ import logging from odoo import _, api, fields, models -from odoo.exceptions import UserError, ValidationError +from odoo.exceptions import UserError _logger = logging.getLogger(__name__) @@ -58,16 +58,6 @@ def _compute_production_wo_batch_count(self): rec.production_ids.filtered(lambda r: not r.is_ready_to_produce) ) - cancelled_production_count = fields.Integer( - compute="_compute_cancelled_production_count", - ) - - def _compute_cancelled_production_count(self): - for rec in self: - rec.cancelled_production_count = len( - rec.production_ids.filtered(lambda r: r.state == "cancel") - ) - creation_date = fields.Date( string="Creation Date", ) @@ -119,37 +109,54 @@ def _compute_product_ids(self): for rec in self: rec.product_ids = rec.production_ids.product_id - def action_done(self): - self.ensure_one() - productions = self.production_ids.filtered(lambda r: r.state != "cancel") - for production in productions: - production.with_context(mrp_production_batch_create=True).button_mark_done() + ready_production_ids = fields.Many2many( + comodel_name="mrp.production", + compute="_compute_production_ready_ids", + ) + + def _compute_production_ready_ids(self): + for rec in self: + rec.ready_production_ids = rec.production_ids.filtered( + lambda x: x.is_ready_to_produce + ) + + to_review_production_ids = fields.Many2many( + comodel_name="mrp.production", + compute="_compute_production_to_review_ids", + ) + + def _compute_production_to_review_ids(self): + for rec in self: + rec.to_review_production_ids = rec.production_ids.filtered( + lambda x: not x.is_ready_to_produce + ) + + def action_generate_serial(self): + for rec in self: + for production in rec.production_wo_lot_producing_id: + production.action_generate_serial() def action_check(self): self.ensure_one() productions = self.production_ids.filtered(lambda r: not r.is_ready_to_produce) - len_production = len(productions) - productions_not_ready = [] + init_production_count = len(productions) for production in productions: - raise_msg = _("Is Ready To Produce") - try: - with self.env.cr.savepoint(): - production.with_context( - mrp_production_batch_create=True - ).button_mark_done() - raise ValidationError(raise_msg) - except (ValidationError, UserError) as e: - production.is_ready_to_produce = bool(e.name == raise_msg) - if not production.is_ready_to_produce: - productions_not_ready.append(production.display_name) - production.error_message = e.name - else: - production.error_message = False - if not self.env.context.get("mrp_production_check"): - if productions_not_ready and len(productions_not_ready) == len_production: - message = "The following productions could not be marked as 'done':\n" - message += "\n".join(productions_not_ready) - raise UserError(message) + production.action_check_with_batch() + final_production_count = len( + self.production_ids.filtered(lambda r: not r.is_ready_to_produce) + ) + if init_production_count == final_production_count: + message = [ + _("The following productions could not be marked as 'done':"), + "\n".join(productions.mapped("display_name")), + ] + raise UserError("\n".join(message)) + + def action_done(self): + self.ensure_one() + self.action_check() + for production in self.production_ids: + production.with_context(mrp_production_batch_create=True).button_mark_done() def _get_common_action_view_production(self): tree_view = self.env.ref("mrp.mrp_production_tree_view") @@ -175,44 +182,8 @@ def action_view_production_to_review(self): action["domain"] = [("id", "in", self.to_review_production_ids.ids)] return action - ready_production_ids = fields.Many2many( - comodel_name="mrp.production", - compute="_compute_production_ready_ids", - ) - - def _compute_production_ready_ids(self): - for rec in self: - rec.ready_production_ids = rec.production_ids.filtered( - lambda x: x.is_ready_to_produce - ) - - to_review_production_ids = fields.Many2many( - comodel_name="mrp.production", - compute="_compute_production_to_review_ids", - ) - - def _compute_production_to_review_ids(self): - for rec in self: - rec.to_review_production_ids = rec.production_ids.filtered( - lambda x: not x.is_ready_to_produce - ) - def action_view_production_ready(self): self.ensure_one() action = self._get_common_action_view_production() action["domain"] = [("id", "in", self.ready_production_ids.ids)] return action - - def action_view_production_cancelled(self): - self.ensure_one() - action = self._get_common_action_view_production() - action["domain"] = [ - ("id", "in", self.production_ids.ids), - ("state", "=", "cancel"), - ] - return action - - def action_generate_serial(self): - for rec in self: - for production in rec.production_wo_lot_producing_id: - production.action_generate_serial() diff --git a/mrp_production_batch/views/mrp_production_batch_views.xml b/mrp_production_batch/views/mrp_production_batch_views.xml index f2fa38630..c100bc0c0 100644 --- a/mrp_production_batch/views/mrp_production_batch_views.xml +++ b/mrp_production_batch/views/mrp_production_batch_views.xml @@ -61,19 +61,6 @@ string="Total" /> -
+
+

+ Draft +

+

+ +

+
- - - - - - - + + + + -
- - mrp.production.batch.select + + mrp.production.batch.search mrp.production.batch + + - + @@ -128,7 +133,7 @@ mrp.production.batch tree,kanban,form - + [('operation_type', '=', active_id)] {'default_picking_type_id': active_id} @@ -137,6 +142,7 @@ ir.actions.act_window mrp.production.batch tree,form + {'search_default_todo': 1}

No Batch Production order found diff --git a/mrp_production_batch/views/mrp_production_views.xml b/mrp_production_batch/views/mrp_production_views.xml index 395b2e8c8..01440a889 100644 --- a/mrp_production_batch/views/mrp_production_views.xml +++ b/mrp_production_batch/views/mrp_production_views.xml @@ -38,7 +38,7 @@ role="alert" attrs="{'invisible': ['|', ('production_batch_id', '=', False), '|', ('is_ready_to_produce', '=', False), ('state', '=', 'done')]}" > - The location is ready to produce in batch. + The production is ready to produce in batch.