[FIX] {,purchase_}mrp: add missing days when calculate DTPMO

When calculate Days to Prepare Manufacturing Order, we didn't take into
account Days to Purchase and Security Lead times for Purchaseing of the
company. In this commmit, if the (sub-)bom has company_id set, these two
days will added to the calculation.

Task-3078049

X-original-commit: bf59aedad649dec350f091bb074d3ef1e51d5fcb
Part-of: odoo/odoo#121813
This commit is contained in:
yhu-odoo
2023-05-19 16:42:07 +02:00
parent baefb74b04
commit 0171f4a1e4
6 changed files with 74 additions and 10 deletions
+4 -2
View File
@@ -1235,6 +1235,8 @@ msgstr ""
msgid ""
"Compute the days required to resupply all components from BoM, by either "
"buying or manufacturing the components and/or subassemblies."
" Also note that purchase security lead"
" times will be added when appropriate."
msgstr ""
#. module: mrp
@@ -1419,8 +1421,8 @@ msgstr ""
#. module: mrp
#: model:ir.model.fields,help:mrp.field_mrp_bom__days_to_prepare_mo
msgid ""
"Create and confirm Manufacturing Orders these many days in advance, to have enough time to replenish components or manufacture semi-finished products.\n"
"Note that this does not affect the MO scheduled date, which still respects the just-in-time mechanism."
"Create and confirm Manufacturing Orders this many days in advance, to have enough time to replenish components or manufacture semi-finished products.\n"
"Note that security lead times will also be considered when appropriate."
msgstr ""
#. module: mrp
+2 -2
View File
@@ -87,8 +87,8 @@ class MrpBom(models.Model):
help="Average lead time in days to manufacture this product. In the case of multi-level BOM, the manufacturing lead times of the components will be added. In case the product is subcontracted, this can be used to determine the date at which components should be sent to the subcontractor.")
days_to_prepare_mo = fields.Float(
string="Days to prepare Manufacturing Order", default=0.0,
help="Create and confirm Manufacturing Orders these many days in advance, to have enough time to replenish components or manufacture semi-finished products.\n"
"Note that this does not affect the MO scheduled date, which still respects the just-in-time mechanism.")
help="Create and confirm Manufacturing Orders this many days in advance, to have enough time to replenish components or manufacture semi-finished products.\n"
"Note that security lead times will also be considered when appropriate.")
_sql_constraints = [
('qty_positive', 'check (product_qty > 0)', 'The quantity to produce must be positive!'),
@@ -479,7 +479,7 @@ class ReportBomStructure(models.AbstractModel):
if not found_rules:
return {}
rules_delay = sum(rule.delay for rule in found_rules)
return self._format_route_info(found_rules, rules_delay, warehouse, product, bom, quantity)
return self.with_context(parent_bom=parent_bom)._format_route_info(found_rules, rules_delay, warehouse, product, bom, quantity)
@api.model
def _need_special_rules(self, product_info, parent_bom=False, parent_product=False):
@@ -497,12 +497,13 @@ class ReportBomStructure(models.AbstractModel):
wh_manufacture_rules = product._get_rules_from_location(product.property_stock_production, route_ids=warehouse.route_ids)
wh_manufacture_rules -= rules
rules_delay += sum(rule.delay for rule in wh_manufacture_rules)
manufacturing_lead = bom.company_id.manufacturing_lead if bom and bom.company_id else 0
return {
'route_type': 'manufacture',
'route_name': manufacture_rules[0].route_id.display_name,
'route_detail': bom.display_name,
'lead_time': bom.produce_delay + rules_delay,
'manufacture_delay': bom.produce_delay + rules_delay,
'lead_time': bom.produce_delay + rules_delay + manufacturing_lead,
'manufacture_delay': bom.produce_delay + rules_delay + manufacturing_lead,
}
return {}
+2 -1
View File
@@ -153,7 +153,8 @@
<div>
<field name="days_to_prepare_mo" class="oe_inline"/> days
<button name="action_compute_bom_days" string="Compute" type="object"
help="Compute the days required to resupply all components from BoM, by either buying or manufacturing the components and/or subassemblies."
help="Compute the days required to resupply all components from BoM, by either buying or manufacturing the components and/or subassemblies.
Also note that purchase security lead times will be added when appropriate."
class="oe_link pt-0"/>
</div>
</group>
@@ -12,13 +12,15 @@ class ReportBomStructure(models.AbstractModel):
if self._is_buy_route(rules, product, bom):
buy_rules = [rule for rule in rules if rule.action == 'buy']
supplier = product._select_seller(quantity=quantity, uom_id=product.uom_id)
parent_bom = self.env.context.get('parent_bom')
purchase_lead = parent_bom.company_id.days_to_purchase + parent_bom.company_id.po_lead if parent_bom and parent_bom.company_id else 0
if supplier:
return {
'route_type': 'buy',
'route_name': buy_rules[0].route_id.display_name,
'route_detail': supplier.display_name,
'lead_time': supplier.delay + rules_delay,
'supplier_delay': supplier.delay + rules_delay,
'lead_time': supplier.delay + rules_delay + purchase_lead,
'supplier_delay': supplier.delay + rules_delay + purchase_lead,
'supplier': supplier,
}
return res
@@ -614,3 +614,61 @@ class TestPurchaseMrpFlow(TransactionCase):
orderpoint_product = self.env['stock.warehouse.orderpoint'].search(
[('product_id', '=', product.id)])
self.assertEqual(orderpoint_product.route_id, manu_route, "The route manufacture should be set on the orderpoint")
def test_compute_bom_days_00(self):
"""Check Days to prepare Manufacturing Order are correctly computed when
Security Lead Time and Days to Purchase are set.
"""
purchase_route = self.env.ref("purchase_stock.route_warehouse0_buy")
manufacture_route = self.env['stock.route'].search([('name', '=', 'Manufacture')])
vendor = self.env['res.partner'].create({'name': 'super vendor'})
company_1 = self.kit_parent.bom_ids.company_id
company_2 = self.env['res.company'].create({
'name': 'TestCompany2',
})
company_1.po_lead = 0
company_1.days_to_purchase = 0
company_1.manufacturing_lead = 0
company_2.po_lead = 0
company_2.days_to_purchase = 0
company_2.manufacturing_lead = 0
components = self.component_a | self.component_b | self.component_c | self.component_d | self.component_e | self.component_f | self.component_g
kits = self.kit_parent | self.kit_1 | self.kit_2 | self.kit_3
kits.route_ids = [(6, 0, manufacture_route.ids)]
components.write({
'route_ids': [(6, 0, purchase_route.ids)],
'seller_ids': [(0, 0, {
'partner_id': vendor.id,
'min_qty': 1,
'price': 1,
'delay': 1,
})],
})
bom_kit_parent = self.kit_parent.bom_ids
bom_kit_parent.action_compute_bom_days()
self.assertEqual(bom_kit_parent.days_to_prepare_mo, 1)
# set "Security Lead Time" for Purchase and manufacturing, and "Days to Purchase"
company_1.po_lead = 10
company_1.days_to_purchase = 10
company_1.manufacturing_lead = 10
company_2.po_lead = 20
company_2.days_to_purchase = 20
company_2.manufacturing_lead = 20
# check "Security Lead Time" and "Days to Purchase" will also be included if bom has company_id
bom_kit_parent.action_compute_bom_days()
self.assertEqual(bom_kit_parent.days_to_prepare_mo, 10 + 10 + 10 + 10 + 1)
self.kit_1.bom_ids.company_id = company_2
bom_kit_parent.action_compute_bom_days()
self.assertEqual(bom_kit_parent.days_to_prepare_mo, 20 + 20 + 20 + 10 + 1)
# check "Security Lead Time" and "Days to Purchase" will won't be included if bom doesn't have company_id
kits.bom_ids.company_id = False
bom_kit_parent.action_compute_bom_days()
self.assertEqual(bom_kit_parent.days_to_prepare_mo, 1)