From 3efa7b9545779d46922002ec074b95d7281b6d79 Mon Sep 17 00:00:00 2001 From: Lois Rilo Date: Tue, 3 May 2022 16:01:51 +0200 Subject: [PATCH] [IMP] mrp_production_serial_matrix: handle flexible manufacturing. If the component lines are changed they might differ from what it is stated in the BoM. It is better to rely on compoent lines to generate Matrix. New option to decide whether to add or not products tracked by lots to the matrix is added. Product tracked by serials are always added. --- .../test_mrp_production_serial_matrix.py | 3 ++ .../wizards/mrp_production_serial_matrix.py | 41 +++++++++++++++---- .../mrp_production_serial_matrix_view.xml | 21 ++++++---- 3 files changed, 48 insertions(+), 17 deletions(-) diff --git a/mrp_production_serial_matrix/tests/test_mrp_production_serial_matrix.py b/mrp_production_serial_matrix/tests/test_mrp_production_serial_matrix.py index 89738b4dc..a55146a37 100644 --- a/mrp_production_serial_matrix/tests/test_mrp_production_serial_matrix.py +++ b/mrp_production_serial_matrix/tests/test_mrp_production_serial_matrix.py @@ -175,6 +175,9 @@ class TestMrpProductionSerialMatrix(SavepointCase): active_id=production_1.id, active_model="mrp.production" ) ) + expected = 3 * 3 # Only SN products (1 + 2 per finish unit) + self.assertEqual(len(wizard_form.line_ids), expected) + wizard_form.include_lots = True expected = 3 * 4 self.assertEqual(len(wizard_form.line_ids), expected) self.assertEqual(wizard_form.lot_selection_warning_count, 0) diff --git a/mrp_production_serial_matrix/wizards/mrp_production_serial_matrix.py b/mrp_production_serial_matrix/wizards/mrp_production_serial_matrix.py index 2bf4ea96c..bc4bc36e5 100644 --- a/mrp_production_serial_matrix/wizards/mrp_production_serial_matrix.py +++ b/mrp_production_serial_matrix/wizards/mrp_production_serial_matrix.py @@ -40,6 +40,11 @@ class MrpProductionSerialMatrix(models.TransientModel): lot_selection_warning_count = fields.Integer( compute="_compute_lot_selection_warning" ) + include_lots = fields.Boolean( + string="Include Lots?", + help="Include products tracked by Lots in matrix. Product tracket by " + "serial numbers are always included.", + ) @api.depends("line_ids", "line_ids.component_lot_id") def _compute_lot_selection_warning(self): @@ -129,14 +134,26 @@ class MrpProductionSerialMatrix(models.TransientModel): def _get_matrix_lines(self, production, finished_lots): tracked_components = [] - for line in production.bom_id.bom_line_ids: - if line.product_id.tracking == "serial": - # TODO: factor if parent is not 1. - # TODO: uom. - for i in range(1, int(line.product_qty) + 1): - tracked_components.append((line.product_id, i, 1)) - elif line.product_id.tracking == "lot": - tracked_components.append((line.product_id, 0, line.product_qty)) + for move in production.move_raw_ids: + rounding = move.product_id.uom_id.rounding + if float_is_zero(move.product_qty, precision_rounding=rounding): + # Component moves cannot be deleted in in-progress MO's; however, + # they can be set to 0 units to consume. In such case, we ignore + # the move. + continue + boml = move.bom_line_id + # TODO: UoM (MO/BoM using different UoMs than product's defaults). + if boml: + qty_per_finished_unit = boml.product_qty / boml.bom_id.product_qty + else: + # The product could have been added for the specific MO but not + # be part of the BoM. + qty_per_finished_unit = move.product_qty / production.product_qty + if move.product_id.tracking == "serial": + for i in range(1, int(qty_per_finished_unit) + 1): + tracked_components.append((move.product_id, i, 1)) + elif move.product_id.tracking == "lot" and self.include_lots: + tracked_components.append((move.product_id, 0, qty_per_finished_unit)) matrix_lines = [] current_lot = False @@ -187,7 +204,7 @@ class MrpProductionSerialMatrix(models.TransientModel): ) return res - @api.onchange("finished_lot_ids") + @api.onchange("finished_lot_ids", "include_lots") def _onchange_finished_lot_ids(self): for rec in self: matrix_lines = self._get_matrix_lines( @@ -212,6 +229,12 @@ class MrpProductionSerialMatrix(models.TransientModel): current_mo.qty_producing = 1.0 current_mo._set_qty_producing() for move in current_mo.move_raw_ids: + rounding = move.product_id.uom_id.rounding + if float_is_zero(move.product_qty, precision_rounding=rounding): + # Component moves cannot be deleted in in-progress MO's; however, + # they can be set to 0 units to consume. In such case, we ignore + # the move. + continue if move.product_id.tracking in ["serial", "lot"]: # We filter using the lot nane because the ORM sometimes # is not storing correctly the finished_lot_id in the lines diff --git a/mrp_production_serial_matrix/wizards/mrp_production_serial_matrix_view.xml b/mrp_production_serial_matrix/wizards/mrp_production_serial_matrix_view.xml index 313ac0dc7..c2a4a82c1 100644 --- a/mrp_production_serial_matrix/wizards/mrp_production_serial_matrix_view.xml +++ b/mrp_production_serial_matrix/wizards/mrp_production_serial_matrix_view.xml @@ -5,14 +5,19 @@ mrp.production.serial.matrix
- - - - + + + + + + + + +