Skip to content

Commit

Permalink
[FIX] stock_available_mrp: variant BoMs
Browse files Browse the repository at this point in the history
When a BoM is linked just to one variant through field `product_id`,
it is taken in account when computing stock of the rest of variants
of the same template.
  • Loading branch information
danielduqma committed Dec 12, 2023
1 parent b8fe27c commit 6bf6174
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 3 deletions.
22 changes: 19 additions & 3 deletions stock_available_mrp/models/product_product.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,25 @@
class ProductProduct(models.Model):
_inherit = "product.product"

@api.depends("virtual_available", "bom_ids", "bom_ids.product_qty")
@api.depends(
"virtual_available",
"bom_ids",
"bom_ids.product_qty",
"variant_bom_ids",
"variant_bom_ids.product_qty",
)
def _compute_available_quantities(self):
res = super()._compute_available_quantities()
return res

def _compute_available_quantities_dict(self):
res, stock_dict = super()._compute_available_quantities_dict()
# compute qty for product with bom
product_with_bom = self.filtered("bom_ids")
product_with_bom = self.filtered("variant_bom_ids")
product_with_bom |= (self - product_with_bom).filtered(
lambda p: p.bom_ids
and any(not bom.product_id or bom.product_id == p for bom in p.bom_ids)
)

if not product_with_bom:
return res, stock_dict
Expand Down Expand Up @@ -53,7 +63,13 @@ def _compute_available_quantities_dict(self):

for product in product_with_bom:
# Need by product (same product can be in many BOM lines/levels)
bom_id = first(product.bom_ids)
bom_id = first(
product.variant_bom_ids
or product.bom_ids.filtered(
lambda b, product=product: not b.product_id
or b.product_id == product
)
)
exploded_components = exploded_boms[product.id]
component_needs = product._get_components_needs(exploded_components)
if not component_needs:
Expand Down
67 changes: 67 additions & 0 deletions stock_available_mrp/tests/test_potential_qty.py
Original file line number Diff line number Diff line change
Expand Up @@ -451,3 +451,70 @@ def test_product_phantom(self):
product.invalidate_model()

self.assertEqual(product.immediately_usable_qty, 0.0)

def test_06_potential_qty(self):
# BoM only applies to white variant.
bom = self.env["mrp.bom"].search([("product_tmpl_id", "=", self.tmpl.id)])
bom.bom_line_ids.write({"bom_product_template_attribute_value_ids": False})
bom.product_id = self.var2.id
for i in [self.tmpl, self.var1, self.var2]:
self.assertPotentialQty(i, 0.0, "The potential quantity should start at 0")

# Receive 1000x Wood Panel
self.create_inventory(
product=self.env.ref("mrp.product_product_wood_panel"),
qty=1000.0,
location=self.wh_main.lot_stock_id,
)
for i in [self.tmpl, self.var1, self.var2]:
self.assertPotentialQty(
i,
0.0,
"Receiving a single component should not change the "
"potential of %s" % i,
)

# Receive second component
self.create_inventory(
product=self.env.ref("mrp.product_product_computer_desk_bolt"),
qty=1000.0,
location=self.wh_main.lot_stock_id,
)
self.assertPotentialQty(
self.tmpl,
0,
"Template potential changed after receiving partial variant 2 components",
)
self.assertPotentialQty(
self.var1,
0,
"Variant 1 potential changed after receiving partial variant 2 components",
)
self.assertPotentialQty(
self.var2,
0.0,
"Variant 2 potential changed after receiving partial components",
)

# Receive enough components to make 250 the 1st variant
self.create_inventory(
product=self.env.ref(
"stock_available_mrp.product_computer_desk_bolt_white"
),
qty=1000.0,
location=self.wh_main.lot_stock_id,
)
self.var1.invalidate_model()
self.assertPotentialQty(
self.tmpl,
250.0,
"Wrong template potential after receiving variant 2 components",
)
self.assertPotentialQty(
self.var1,
0,
"Wrong variant 1 potential after receiving variant 2 components",
)
self.assertPotentialQty(
self.var2, 250.0, "Wrong variant 2 potential after receiving its components"
)

0 comments on commit 6bf6174

Please sign in to comment.