[FIX] mrp: correct interpretation of explode's quantity parameter

In previous versions, the quantity passed to the bom_explode was the number
of times you needed to count the BoM.  If the BoM was for 2 dozens and you pass
48 units, 2 was passed to the bom_explode method.  We are now doing the same
for the explode method and we check it is called this way everywhere.
This commit is contained in:
Josse Colpaert
2016-09-28 12:38:13 +02:00
parent fbab021a9b
commit 153a6d0814
6 changed files with 16 additions and 15 deletions
+5 -4
View File
@@ -113,7 +113,8 @@ class MrpBom(models.Model):
def explode(self, product, quantity, picking_type=False):
"""
Explodes the BoM and creates two lists with all the information you need: bom_done and line_done
Quantity should be passed in the UoM of the BoM (don't divide by its quantity)
Quantity describes the number of times you need the BoM: so the quantity divided by the number created by the BoM
and converted into its UoM
"""
boms_done = [(self, {'qty': quantity, 'product': product, 'original_qty': quantity, 'parent_line': False})]
lines_done = []
@@ -129,11 +130,11 @@ class MrpBom(models.Model):
if current_line.product_id.product_tmpl_id in templates_done:
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
line_quantity = current_qty * current_line.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, current_line) for line in bom.bom_line_ids] + bom_lines
converted_line_quantity = self.env['product.uom']._compute_qty_obj(current_line.product_uom_id, line_quantity / bom.product_qty, bom.product_uom_id)
bom_lines = [(line, current_line.product_id, converted_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, 'parent_line': current_line}))
else:
+5 -5
View File
@@ -264,7 +264,7 @@ class MrpProduction(models.Model):
def _generate_moves(self):
for production in self:
production._generate_finished_moves()
factor = self.env['product.uom']._compute_qty(production.product_uom_id.id, production.product_qty, production.bom_id.product_uom_id.id)
factor = self.env['product.uom']._compute_qty(production.product_uom_id.id, production.product_qty, production.bom_id.product_uom_id.id) / production.bom_id.product_qty
boms, lines = production.bom_id.explode(production.product_id, factor, picking_type=production.bom_id.picking_type_id)
production._generate_raw_moves(lines)
# Check for all draft moves whether they are mto or not
@@ -382,7 +382,7 @@ class MrpProduction(models.Model):
orders_to_plan = self.filtered(lambda order: order.routing_id and order.state == 'confirmed')
UoM = self.env['product.uom']
for order in orders_to_plan:
quantity = UoM._compute_qty_obj(order.product_uom_id, order.product_qty, order.bom_id.product_uom_id)
quantity = UoM._compute_qty_obj(order.product_uom_id, order.product_qty, order.bom_id.product_uom_id) / order.bom_id.product_qty
boms, lines = order.bom_id.explode(order.product_id, quantity, picking_type=order.bom_id.picking_type_id)
order._generate_workorders(boms)
orders_to_plan.write({'state': 'planned'})
@@ -402,18 +402,18 @@ class MrpProduction(models.Model):
BoMs
"""
workorders = self.env['mrp.workorder']
qty = bom_data['qty']
bom_qty = bom_data['qty']
# Initial qty producing
if self.product_id.tracking == 'serial':
quantity = 1.0
else:
quantity = self.product_qty - sum(self.move_finished_ids.mapped('quantity_done'))
quantity = quantity if (quantity > 0) else 0
# TDE FIXME: what is qty compared to quantity ??
for operation in bom.routing_id.operation_ids:
# create workorder
cycle_number = math.ceil(qty / bom.product_qty / operation.workcenter_id.capacity) # TODO: float_round UP
cycle_number = math.ceil(bom_qty / operation.workcenter_id.capacity) # TODO: float_round UP
duration_expected = (operation.workcenter_id.time_start +
operation.workcenter_id.time_stop +
cycle_number * operation.time_cycle * 100.0 / operation.workcenter_id.time_efficiency)
+2 -2
View File
@@ -154,8 +154,8 @@ class MrpUnbuild(models.Model):
def _generate_produce_moves(self):
moves = self.env['stock.move']
for unbuild in self:
factor = self.env['product.uom']._compute_qty(unbuild.product_uom_id.id, unbuild.product_qty, unbuild.bom_id.product_uom_id.id)
boms, lines = unbuild.bom_id.explode(unbuild.product_id, factor / unbuild.bom_id.product_qty, picking_type=unbuild.bom_id.picking_type_id)
factor = self.env['product.uom']._compute_qty(unbuild.product_uom_id.id, unbuild.product_qty, unbuild.bom_id.product_uom_id.id) / unbuild.bom_id.product_qty
boms, lines = unbuild.bom_id.explode(unbuild.product_id, factor, picking_type=unbuild.bom_id.picking_type_id)
for line, line_data in lines:
moves += unbuild._generate_move_from_bom_line(line, line_data['qty'])
return moves
+2 -2
View File
@@ -44,7 +44,7 @@ class ChangeProductionQty(models.TransientModel):
raise UserError(_("You have already processed %d. Please input a quantity higher than %d ")%(produced, produced))
production.write({'product_qty': wizard.product_qty})
bom_point = production.bom_id
factor = self.env['product.uom']._compute_qty(production.product_uom_id.id, production.product_qty - production.qty_produced, production.bom_id.product_uom_id.id)
factor = self.env['product.uom']._compute_qty(production.product_uom_id.id, production.product_qty - production.qty_produced, production.bom_id.product_uom_id.id) / production.bom_id.product_qty
boms, lines = production.bom_id.explode(production.product_id, factor, picking_type=production.bom_id.picking_type_id)
for line, line_data in lines:
production._update_raw_move(line, line_data)
@@ -61,7 +61,7 @@ class ChangeProductionQty(models.TransientModel):
wo.qty_producing = quantity
if wo.qty_produced < wo.qty_production and wo.state == 'done':
wo.state = 'progress'
# assign moves; last operation receive all unassigned moves (which case ?)
# assign moves; last operation receive all unassigned moves
operation = wo.operation_id
# TODO: following could be put in a function as it is similar as code in _workorders_create
+1 -1
View File
@@ -27,7 +27,7 @@ class PurchaseOrderLine(models.Model):
bom_delivered = {}
if bom:
bom_delivered[bom.id] = False
product_uom_qty_bom = self.env['product.uom']._compute_qty_obj(self.product_uom, self.product_qty, bom.product_uom_id)
product_uom_qty_bom = self.env['product.uom']._compute_qty_obj(self.product_uom, self.product_qty, bom.product_uom_id) / bom.product_qty
boms, lines = bom.explode(self.product_id, product_uom_qty_bom)
for bom_line, data in lines:
qty = 0.0
+1 -1
View File
@@ -38,7 +38,7 @@ class SaleOrderLine(models.Model):
bom = self.env['mrp.bom']._bom_find(product=self.product_id)
if bom and bom.type == 'phantom':
bom_delivered[bom.id] = False
product_uom_qty_bom = self.env['product.uom']._compute_qty_obj(self.product_uom, self.product_uom_qty, bom.product_uom_id)
product_uom_qty_bom = self.env['product.uom']._compute_qty_obj(self.product_uom, self.product_uom_qty, bom.product_uom_id) / bom.product_qty
boms, lines = bom.explode(self.product_id, product_uom_qty_bom)
for bom_line, data in lines:
qty = 0.0