[IMP] mrp{,_subcontracting_purchase}, {purchase_,}stock: add DTPMO to lead days

For subcontracting, we need to consider both vendor lead time and
manufacturing lead time, and DTPMO (Days To Prepare MO) on the BOM.
Subcontracting delay =
    max(Vendor lead time, Manufacturing lead time + DTPMO) + Days to Purchase + Purchase security lead time

Same thing applied to Bom overview, except:
1. Availability state will be computed based on the delay time of it's
   components. DTPMO on the bom won't be take into account.
2. Lead time will use the DTPMO on the BOM. DTPMO will be added to
   the lead time when it's a manufacturing bom or when it's a
   subcontracting bom with Manufacturing Lead Time + DTPMO > Vendor Lead Time

Task-3081481

Part-of: odoo/odoo#137810
This commit is contained in:
yhu-odoo
2023-11-06 13:58:36 +00:00
committed by William Henrotin
parent 6c749a4b0d
commit 78e44dc5a3
17 changed files with 235 additions and 63 deletions
@@ -72,15 +72,16 @@ class ReportBomStructure(models.AbstractModel):
subcontract_rules = [rule for rule in rules if rule.action == 'buy' and bom and bom.type == 'subcontract']
if subcontract_rules:
supplier = product._select_seller(quantity=quantity, uom_id=product.uom_id, params={'subcontractor_ids': bom.subcontractor_ids})
# for subcontracting, we can't decide the lead time without component's resupply availability
# we only return necessary info and calculate the lead time late when we have component's data
if supplier:
return {
'route_type': 'subcontract',
'route_name': subcontract_rules[0].route_id.display_name,
'route_detail': supplier.display_name,
'lead_time': supplier.delay + rules_delay,
'supplier_delay': supplier.delay + rules_delay,
'manufacture_delay': bom.produce_delay,
'lead_time': rules_delay,
'supplier': supplier,
'bom': bom,
}
return res
@@ -106,11 +107,16 @@ class ReportBomStructure(models.AbstractModel):
@api.model
def _get_resupply_availability(self, route_info, components):
resupply_state, resupply_delay = super()._get_resupply_availability(route_info, components)
if route_info.get('route_type') == 'subcontract':
max_component_delay = self._get_max_component_delay(components)
if max_component_delay is False:
return ('unavailable', False)
produce_delay = route_info.get('manufacture_delay', 0) + max_component_delay
supplier_delay = route_info.get('supplier_delay', 0)
return ('estimated', max(produce_delay, supplier_delay))
return super()._get_resupply_availability(route_info, components)
# Calculate the lead time for subcontracting, keep same as `_get_lead_days`
vendor_lead_time = route_info['supplier'].delay
manufacture_lead_time = route_info['bom'].produce_delay
subcontract_delay = resupply_delay if resupply_delay else 0
subcontract_delay += max(vendor_lead_time, manufacture_lead_time + max_component_delay)
route_info['lead_time'] += max(vendor_lead_time, manufacture_lead_time + route_info['bom'].days_to_prepare_mo)
return ('estimated', subcontract_delay)
return (resupply_state, resupply_delay)