[FIX] sale_mrp, purchase_mrp: delivered quantity

- Create a manufactured Product A (sold as kit), invoicing based on
  delivered quantity.
- Create the associated BOM, e.g. contains 2 Products B.
- Create a SO with Product A, validate
- Change the BOM so it contains 2 Products C
- Validate the picking linked to the SO

The delivered quantity is not updated since the delivered products (B)
are not the same than the products of the BOM.

This should not be the case. Changing a BOM should not affect the
invoicing. To solve this, we simplify the check and only verifies that
all moves are done.

The same change is applied for PO.
This commit is contained in:
Nicolas Martinelli
2017-02-02 15:47:21 +01:00
parent 2ee2e065b6
commit 0a5a423bff
2 changed files with 14 additions and 43 deletions
+7 -21
View File
@@ -19,26 +19,12 @@ class PurchaseOrderLine(models.Model):
def _get_bom_delivered(self, bom=False):
self.ensure_one()
precision = self.env['decimal.precision'].precision_get('Product Unit of Measure')
# In the case of a kit, we need to check if all components are received or not.
# nothing policy. A product can have several BoMs, we don't know which one was used when the
# receipt was created.
bom_delivered = {}
# In the case of a kit, we need to check if all components are shipped. Since the BOM might
# have changed, we don't compute the quantities but verify the move state.
if bom:
bom_delivered[bom.id] = False
product_uom_qty_bom = self.product_uom._compute_quantity(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
for move in self.move_ids.filtered(lambda x: x.state == 'done' and x.product_id == bom_line.product_id):
qty += move.product_uom._compute_quantity(move.product_uom_qty, bom_line.product_uom_id)
if float_compare(qty, data['qty'], precision_digits=precision) < 0:
bom_delivered[bom.id] = False
break
else:
bom_delivered[bom.id] = True
if bom_delivered and any(bom_delivered.values()):
return self.product_qty
elif bom_delivered:
return 0.0
bom_delivered = all([move.state == 'done' for move in self.move_ids])
if bom_delivered:
return self.product_qty
else:
return 0.0
+7 -22
View File
@@ -30,31 +30,16 @@ class SaleOrderLine(models.Model):
@api.multi
def _get_delivered_qty(self):
self.ensure_one()
precision = self.env['decimal.precision'].precision_get('Product Unit of Measure')
# In the case of a kit, we need to check if all components are shipped. We use a all or
# nothing policy. A product can have several BoMs, we don't know which one was used when the
# delivery was created.
bom_delivered = {}
# In the case of a kit, we need to check if all components are shipped. Since the BOM might
# have changed, we don't compute the quantities but verify the move state.
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.product_uom._compute_quantity(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
for move in self.procurement_ids.mapped('move_ids'):
if move.state == 'done' and move.product_id.id == bom_line.product_id.id:
qty += move.product_uom._compute_quantity(move.product_uom_qty, bom_line.product_uom_id)
if float_compare(qty, data['qty'], precision_digits=precision) < 0:
bom_delivered[bom.id] = False
break
else:
bom_delivered[bom.id] = True
if bom_delivered and any(bom_delivered.values()):
return self.product_uom_qty
elif bom_delivered:
return 0.0
bom_delivered = all([move.state == 'done' for move in self.procurement_ids.mapped('move_ids')])
if bom_delivered:
return self.product_uom_qty
else:
return 0.0
return super(SaleOrderLine, self)._get_delivered_qty()