diff --git a/addons/mrp/models/mrp_bom.py b/addons/mrp/models/mrp_bom.py index ab22fbc8584..91ee51bd9f1 100644 --- a/addons/mrp/models/mrp_bom.py +++ b/addons/mrp/models/mrp_bom.py @@ -111,13 +111,13 @@ class MrpBom(models.Model): return self.search(domain, order='sequence, product_id', limit=1) def explode(self, product, quantity, picking_type=False): - boms_done = [(self, {'qty': quantity, 'product': product, 'original_qty': quantity})] + boms_done = [(self, {'qty': quantity, 'product': product, 'original_qty': quantity, 'parent_line': False})] lines_done = [] templates_done = product.product_tmpl_id - bom_lines = [(bom_line, product, quantity) for bom_line in self.bom_line_ids] + bom_lines = [(bom_line, product, quantity, False) for bom_line in self.bom_line_ids] while bom_lines: - current_line, current_product, current_qty = bom_lines[0] + current_line, current_product, current_qty, parent_line = bom_lines[0] bom_lines = bom_lines[1:] if current_line._skip_bom_line(current_product): @@ -126,15 +126,14 @@ class MrpBom(models.Model): raise UserError(_('Recursion error! A product with a Bill of Material should not have itself in its BoM or child BoMs!')) line_quantity = current_qty * current_line.product_qty / current_line.bom_id.product_qty - bom = self._bom_find(product=current_line.product_id, picking_type=picking_type or self.picking_type_id, company_id=self.company_id.id) if bom.type == 'phantom': converted_line_quantity = self.env['product.uom']._compute_qty_obj(current_line.product_uom_id, line_quantity, bom.product_uom_id) - bom_lines = [(line, current_line.product_id, line_quantity) for line in bom.bom_line_ids] + bom_lines + bom_lines = [(line, current_line.product_id, line_quantity, current_line) for line in bom.bom_line_ids] + bom_lines templates_done |= current_line.product_id.product_tmpl_id - boms_done.append((bom, {'qty': converted_line_quantity, 'product': current_product, 'original_qty': quantity})) + boms_done.append((bom, {'qty': converted_line_quantity, 'product': current_product, 'original_qty': quantity, 'parent_line': current_line})) else: - lines_done.append((current_line, {'qty': line_quantity, 'product': current_product, 'original_qty': quantity})) + lines_done.append((current_line, {'qty': line_quantity, 'product': current_product, 'original_qty': quantity, 'parent_line': parent_line})) return boms_done, lines_done diff --git a/addons/mrp/models/mrp_production.py b/addons/mrp/models/mrp_production.py index 503be6e2ac9..248ec9b1954 100644 --- a/addons/mrp/models/mrp_production.py +++ b/addons/mrp/models/mrp_production.py @@ -296,10 +296,13 @@ class MrpProduction(models.Model): self.ensure_one() moves = self.env['stock.move'] for bom_line, line_data in exploded_lines: - moves += self._generate_raw_move(bom_line, line_data['qty']) + moves += self._generate_raw_move(bom_line, line_data) return moves - def _generate_raw_move(self, bom_line, quantity): + def _generate_raw_move(self, bom_line, line_data): + quantity = line_data['qty'] + # alt_op needed for the case when you explode phantom bom and all the lines will be consumed in the operation given by the parent bom line + alt_op = line_data['parent_line'] and line_data['parent_line'].operation_id.id or False if bom_line.child_bom_id and bom_line.child_bom_id.type == 'phantom': return self.env['stock.move'] if bom_line.product_id.type not in ['product', 'consu']: @@ -321,7 +324,7 @@ class MrpProduction(models.Model): 'location_dest_id': self.product_id.property_stock_production.id, 'raw_material_production_id': self.id, 'company_id': self.company_id.id, - 'operation_id': bom_line.operation_id.id, + 'operation_id': bom_line.operation_id.id or alt_op, 'price_unit': bom_line.product_id.standard_price, 'procure_method': 'make_to_stock', 'origin': self.name, @@ -382,15 +385,18 @@ class MrpProduction(models.Model): def _generate_workorders(self, exploded_boms): workorders = self.env['mrp.workorder'] for bom, bom_data in exploded_boms: - workorders += self._workorders_create(bom, bom_data['qty']) + # If the routing of the parent BoM and phantom BoM are the same, don't recreate work orders, but use one master routing + if bom.routing_id.id and (not bom_data['parent_line'] or bom_data['parent_line'].bom_id.routing_id.id != bom.routing_id.id): + workorders += self._workorders_create(bom, bom_data) return workorders - def _workorders_create(self, bom, qty): + def _workorders_create(self, bom, bom_data): """ :param bom: in case of recursive boms: we could create work orders for child BoMs """ workorders = self.env['mrp.workorder'] + qty = bom_data['qty'] use_serial = any(product.tracking == 'serial' for product in self.mapped('move_finished_ids.product_id')) if use_serial: