diff --git a/addons/mrp/models/mrp_production.py b/addons/mrp/models/mrp_production.py index fb1a1131def..b0cdaa89b2d 100644 --- a/addons/mrp/models/mrp_production.py +++ b/addons/mrp/models/mrp_production.py @@ -658,7 +658,7 @@ class MrpProduction(models.Model): for production in self: if not production.date_planned_start or production.is_planned: continue - days_delay = production.product_id.produce_delay + production.company_id.manufacturing_lead + days_delay = production.product_id.produce_delay date_planned_finished = production.date_planned_start + relativedelta(days=days_delay) if date_planned_finished == production.date_planned_start: date_planned_finished = date_planned_finished + relativedelta(hours=1) @@ -904,7 +904,6 @@ class MrpProduction(models.Model): def _get_date_planned_finished(self): date_planned_finished = self.date_planned_start + relativedelta(days=self.product_id.produce_delay) - date_planned_finished = date_planned_finished + relativedelta(days=self.company_id.manufacturing_lead) if date_planned_finished == self.date_planned_start: date_planned_finished = date_planned_finished + relativedelta(hours=1) return date_planned_finished diff --git a/addons/mrp/models/product.py b/addons/mrp/models/product.py index 787c5c5c8bd..eeaf8deba20 100644 --- a/addons/mrp/models/product.py +++ b/addons/mrp/models/product.py @@ -33,6 +33,10 @@ class ProductTemplate(models.Model): 'Manufacturing Lead Time', default=0.0, 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.") is_kits = fields.Boolean(compute='_compute_is_kits', compute_sudo=False) + 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.") def _compute_bom_count(self): for product in self: diff --git a/addons/mrp/models/stock_move.py b/addons/mrp/models/stock_move.py index 77660241770..3ae798e8048 100644 --- a/addons/mrp/models/stock_move.py +++ b/addons/mrp/models/stock_move.py @@ -2,6 +2,7 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. from collections import defaultdict +from dateutil.relativedelta import relativedelta from odoo import api, Command, fields, models from odoo.osv import expression from odoo.tools import float_compare, float_round, float_is_zero, OrderedSet @@ -547,3 +548,9 @@ class StockMove(models.Model): res = super()._prepare_procurement_values() res['bom_line_id'] = self.bom_line_id.id return res + + def _get_mto_procurement_date(self): + date = super()._get_mto_procurement_date() + if 'manufacture' in self.product_id._get_rules_from_location(self.location_id).mapped('action'): + date -= relativedelta(days=self.company_id.manufacturing_lead) + return date diff --git a/addons/mrp/models/stock_orderpoint.py b/addons/mrp/models/stock_orderpoint.py index 2e5022c7d27..eb4ac948bc3 100644 --- a/addons/mrp/models/stock_orderpoint.py +++ b/addons/mrp/models/stock_orderpoint.py @@ -4,6 +4,7 @@ from odoo import _, api, fields, models from odoo.tools.float_utils import float_is_zero from odoo.osv.expression import AND +from dateutil.relativedelta import relativedelta class StockWarehouseOrderpoint(models.Model): @@ -13,6 +14,7 @@ class StockWarehouseOrderpoint(models.Model): bom_id = fields.Many2one( 'mrp.bom', string='Bill of Materials', check_company=True, domain="[('type', '=', 'normal'), '&', '|', ('company_id', '=', company_id), ('company_id', '=', False), '|', ('product_id', '=', product_id), '&', ('product_id', '=', False), ('product_tmpl_id', '=', product_tmpl_id)]") + manufacturing_visibility_days = fields.Float(default=0.0, help="Visibility Days applied on the manufacturing routes.") def _get_replenishment_order_notification(self): self.ensure_one() @@ -45,6 +47,27 @@ class StockWarehouseOrderpoint(models.Model): for orderpoint in self: orderpoint.show_bom = orderpoint.route_id.id in manufacture_route + def _compute_visibility_days(self): + res = super()._compute_visibility_days() + for orderpoint in self: + if 'manufacture' in orderpoint.rule_ids.mapped('action'): + orderpoint.visibility_days = orderpoint.manufacturing_visibility_days + return res + + def _set_visibility_days(self): + res = super()._set_visibility_days() + for orderpoint in self: + if 'manufacture' in orderpoint.rule_ids.mapped('action'): + orderpoint.manufacturing_visibility_days = orderpoint.visibility_days + return res + + def _compute_days_to_order(self): + res = super()._compute_days_to_order() + for orderpoint in self: + if 'manufacture' in orderpoint.rule_ids.mapped('action'): + orderpoint.days_to_order = orderpoint.product_id.days_to_prepare_mo + return res + def _quantity_in_progress(self): bom_kits = self.env['mrp.bom']._bom_find(self.product_id, bom_type='phantom') bom_kit_orderpoints = { @@ -109,6 +132,12 @@ class StockWarehouseOrderpoint(models.Model): orderpoint_wh_bom.route_id = route_id[0].id return super()._set_default_route_id() + def _get_orderpoint_procurement_date(self): + date = super()._get_orderpoint_procurement_date() + if any(rule.action == 'manufacture' for rule in self.rule_ids): + date -= relativedelta(days=self.company_id.manufacturing_lead) + return date + def _prepare_procurement_values(self, date=False, group=False): values = super()._prepare_procurement_values(date=date, group=group) values['bom_id'] = self.bom_id diff --git a/addons/mrp/models/stock_rule.py b/addons/mrp/models/stock_rule.py index 8af591ea519..82da0108cd5 100644 --- a/addons/mrp/models/stock_rule.py +++ b/addons/mrp/models/stock_rule.py @@ -109,7 +109,7 @@ class StockRule(models.Model): def _prepare_mo_vals(self, product_id, product_qty, product_uom, location_dest_id, name, origin, company_id, values, bom): date_planned = self._get_date_planned(product_id, company_id, values) - date_deadline = values.get('date_deadline') or date_planned + relativedelta(days=company_id.manufacturing_lead) + relativedelta(days=product_id.produce_delay) + date_deadline = values.get('date_deadline') or date_planned + relativedelta(days=product_id.produce_delay) mo_values = { 'origin': origin, 'product_id': product_id.id, @@ -144,7 +144,6 @@ class StockRule(models.Model): def _get_date_planned(self, product_id, company_id, values): format_date_planned = fields.Datetime.from_string(values['date_planned']) date_planned = format_date_planned - relativedelta(days=product_id.produce_delay) - date_planned = date_planned - relativedelta(days=company_id.manufacturing_lead) if date_planned == format_date_planned: date_planned = date_planned - relativedelta(hours=1) return date_planned diff --git a/addons/mrp/views/product_views.xml b/addons/mrp/views/product_views.xml index 644ed616540..5ea072a561e 100644 --- a/addons/mrp/views/product_views.xml +++ b/addons/mrp/views/product_views.xml @@ -12,6 +12,10 @@
days
+