From 0171f4a1e4a0cb9b0171e329e937385e957dd3bb Mon Sep 17 00:00:00 2001 From: yhu-odoo Date: Thu, 2 Mar 2023 14:39:23 +0000 Subject: [PATCH] [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 --- addons/mrp/i18n/mrp.pot | 6 +- addons/mrp/models/mrp_bom.py | 4 +- addons/mrp/report/mrp_report_bom_structure.py | 7 ++- addons/mrp/views/mrp_bom_views.xml | 3 +- .../report/mrp_report_bom_structure.py | 6 +- .../tests/test_purchase_mrp_flow.py | 58 +++++++++++++++++++ 6 files changed, 74 insertions(+), 10 deletions(-) diff --git a/addons/mrp/i18n/mrp.pot b/addons/mrp/i18n/mrp.pot index a018a25a3b3..351c4e3515e 100644 --- a/addons/mrp/i18n/mrp.pot +++ b/addons/mrp/i18n/mrp.pot @@ -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 diff --git a/addons/mrp/models/mrp_bom.py b/addons/mrp/models/mrp_bom.py index 1ca8bee00f3..8fd0c5164a3 100644 --- a/addons/mrp/models/mrp_bom.py +++ b/addons/mrp/models/mrp_bom.py @@ -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!'), diff --git a/addons/mrp/report/mrp_report_bom_structure.py b/addons/mrp/report/mrp_report_bom_structure.py index 1babde69ca8..3e253feb3f4 100644 --- a/addons/mrp/report/mrp_report_bom_structure.py +++ b/addons/mrp/report/mrp_report_bom_structure.py @@ -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 {} diff --git a/addons/mrp/views/mrp_bom_views.xml b/addons/mrp/views/mrp_bom_views.xml index 926f3d9be3b..e00a15bea7e 100644 --- a/addons/mrp/views/mrp_bom_views.xml +++ b/addons/mrp/views/mrp_bom_views.xml @@ -153,7 +153,8 @@
days
diff --git a/addons/purchase_mrp/report/mrp_report_bom_structure.py b/addons/purchase_mrp/report/mrp_report_bom_structure.py index edca457206f..a9a64c39329 100644 --- a/addons/purchase_mrp/report/mrp_report_bom_structure.py +++ b/addons/purchase_mrp/report/mrp_report_bom_structure.py @@ -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 diff --git a/addons/purchase_mrp/tests/test_purchase_mrp_flow.py b/addons/purchase_mrp/tests/test_purchase_mrp_flow.py index 09759f194ad..02d6e1b2928 100644 --- a/addons/purchase_mrp/tests/test_purchase_mrp_flow.py +++ b/addons/purchase_mrp/tests/test_purchase_mrp_flow.py @@ -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)