mirror of
https://github.com/bringout/oca-ocb-mrp.git
synced 2026-04-26 09:31:58 +02:00
19.0 vanilla
This commit is contained in:
parent
accf5918df
commit
6e65e8c877
688 changed files with 225434 additions and 199401 deletions
|
|
@ -1,13 +1,12 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from collections import defaultdict
|
||||
from datetime import datetime
|
||||
from dateutil.relativedelta import relativedelta
|
||||
|
||||
from odoo import api, fields, models, SUPERUSER_ID, _
|
||||
from odoo.osv import expression
|
||||
from odoo.addons.stock.models.stock_rule import ProcurementException
|
||||
from odoo.tools import float_compare, OrderedSet
|
||||
from odoo.fields import Domain, Command
|
||||
from odoo.tools import OrderedSet
|
||||
|
||||
|
||||
class StockRule(models.Model):
|
||||
|
|
@ -18,183 +17,25 @@ class StockRule(models.Model):
|
|||
|
||||
def _get_message_dict(self):
|
||||
message_dict = super(StockRule, self)._get_message_dict()
|
||||
source, destination, operation = self._get_message_values()
|
||||
manufacture_message = _('When products are needed in <b>%s</b>, <br/> a manufacturing order is created to fulfill the need.') % (destination)
|
||||
source, destination, direct_destination, operation = self._get_message_values()
|
||||
manufacture_message = _('When products are needed in <b>%s</b>, <br/> a manufacturing order is created to fulfill the need.', destination)
|
||||
if self.location_src_id:
|
||||
manufacture_message += _(' <br/><br/> The components will be taken from <b>%s</b>.') % (source)
|
||||
message_dict.update({
|
||||
'manufacture': manufacture_message
|
||||
})
|
||||
manufacture_message += _(' <br/><br/> The components will be taken from <b>%s</b>.', source)
|
||||
if direct_destination and not self.location_dest_from_rule:
|
||||
manufacture_message += _(' <br/><br/> The manufactured products will be moved towards <b>%(destination)s</b>, <br/> as specified from <b>%(operation)s</b> destination.', destination=direct_destination, operation=operation)
|
||||
message_dict['manufacture'] = manufacture_message
|
||||
return message_dict
|
||||
|
||||
@api.depends('action')
|
||||
def _compute_picking_type_code_domain(self):
|
||||
remaining = self.browse()
|
||||
super()._compute_picking_type_code_domain()
|
||||
for rule in self:
|
||||
if rule.action == 'manufacture':
|
||||
rule.picking_type_code_domain = 'mrp_operation'
|
||||
else:
|
||||
remaining |= rule
|
||||
super(StockRule, remaining)._compute_picking_type_code_domain()
|
||||
rule.picking_type_code_domain = rule.picking_type_code_domain or [] + ['mrp_operation']
|
||||
|
||||
def _should_auto_confirm_procurement_mo(self, p):
|
||||
return (not p.orderpoint_id and p.move_raw_ids) or (p.move_dest_ids.procure_method != 'make_to_order' and not p.move_raw_ids and not p.workorder_ids)
|
||||
|
||||
@api.model
|
||||
def _run_manufacture(self, procurements):
|
||||
productions_values_by_company = defaultdict(list)
|
||||
for procurement, rule in procurements:
|
||||
if float_compare(procurement.product_qty, 0, precision_rounding=procurement.product_uom.rounding) <= 0:
|
||||
# If procurement contains negative quantity, don't create a MO that would be for a negative value.
|
||||
continue
|
||||
bom = rule._get_matching_bom(procurement.product_id, procurement.company_id, procurement.values)
|
||||
|
||||
productions_values_by_company[procurement.company_id.id].append(rule._prepare_mo_vals(*procurement, bom))
|
||||
|
||||
for company_id, productions_values in productions_values_by_company.items():
|
||||
# create the MO as SUPERUSER because the current user may not have the rights to do it (mto product launched by a sale for example)
|
||||
productions = self.env['mrp.production'].with_user(SUPERUSER_ID).sudo().with_company(company_id).create(productions_values)
|
||||
productions.filtered(self._should_auto_confirm_procurement_mo).action_confirm()
|
||||
|
||||
for production in productions:
|
||||
origin_production = production.move_dest_ids and production.move_dest_ids[0].raw_material_production_id or False
|
||||
orderpoint = production.orderpoint_id
|
||||
if orderpoint and orderpoint.create_uid.id == SUPERUSER_ID and orderpoint.trigger == 'manual':
|
||||
production.message_post(
|
||||
body=_('This production order has been created from Replenishment Report.'),
|
||||
message_type='comment',
|
||||
subtype_xmlid='mail.mt_note')
|
||||
elif orderpoint:
|
||||
production.message_post_with_view(
|
||||
'mail.message_origin_link',
|
||||
values={'self': production, 'origin': orderpoint},
|
||||
subtype_id=self.env.ref('mail.mt_note').id)
|
||||
elif origin_production:
|
||||
production.message_post_with_view(
|
||||
'mail.message_origin_link',
|
||||
values={'self': production, 'origin': origin_production},
|
||||
subtype_id=self.env.ref('mail.mt_note').id)
|
||||
return True
|
||||
|
||||
@api.model
|
||||
def _run_pull(self, procurements):
|
||||
# Override to correctly assign the move generated from the pull
|
||||
# in its production order (pbm_sam only)
|
||||
for procurement, rule in procurements:
|
||||
warehouse_id = rule.warehouse_id
|
||||
if not warehouse_id:
|
||||
warehouse_id = rule.location_dest_id.warehouse_id
|
||||
manu_rule = rule.route_id.rule_ids.filtered(lambda r: r.action == 'manufacture' and r.warehouse_id == warehouse_id)
|
||||
if warehouse_id.manufacture_steps != 'pbm_sam' or not manu_rule:
|
||||
continue
|
||||
if rule.picking_type_id == warehouse_id.sam_type_id or (
|
||||
warehouse_id.sam_loc_id and warehouse_id.sam_loc_id.parent_path in rule.location_src_id.parent_path
|
||||
):
|
||||
if float_compare(procurement.product_qty, 0, precision_rounding=procurement.product_uom.rounding) < 0:
|
||||
procurement.values['group_id'] = procurement.values['group_id'].stock_move_ids.filtered(
|
||||
lambda m: m.state not in ['done', 'cancel']).move_orig_ids.group_id[:1]
|
||||
continue
|
||||
manu_type_id = manu_rule[0].picking_type_id
|
||||
if manu_type_id:
|
||||
name = manu_type_id.sequence_id.next_by_id()
|
||||
else:
|
||||
name = self.env['ir.sequence'].next_by_code('mrp.production') or _('New')
|
||||
# Create now the procurement group that will be assigned to the new MO
|
||||
# This ensure that the outgoing move PostProduction -> Stock is linked to its MO
|
||||
# rather than the original record (MO or SO)
|
||||
group = procurement.values.get('group_id')
|
||||
if group:
|
||||
procurement.values['group_id'] = group.copy({'name': name})
|
||||
else:
|
||||
procurement.values['group_id'] = self.env["procurement.group"].create({'name': name})
|
||||
return super()._run_pull(procurements)
|
||||
|
||||
def _get_custom_move_fields(self):
|
||||
fields = super(StockRule, self)._get_custom_move_fields()
|
||||
fields += ['bom_line_id']
|
||||
return fields
|
||||
|
||||
def _get_matching_bom(self, product_id, company_id, values):
|
||||
if values.get('bom_id', False):
|
||||
return values['bom_id']
|
||||
if values.get('orderpoint_id', False) and values['orderpoint_id'].bom_id:
|
||||
return values['orderpoint_id'].bom_id
|
||||
return self.env['mrp.bom']._bom_find(product_id, picking_type=self.picking_type_id, bom_type='normal', company_id=company_id.id)[product_id]
|
||||
|
||||
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=product_id.produce_delay)
|
||||
mo_values = {
|
||||
'origin': origin,
|
||||
'product_id': product_id.id,
|
||||
'product_description_variants': values.get('product_description_variants'),
|
||||
'product_qty': product_uom._compute_quantity(product_qty, bom.product_uom_id) if bom else product_qty,
|
||||
'product_uom_id': bom.product_uom_id.id if bom else product_uom.id,
|
||||
'location_src_id': self.location_src_id.id or self.picking_type_id.default_location_src_id.id or location_dest_id.id,
|
||||
'location_dest_id': location_dest_id.id,
|
||||
'bom_id': bom.id,
|
||||
'date_deadline': date_deadline,
|
||||
'date_planned_start': date_planned,
|
||||
'date_planned_finished': fields.Datetime.from_string(values['date_planned']),
|
||||
'procurement_group_id': False,
|
||||
'propagate_cancel': self.propagate_cancel,
|
||||
'orderpoint_id': values.get('orderpoint_id', False) and values.get('orderpoint_id').id,
|
||||
'picking_type_id': self.picking_type_id.id or values['warehouse_id'].manu_type_id.id,
|
||||
'company_id': company_id.id,
|
||||
'move_dest_ids': values.get('move_dest_ids') and [(4, x.id) for x in values['move_dest_ids']] or False,
|
||||
'user_id': False,
|
||||
}
|
||||
# Use the procurement group created in _run_pull mrp override
|
||||
# Preserve the origin from the original stock move, if available
|
||||
if location_dest_id.warehouse_id.manufacture_steps == 'pbm_sam' and values.get('move_dest_ids') and values.get('group_id') and values['move_dest_ids'][0].origin != values['group_id'].name:
|
||||
origin = values['move_dest_ids'][0].origin
|
||||
mo_values.update({
|
||||
'name': values['group_id'].name,
|
||||
'procurement_group_id': values['group_id'].id,
|
||||
'origin': origin,
|
||||
})
|
||||
return mo_values
|
||||
|
||||
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)
|
||||
if date_planned == format_date_planned:
|
||||
date_planned = date_planned - relativedelta(hours=1)
|
||||
return date_planned
|
||||
|
||||
def _get_lead_days(self, product, **values):
|
||||
"""Add the product and company manufacture delay to the cumulative delay
|
||||
and cumulative description.
|
||||
"""
|
||||
delay, delay_description = super()._get_lead_days(product, **values)
|
||||
bypass_delay_description = self.env.context.get('bypass_delay_description')
|
||||
manufacture_rule = self.filtered(lambda r: r.action == 'manufacture')
|
||||
if not manufacture_rule:
|
||||
return delay, delay_description
|
||||
manufacture_rule.ensure_one()
|
||||
manufacture_delay = product.produce_delay
|
||||
delay += manufacture_delay
|
||||
if not bypass_delay_description:
|
||||
delay_description.append((_('Manufacturing Lead Time'), _('+ %d day(s)', manufacture_delay)))
|
||||
security_delay = manufacture_rule.picking_type_id.company_id.manufacturing_lead
|
||||
delay += security_delay
|
||||
if not bypass_delay_description:
|
||||
delay_description.append((_('Manufacture Security Lead Time'), _('+ %d day(s)', security_delay)))
|
||||
days_to_order = values.get('days_to_order', product.product_tmpl_id.days_to_prepare_mo)
|
||||
if not bypass_delay_description:
|
||||
delay_description.append((_('Days to Supply Components'), _('+ %d day(s)', days_to_order)))
|
||||
return delay + days_to_order, delay_description
|
||||
|
||||
def _push_prepare_move_copy_values(self, move_to_copy, new_date):
|
||||
new_move_vals = super(StockRule, self)._push_prepare_move_copy_values(move_to_copy, new_date)
|
||||
new_move_vals['production_id'] = False
|
||||
return new_move_vals
|
||||
|
||||
|
||||
class ProcurementGroup(models.Model):
|
||||
_inherit = 'procurement.group'
|
||||
|
||||
mrp_production_ids = fields.One2many('mrp.production', 'procurement_group_id')
|
||||
if not p.move_raw_ids:
|
||||
return (not p.workorder_ids and (p.orderpoint_id or p.move_dest_ids.procure_method == 'make_to_stock'))
|
||||
return not p.orderpoint_id
|
||||
|
||||
@api.model
|
||||
def run(self, procurements, raise_user_error=True):
|
||||
|
|
@ -214,22 +55,201 @@ class ProcurementGroup(models.Model):
|
|||
if bom_kit:
|
||||
order_qty = procurement.product_uom._compute_quantity(procurement.product_qty, bom_kit.product_uom_id, round=False)
|
||||
qty_to_produce = (order_qty / bom_kit.product_qty)
|
||||
boms, bom_sub_lines = bom_kit.explode(procurement.product_id, qty_to_produce)
|
||||
_dummy, bom_sub_lines = bom_kit.explode(procurement.product_id, qty_to_produce, never_attribute_values=procurement.values.get("never_product_template_attribute_value_ids"))
|
||||
for bom_line, bom_line_data in bom_sub_lines:
|
||||
bom_line_uom = bom_line.product_uom_id
|
||||
quant_uom = bom_line.product_id.uom_id
|
||||
# recreate dict of values since each child has its own bom_line_id
|
||||
values = dict(procurement.values, bom_line_id=bom_line.id)
|
||||
component_qty, procurement_uom = bom_line_uom._adjust_uom_quantities(bom_line_data['qty'], quant_uom)
|
||||
procurements_without_kit.append(self.env['procurement.group'].Procurement(
|
||||
procurements_without_kit.append(self.env['stock.rule'].Procurement(
|
||||
bom_line.product_id, component_qty, procurement_uom,
|
||||
procurement.location_id, procurement.name,
|
||||
procurement.origin, procurement.company_id, values))
|
||||
else:
|
||||
procurements_without_kit.append(procurement)
|
||||
return super(ProcurementGroup, self).run(procurements_without_kit, raise_user_error=raise_user_error)
|
||||
return super().run(procurements_without_kit, raise_user_error=raise_user_error)
|
||||
|
||||
def _filter_warehouse_routes(self, product, warehouses, route):
|
||||
if any(rule.action == 'manufacture' for rule in route.rule_ids):
|
||||
if any(bom.type == 'normal' for bom in product.bom_ids):
|
||||
return super()._filter_warehouse_routes(product, warehouses, route)
|
||||
return False
|
||||
return super()._filter_warehouse_routes(product, warehouses, route)
|
||||
|
||||
@api.model
|
||||
def _run_manufacture(self, procurements):
|
||||
new_productions_values_by_company = defaultdict(lambda: defaultdict(list))
|
||||
for procurement, rule in procurements:
|
||||
if procurement.product_uom.compare(procurement.product_qty, 0) <= 0:
|
||||
# If procurement contains negative quantity, don't create a MO that would be for a negative value.
|
||||
continue
|
||||
bom = rule._get_matching_bom(procurement.product_id, procurement.company_id, procurement.values)
|
||||
|
||||
mo = self.env['mrp.production']
|
||||
if procurement.origin != 'MPS':
|
||||
domain = rule._make_mo_get_domain(procurement, bom)
|
||||
mo = self.env['mrp.production'].sudo().search(domain, limit=1)
|
||||
is_batch_size = bom and bom.enable_batch_size
|
||||
if not mo or is_batch_size:
|
||||
procurement_qty = procurement.product_qty
|
||||
batch_size = bom.product_uom_id._compute_quantity(bom.batch_size, procurement.product_uom) if is_batch_size else procurement_qty
|
||||
vals = rule._prepare_mo_vals(*procurement, bom)
|
||||
while procurement.product_uom.compare(procurement_qty, 0) > 0:
|
||||
new_productions_values_by_company[procurement.company_id.id]['values'].append({
|
||||
**vals,
|
||||
'product_qty': procurement.product_uom._compute_quantity(batch_size, bom.product_uom_id) if bom else procurement_qty,
|
||||
})
|
||||
new_productions_values_by_company[procurement.company_id.id]['procurements'].append(procurement)
|
||||
procurement_qty -= batch_size
|
||||
else:
|
||||
procurement_product_uom_qty = procurement.product_uom._compute_quantity(procurement.product_qty, procurement.product_id.uom_id)
|
||||
self.env['change.production.qty'].sudo().with_context(skip_activity=True).create({
|
||||
'mo_id': mo.id,
|
||||
'product_qty': mo.product_id.uom_id._compute_quantity((mo.product_uom_qty + procurement_product_uom_qty), mo.product_uom_id),
|
||||
}).change_prod_qty()
|
||||
|
||||
for company_id in new_productions_values_by_company:
|
||||
productions_vals_list = new_productions_values_by_company[company_id]['values']
|
||||
# create the MO as SUPERUSER because the current user may not have the rights to do it (mto product launched by a sale for example)
|
||||
productions = self.env['mrp.production'].with_user(SUPERUSER_ID).sudo().with_company(company_id).create(productions_vals_list)
|
||||
for mo in productions:
|
||||
if self._should_auto_confirm_procurement_mo(mo):
|
||||
mo.action_confirm()
|
||||
productions._post_run_manufacture(new_productions_values_by_company[company_id]['procurements'])
|
||||
return True
|
||||
|
||||
def _get_stock_move_values(self, product_id, product_qty, product_uom, location_id, name, origin, company_id, values):
|
||||
res = super()._get_stock_move_values(product_id, product_qty, product_uom, location_id, name, origin, company_id, values)
|
||||
res['production_group_id'] = values.get('production_group_id')
|
||||
return res
|
||||
|
||||
def _get_moves_to_assign_domain(self, company_id):
|
||||
domain = super(ProcurementGroup, self)._get_moves_to_assign_domain(company_id)
|
||||
domain = expression.AND([domain, [('production_id', '=', False)]])
|
||||
domain = super()._get_moves_to_assign_domain(company_id)
|
||||
return Domain(domain) & Domain('production_id', '=', False)
|
||||
|
||||
def _get_custom_move_fields(self):
|
||||
fields = super(StockRule, self)._get_custom_move_fields()
|
||||
fields += ['bom_line_id']
|
||||
return fields
|
||||
|
||||
def _get_matching_bom(self, product_id, company_id, values):
|
||||
if values.get('bom_id', False):
|
||||
return values['bom_id']
|
||||
if values.get('orderpoint_id', False) and values['orderpoint_id'].bom_id:
|
||||
return values['orderpoint_id'].bom_id
|
||||
bom = self.env['mrp.bom']._bom_find(product_id, picking_type=self.picking_type_id, bom_type='normal', company_id=company_id.id)[product_id]
|
||||
if bom:
|
||||
return bom
|
||||
return self.env['mrp.bom']._bom_find(product_id, picking_type=False, bom_type='normal', company_id=company_id.id)[product_id]
|
||||
|
||||
def _make_mo_get_domain(self, procurement, bom):
|
||||
domain = (
|
||||
('bom_id', '=', bom.id),
|
||||
('product_id', '=', procurement.product_id.id),
|
||||
('state', 'in', ['draft', 'confirmed']),
|
||||
('is_planned', '=', False),
|
||||
('picking_type_id', '=', self.picking_type_id.id),
|
||||
('company_id', '=', procurement.company_id.id),
|
||||
('user_id', '=', False),
|
||||
('reference_ids', '=', procurement.values.get('reference_ids', self.env['stock.reference']).ids),
|
||||
)
|
||||
if procurement.values.get('orderpoint_id'):
|
||||
procurement_date = datetime.combine(
|
||||
fields.Date.to_date(procurement.values['date_planned']) - relativedelta(days=int(bom.produce_delay)),
|
||||
datetime.max.time()
|
||||
)
|
||||
domain += ('|',
|
||||
'&', ('state', '=', 'draft'), ('date_deadline', '<=', procurement_date),
|
||||
'&', ('state', '=', 'confirmed'), ('date_start', '<=', procurement_date))
|
||||
return domain
|
||||
|
||||
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(bom, values)
|
||||
date_deadline = values.get('date_deadline') or date_planned + relativedelta(days=bom.produce_delay)
|
||||
picking_type = bom.picking_type_id or self.picking_type_id
|
||||
mo_values = {
|
||||
'origin': origin,
|
||||
'product_id': product_id.id,
|
||||
'product_description_variants': values.get('product_description_variants'),
|
||||
'never_product_template_attribute_value_ids': values.get('never_product_template_attribute_value_ids'),
|
||||
'product_qty': product_uom._compute_quantity(product_qty, bom.product_uom_id) if bom else product_qty,
|
||||
'product_uom_id': bom.product_uom_id.id if bom else product_uom.id,
|
||||
'location_src_id': picking_type.default_location_src_id.id,
|
||||
'location_dest_id': picking_type.default_location_dest_id.id or location_dest_id.id,
|
||||
'location_final_id': location_dest_id.id,
|
||||
'bom_id': bom.id,
|
||||
'date_deadline': date_deadline,
|
||||
'date_start': date_planned,
|
||||
'reference_ids': [Command.set(values.get('reference_ids', self.env['stock.reference']).ids)],
|
||||
'propagate_cancel': self.propagate_cancel,
|
||||
'orderpoint_id': values.get('orderpoint_id', False) and values.get('orderpoint_id').id,
|
||||
'picking_type_id': picking_type.id or values['warehouse_id'].manu_type_id.id,
|
||||
'company_id': company_id.id,
|
||||
'move_dest_ids': values.get('move_dest_ids') and [(4, x.id) for x in values['move_dest_ids']] or False,
|
||||
'user_id': False,
|
||||
}
|
||||
if self.location_dest_from_rule:
|
||||
mo_values['location_dest_id'] = self.location_dest_id.id
|
||||
return mo_values
|
||||
|
||||
def _get_date_planned(self, bom_id, values):
|
||||
format_date_planned = fields.Datetime.from_string(values['date_planned'])
|
||||
date_planned = format_date_planned - relativedelta(days=bom_id.produce_delay)
|
||||
if date_planned == format_date_planned:
|
||||
date_planned = date_planned - relativedelta(hours=1)
|
||||
return date_planned
|
||||
|
||||
def _get_lead_days(self, product, **values):
|
||||
"""Add the product and company manufacture delay to the cumulative delay
|
||||
and cumulative description.
|
||||
"""
|
||||
delays, delay_description = super()._get_lead_days(product, **values)
|
||||
bypass_delay_description = self.env.context.get('bypass_delay_description')
|
||||
manufacture_rule = self.filtered(lambda r: r.action == 'manufacture')
|
||||
if not manufacture_rule:
|
||||
return delays, delay_description
|
||||
manufacture_rule.ensure_one()
|
||||
bom = values.get('bom') or self.env['mrp.bom']._bom_find(product, picking_type=manufacture_rule.picking_type_id, company_id=manufacture_rule.company_id.id)[product]
|
||||
if not bom:
|
||||
delays['total_delay'] += 365
|
||||
delays['no_bom_found_delay'] += 365
|
||||
if not bypass_delay_description:
|
||||
delay_description.append((_('No BoM Found'), _('+ %s day(s)', 365)))
|
||||
manufacture_delay = bom.produce_delay
|
||||
delays['total_delay'] += manufacture_delay
|
||||
delays['manufacture_delay'] += manufacture_delay
|
||||
if not bypass_delay_description:
|
||||
delay_description.append((_('Production End Date'), manufacture_delay))
|
||||
delay_description.append((_('Manufacturing Lead Time'), _('+ %d day(s)', manufacture_delay)))
|
||||
if bom.type == 'normal':
|
||||
# pre-production rules
|
||||
warehouse = self.location_dest_id.warehouse_id
|
||||
for wh in warehouse:
|
||||
if wh.manufacture_steps != 'mrp_one_step':
|
||||
wh_manufacture_rules = product._get_rules_from_location(product.property_stock_production, route_ids=wh.pbm_route_id)
|
||||
extra_delays, extra_delay_description = (wh_manufacture_rules - self).with_context(global_horizon_days=0)._get_lead_days(product, **values)
|
||||
for key, value in extra_delays.items():
|
||||
delays[key] += value
|
||||
delay_description += extra_delay_description
|
||||
days_to_order = values.get('days_to_order', bom.days_to_prepare_mo)
|
||||
delays['total_delay'] += days_to_order
|
||||
if not bypass_delay_description:
|
||||
delay_description.append((_('Production Start Date'), days_to_order))
|
||||
delay_description.append((_('Days to Supply Components'), _('+ %d day(s)', days_to_order)))
|
||||
return delays, delay_description
|
||||
|
||||
def _push_prepare_move_copy_values(self, move_to_copy, new_date):
|
||||
new_move_vals = super()._push_prepare_move_copy_values(move_to_copy, new_date)
|
||||
new_move_vals['production_group_id'] = move_to_copy.production_group_id.id
|
||||
new_move_vals['production_id'] = False
|
||||
return new_move_vals
|
||||
|
||||
|
||||
class StockRoute(models.Model):
|
||||
_inherit = "stock.route"
|
||||
|
||||
def _is_valid_resupply_route_for_product(self, product):
|
||||
if any(rule.action == 'manufacture' for rule in self.rule_ids):
|
||||
return any(bom.type == 'normal' for bom in product.bom_ids)
|
||||
return super()._is_valid_resupply_route_for_product(product)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue