[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.
This commit is contained in:
Lois Rilo
2022-05-03 16:01:51 +02:00
committed by Ruchir Shukla
parent 7e685eb285
commit 6326ba0901
3 changed files with 48 additions and 17 deletions

View File

@@ -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)

View File

@@ -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

View File

@@ -5,14 +5,19 @@
<field name="model">mrp.production.serial.matrix</field>
<field name="arch" type="xml">
<form>
<group name="info">
<field name="production_id" options='{"no_open": True}' />
<field name="product_id" options='{"no_open": True}' />
<field
name="company_id"
options='{"no_open": True}'
invisible="1"
/>
<group>
<group name="info">
<field name="production_id" options='{"no_open": True}' />
<field name="product_id" options='{"no_open": True}' />
<field
name="company_id"
options='{"no_open": True}'
invisible="1"
/>
</group>
<group name="settings">
<field name="include_lots" widget="boolean_toggle" />
</group>
</group>
<group name="finished_lots" string="Finished Product Serial Numbers">
<p