Skip to content

Commit 811035f

Browse files
committed
[FIX] product_replenishment_cost_mrp: adapt module to subcontracting
X-original-commit: 0f36826
1 parent 50451ac commit 811035f

File tree

3 files changed

+74
-8
lines changed

3 files changed

+74
-8
lines changed

product_replenishment_cost_mrp/README.rst

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@
1414
Integration between Replenishment Cost and Manufacture
1515
======================================================
1616

17-
#. Agregado de método para cálculo de costo de reposición utilizando el costo de reposición de la LdM.
18-
#. Modifica el reporte de "Estructura de Lista de Materiales" para que utilice el costo de reposición.
17+
#. Add a method to compute the replenishment cost using the BoM's replenishment cost.
18+
#. Modify the "Bill of Materials Structure" report to use the replenishment cost
19+
#. Support for replenishment cost calculation in subcontracted BOMs, adding the supplier/subcontractor cost to the components' cost
1920

2021
Installation
2122
============

product_replenishment_cost_mrp/models/product_template.py

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,11 @@ def _compute_replenishment_cost(self):
4646
rec.update({"replenishment_base_cost_on_currency": 0.0, "replenishment_cost": 0.0})
4747
continue
4848
# el explode es para product.product, tomamos la primer variante
49-
result, result2 = bom.explode(rec.with_context(active_test=rec.active).product_variant_ids[0], 1)
49+
product_variant = rec.with_context(active_test=rec.active).product_variant_ids[:1]
50+
if not product_variant:
51+
rec.update({"replenishment_base_cost_on_currency": 0.0, "replenishment_cost": 0.0})
52+
continue
53+
result, result2 = bom.explode(product_variant, 1)
5054
for sbom, sbom_data in result2:
5155
sbom_rep_cost = (
5256
sbom.product_id.uom_id._compute_price(
@@ -57,6 +61,36 @@ def _compute_replenishment_cost(self):
5761
price += sbom.product_id.product_tmpl_id.currency_id._convert(
5862
sbom_rep_cost, product_currency, company, date, round=False
5963
)
64+
65+
# Add subcontracting cost if bom type is 'subcontract'
66+
if bom.type == "subcontract":
67+
# Look for the seller/subcontractor set in the BOM
68+
product = rec.product_variant_ids[:1]
69+
if product:
70+
seller = product._select_seller(
71+
quantity=1, uom_id=bom.product_uom_id, params={"subcontractor_ids": bom.subcontractor_ids}
72+
)
73+
else:
74+
# If no product variant, look for sellers in the template
75+
seller = rec.seller_ids.filtered(lambda s: s.partner_id in bom.subcontractor_ids)[:1]
76+
77+
if seller:
78+
if bom.product_uom_id.ratio == 0:
79+
raise ValueError(
80+
_(
81+
"El ratio de la unidad de medida del producto '%s' en el BOM es cero. "
82+
"Esto provocaría una división por cero. Verifique la configuración de la UoM."
83+
)
84+
% bom.display_name
85+
)
86+
# Calculate the subcontracting cost
87+
ratio_uom_seller = seller.product_uom.ratio / bom.product_uom_id.ratio
88+
subcontract_price = seller.currency_id._convert(
89+
seller.price, product_currency, company, date, round=False
90+
)
91+
# Add the subcontract price to the total price
92+
price += subcontract_price / ratio_uom_seller
93+
6094
# NO implementamos total va a ser borrado. Ver si implementamos mas adelante (tener en cuenta convertir
6195
# moneda)
6296
# if bom.routing_id:

product_replenishment_cost_mrp/report/mrp_report_bom_structure.py

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,31 @@
44
class ReportReplenishmentBomStructure(models.AbstractModel):
55
_inherit = "report.mrp.report_bom_structure"
66

7+
@api.model
8+
def _get_subcontracting_line(self, bom, seller, level, bom_quantity):
9+
"""Override to convert seller price to the proper currency"""
10+
res = super()._get_subcontracting_line(bom, seller, level, bom_quantity)
11+
currency = self.env.context.get("force_currency") or self.env.company.currency_id
12+
13+
# Convert the seller price to the proper currency
14+
if bom.product_uom_id.ratio == 0:
15+
raise ValueError(
16+
"El ratio de la unidad de medida del producto en el BOM es cero. "
17+
"Esto provocaría una división por cero. Verifique la configuración de la UoM."
18+
)
19+
ratio_uom_seller = seller.product_uom.ratio / bom.product_uom_id.ratio
20+
price = seller.currency_id._convert(seller.price, currency, self.env.company, fields.Date.today(), round=True)
21+
res.update(
22+
{
23+
"prod_cost": price / ratio_uom_seller * bom_quantity,
24+
"bom_cost": price / ratio_uom_seller * bom_quantity,
25+
"currency": currency,
26+
"currency_id": currency.id,
27+
}
28+
)
29+
30+
return res
31+
732
@api.model
833
def _get_bom_data(
934
self,
@@ -22,7 +47,7 @@ def _get_bom_data(
2247
):
2348
"""Here we use the replenishment cost for the uom unit"""
2449
if not self.env.context.get("force_currency"):
25-
self = self.with_context(force_currency=product.currency_id)
50+
self = self.with_context(force_currency=product.currency_id if product else bom.product_tmpl_id.currency_id)
2651
res = super(ReportReplenishmentBomStructure, self)._get_bom_data(
2752
bom,
2853
warehouse,
@@ -43,6 +68,9 @@ def _get_bom_data(
4368
current_quantity = line_qty
4469
if bom_line:
4570
current_quantity = bom_line.product_uom_id._compute_quantity(line_qty, bom.product_uom_id) or 0
71+
72+
# Only update prod_cost (costo del producto final), not bom_cost
73+
# bom_cost is automatically calculated as: components + operations + subcontracting
4674
if not is_minimized:
4775
if product:
4876
price = product.uom_id._compute_price(product.replenishment_cost, bom.product_uom_id) * current_quantity
@@ -79,10 +107,13 @@ def _get_component_data(
79107
parent_bom, parent_product, warehouse, bom_line, line_quantity, level, index, product_info, ignore_stock
80108
)
81109
currency = self.env.context.get("force_currency") or self.env.company.currency_id
82-
price = (
83-
bom_line.product_id.uom_id._compute_price(bom_line.product_id.replenishment_cost, bom_line.product_uom_id)
84-
* line_quantity
85-
)
110+
111+
# Use replenishment_cost, if not defined use standard_price as fallback
112+
component_cost = bom_line.product_id.replenishment_cost
113+
if not component_cost:
114+
component_cost = bom_line.product_id.standard_price
115+
116+
price = bom_line.product_id.uom_id._compute_price(component_cost, bom_line.product_uom_id) * line_quantity
86117
price = bom_line.product_id.currency_id._convert(
87118
price, currency, self.env.company, fields.Date.today(), round=True
88119
)

0 commit comments

Comments
 (0)