mirror of
https://github.com/OCA/manufacture.git
synced 2025-01-28 16:37:15 +02:00
mrp_package_propagation: propagate from consumable components
As there is no quant created for consumable products, Odoo does not support the propagation of a destination package from an ancestor move to its destination move. As such, the consumable component move of a MO has no package to propagate even if the Pre-PICK transfer put one. To support this use-case, we try to find a package to propagate from ancestor moves, allowing consumable products to propagate packages.
This commit is contained in:
@@ -28,6 +28,7 @@ class MrpProduction(models.Model):
|
|||||||
@api.depends(
|
@api.depends(
|
||||||
"move_raw_ids.propagate_package",
|
"move_raw_ids.propagate_package",
|
||||||
"move_raw_ids.move_line_ids.qty_done",
|
"move_raw_ids.move_line_ids.qty_done",
|
||||||
|
"move_raw_ids.move_orig_ids.move_line_ids.result_package_id",
|
||||||
)
|
)
|
||||||
def _compute_propagated_package_id(self):
|
def _compute_propagated_package_id(self):
|
||||||
for order in self:
|
for order in self:
|
||||||
@@ -40,6 +41,16 @@ class MrpProduction(models.Model):
|
|||||||
)
|
)
|
||||||
if len(line_with_package) == 1:
|
if len(line_with_package) == 1:
|
||||||
order.propagated_package_id = line_with_package.package_id
|
order.propagated_package_id = line_with_package.package_id
|
||||||
|
continue
|
||||||
|
# Support for consumable components: as no quant is created for
|
||||||
|
# such products Odoo doesn't copy the destination of the ancestor
|
||||||
|
# move (Pre-PICK) to the current move of the component.
|
||||||
|
# In such case, get the package to propagate from the ancestor
|
||||||
|
# move(s).
|
||||||
|
if move_with_package and not line_with_package:
|
||||||
|
order.propagated_package_id = fields.first(
|
||||||
|
move_with_package.move_orig_ids.move_line_ids.result_package_id
|
||||||
|
)
|
||||||
|
|
||||||
@api.onchange("bom_id")
|
@api.onchange("bom_id")
|
||||||
def _onchange_bom_id_package_propagation(self):
|
def _onchange_bom_id_package_propagation(self):
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
# Copyright 2023 Camptocamp SA
|
# Copyright 2023 Camptocamp SA
|
||||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
|
||||||
|
|
||||||
|
from odoo import fields
|
||||||
from odoo.exceptions import UserError
|
from odoo.exceptions import UserError
|
||||||
from odoo.tests.common import Form
|
from odoo.tests.common import Form
|
||||||
|
|
||||||
@@ -18,9 +19,13 @@ class TestMrpProduction(Common):
|
|||||||
line_form.propagate_package = True
|
line_form.propagate_package = True
|
||||||
line_form.save()
|
line_form.save()
|
||||||
form.save()
|
form.save()
|
||||||
|
cls.order = cls._create_manufacturing_order(cls.bom)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _create_manufacturing_order(cls, bom):
|
||||||
with Form(cls.env["mrp.production"]) as form:
|
with Form(cls.env["mrp.production"]) as form:
|
||||||
form.bom_id = cls.bom
|
form.bom_id = bom
|
||||||
cls.order = form.save()
|
return form.save()
|
||||||
|
|
||||||
def _set_qty_done(self, order):
|
def _set_qty_done(self, order):
|
||||||
for line in order.move_raw_ids.move_line_ids:
|
for line in order.move_raw_ids.move_line_ids:
|
||||||
@@ -61,3 +66,49 @@ class TestMrpProduction(Common):
|
|||||||
self.order.action_generate_serial()
|
self.order.action_generate_serial()
|
||||||
self.order.button_mark_done()
|
self.order.button_mark_done()
|
||||||
self.assertEqual(self.order.propagated_package_id.name, self.PACKAGE_NAME)
|
self.assertEqual(self.order.propagated_package_id.name, self.PACKAGE_NAME)
|
||||||
|
self.assertEqual(
|
||||||
|
self.order.move_finished_ids.move_line_ids.result_package_id.name,
|
||||||
|
self.PACKAGE_NAME,
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_order_propagated_package_id_through_consumable_component(self):
|
||||||
|
"""Test package propagation from a consumable component."""
|
||||||
|
# NOTE: we enable the manufacturing in two steps in this test to get
|
||||||
|
# ancestor moves (Pre-PICK transfer to validate to get components
|
||||||
|
# available for MO) required to find the destination package among them.
|
||||||
|
self.env.ref("stock.warehouse0").manufacture_steps = "pbm"
|
||||||
|
# Enable the package propagation on a consumable component
|
||||||
|
self.bom.bom_line_ids.propagate_package = False
|
||||||
|
consu_bom_line = fields.first(
|
||||||
|
self.bom.bom_line_ids.filtered(lambda o: o.product_id.type == "consu")
|
||||||
|
)
|
||||||
|
consu_bom_line.write({"product_qty": 1, "propagate_package": True})
|
||||||
|
# Create MO
|
||||||
|
order = self._create_manufacturing_order(self.bom)
|
||||||
|
self.assertTrue(order.is_package_propagated)
|
||||||
|
self._update_stock_component_qty(order)
|
||||||
|
order.action_confirm()
|
||||||
|
order.action_assign()
|
||||||
|
order.picking_ids.action_assign()
|
||||||
|
# Put a destination package in Pre-PICK for the consumable component
|
||||||
|
consu_move_line = order.picking_ids.move_line_ids.filtered(
|
||||||
|
lambda l: l.product_id == consu_bom_line.product_id
|
||||||
|
)
|
||||||
|
package = self.env["stock.quant.package"].create(
|
||||||
|
{"name": self.PACKAGE_NAME + "-CONSU"}
|
||||||
|
)
|
||||||
|
consu_move_line.result_package_id = package
|
||||||
|
# Validate the Pre-PICK: package is found by the MO
|
||||||
|
for line in order.picking_ids.move_line_ids:
|
||||||
|
line.qty_done = line.product_uom_qty
|
||||||
|
order.picking_ids._action_done()
|
||||||
|
self.assertTrue(order.is_package_propagated)
|
||||||
|
self.assertTrue(any(order.move_raw_ids.mapped("propagate_package")))
|
||||||
|
self.assertEqual(order.propagated_package_id, package)
|
||||||
|
# Validate MO: package is propagated to finished product
|
||||||
|
self._set_qty_done(order)
|
||||||
|
order.action_generate_serial()
|
||||||
|
order.button_mark_done()
|
||||||
|
self.assertEqual(
|
||||||
|
order.move_finished_ids.move_line_ids.result_package_id, package
|
||||||
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user