[FIX] sale_mrp: sell kit with dropshipped component

When selling a kit with a dropshipped component, the delivered quantity
will be incorrect

To reproduce the issue:
1. Create 3 consumable products P01, P02, P_kit:
    - P02:
        - Add a seller S
        - Enable the dropship route
2. Create a bill of materials:
    - Product: P_kit
    - Type: Kit
    - Components:
        - 1 x P01
        - 1 x P02
3. Create and confirm a sale order SO with 1 x P_kit
4. Confirm the generated purchase order (with vendor S)
5. Process the two pickings of SO
6. Go back to SO

Error: The delivered quantity of P_kit is 0 instead of 1

When computing the delivered quantity, because the `dropship` flag is
not set, we don't reach the revelant code:
https://github.com/odoo/odoo/blob/3db136f19480b31ca3f60a77c0c7354161bedde0/addons/sale_mrp/models/sale_mrp.py#L37-L44

OPW-2870893

closes odoo/odoo#94364

X-original-commit: fff6edad8cfb45b9a622bceefa4b83f620d7fe86
Signed-off-by: Arnold Moyaux (arm) <arm@odoo.com>
Signed-off-by: Adrien Widart <awt@odoo.com>
This commit is contained in:
Adrien Widart
2022-06-23 10:15:08 +02:00
parent 92a049ecff
commit e83120936d
2 changed files with 43 additions and 3 deletions
@@ -250,3 +250,44 @@ class TestSaleDropshippingFlows(TestMrpSubcontractingCommon):
sale_order.picking_ids.action_cancel()
self.assertEqual(sale_order.order_line.qty_delivered, 0.0)
def test_sale_kit_with_dropshipped_component(self):
"""
The test checks the delivered quantity of a kit when one of the
components is dropshipped
"""
compo01, compo02, kit = self.env['product.product'].create([{
'name': n,
'type': 'consu',
} for n in ['compo01', 'compo02', 'super kit']])
compo02.write({
'route_ids': [(6, 0, [self.dropship_route.id])],
'seller_ids': [(0, 0, {'partner_id': self.supplier.id})],
})
self.env['mrp.bom'].create({
'product_tmpl_id': kit.product_tmpl_id.id,
'product_qty': 1,
'type': 'phantom',
'bom_line_ids': [
(0, 0, {'product_id': compo01.id, 'product_qty': 1}),
(0, 0, {'product_id': compo02.id, 'product_qty': 1}),
],
})
sale_order = self.env['sale.order'].create({
'partner_id': self.customer.id,
'picking_policy': 'direct',
'order_line': [
(0, 0, {'name': kit.name, 'product_id': kit.id, 'product_uom_qty': 1}),
],
})
sale_order.action_confirm()
self.env['purchase.order'].search([], order='id desc', limit=1).button_confirm()
sale_order.picking_ids.move_ids.quantity_done = 1
sale_order.picking_ids[0].button_validate()
sale_order.picking_ids[1].button_validate()
self.assertEqual(sale_order.order_line.qty_delivered, 1.0)
+2 -3
View File
@@ -35,10 +35,9 @@ class SaleOrderLine(models.Model):
for order_line in self:
if order_line.qty_delivered_method == 'stock_move':
boms = order_line.move_ids.filtered(lambda m: m.state != 'cancel').mapped('bom_line_id.bom_id')
dropship = False
if not boms and any(m._is_dropshipped() for m in order_line.move_ids):
dropship = any(m._is_dropshipped() for m in order_line.move_ids)
if not boms and dropship:
boms = boms._bom_find(order_line.product_id, company_id=order_line.company_id.id, bom_type='phantom')[order_line.product_id]
dropship = True
# We fetch the BoMs of type kits linked to the order_line,
# the we keep only the one related to the finished produst.
# This bom should be the only one since bom_line_id was written on the moves