[FIX] sale_mrp : wrong delivered quantities on kit return
Issue: When returning a product sold that is only made of kits and
validating the return, the delivered quantities of the sales order was
set back to the full amount delivered
Steps to reproduce :
1) Install MRP and Sales
2) Create a BoM Kit for a new product [Nested Kit] that has one or
more consumable or storable product as component
3) Create a BoM Kit for a new product [Main Kit] that has
[Nested Kit] as component
4) Create a SO for [Main Kit], confirm, validate delivery
5) Check SO, 1 product is delivered (correct)
6) Go back to the Delivery, create a return for the delivery
(don't validate)
7) Check SO, 0 product is delivered (correct)
8) Now validate the return for the delivery
-> Check SO, 1 product is delivered (bug)
Why is that a bug:
Since the Main Kit was returned, the delivered should be 0 and not
the full amount initially delivered. It was set back to 1 because we
didn't look at the type of picking, when computing the quantity
delivered, the fall back considered that if all the moves were done,
everything was delivered, but it is the opposite when returning
opw-2542337
closes odoo/odoo#78915
X-original-commit: 206c9c8da4d8001525a540561174326e49d1188d
Signed-off-by: Arnold Moyaux <arm@odoo.com>
Signed-off-by: William Henrotin (whe) <whe@odoo.com>
This commit is contained in:
committed by
William Henrotin
parent
6a7c1c51ce
commit
707cd830f8
@@ -114,7 +114,8 @@ class SaleOrderLine(models.Model):
|
||||
# when the product sold is made only of kits. In this case, the BOM of the stock moves
|
||||
# do not correspond to the product sold => no relevant BOM.
|
||||
elif boms:
|
||||
if all(m.state == 'done' for m in order_line.move_ids):
|
||||
# if the move is ingoing, the product **sold** has delivered qty 0
|
||||
if all(m.state == 'done' and m.location_dest_id.usage == 'customer' for m in order_line.move_ids):
|
||||
order_line.qty_delivered = order_line.product_uom_qty
|
||||
else:
|
||||
order_line.qty_delivered = 0.0
|
||||
|
||||
@@ -1755,3 +1755,92 @@ class TestSaleMrpFlow(ValuationReconciliationTestCommon):
|
||||
check_cogs_entry_values(self.invoice_1, 40)
|
||||
# Check that the cost of Good Sold entries for variant 2 are equal to 2 * 10 = 20
|
||||
check_cogs_entry_values(self.invoice_2, 20)
|
||||
|
||||
def test_13_so_return_kit(self):
|
||||
"""
|
||||
Test that when returning a SO containing only a kit that contains another kit, the
|
||||
SO delivered quantities is set to 0 (with the all-or-nothing policy).
|
||||
Products :
|
||||
Main Kit
|
||||
Nested Kit
|
||||
Screw
|
||||
BoMs :
|
||||
Main Kit BoM (kit), recipe :
|
||||
Nested Kit Bom (kit), recipe :
|
||||
Screw
|
||||
Business flow :
|
||||
Create those
|
||||
Create a Sales order selling one Main Kit BoM
|
||||
Confirm the sales order
|
||||
Validate the delivery (outgoing) (qty_delivered = 1)
|
||||
Create a return for the delivery
|
||||
Validate return for delivery (ingoing) (qty_delivered = 0)
|
||||
"""
|
||||
main_kit_product = self.env['product.product'].create({
|
||||
'name': 'Main Kit',
|
||||
'type': 'product',
|
||||
})
|
||||
|
||||
nested_kit_product = self.env['product.product'].create({
|
||||
'name': 'Nested Kit',
|
||||
'type': 'product',
|
||||
})
|
||||
|
||||
product = self.env['product.product'].create({
|
||||
'name': 'Screw',
|
||||
'type': 'product',
|
||||
})
|
||||
|
||||
self.env['mrp.bom'].create({
|
||||
'product_id': nested_kit_product.id,
|
||||
'product_tmpl_id': nested_kit_product.product_tmpl_id.id,
|
||||
'product_qty': 1.0,
|
||||
'type': 'phantom',
|
||||
'bom_line_ids': [(5, 0), (0, 0, {'product_id': product.id})]
|
||||
})
|
||||
|
||||
self.env['mrp.bom'].create({
|
||||
'product_id': main_kit_product.id,
|
||||
'product_tmpl_id': main_kit_product.product_tmpl_id.id,
|
||||
'product_qty': 1.0,
|
||||
'type': 'phantom',
|
||||
'bom_line_ids': [(5, 0), (0, 0, {'product_id': nested_kit_product.id})]
|
||||
})
|
||||
|
||||
# Create a SO for product Main Kit Product
|
||||
order_form = Form(self.env['sale.order'])
|
||||
order_form.partner_id = self.env.ref('base.res_partner_2')
|
||||
with order_form.order_line.new() as line:
|
||||
line.product_id = main_kit_product
|
||||
line.product_uom_qty = 1
|
||||
order = order_form.save()
|
||||
order.action_confirm()
|
||||
qty_del_not_yet_validated = sum(sol.qty_delivered for sol in order.order_line)
|
||||
self.assertEqual(qty_del_not_yet_validated, 0.0, 'No delivery validated yet')
|
||||
|
||||
# Validate delivery
|
||||
pick = order.picking_ids
|
||||
pick.move_ids.write({'quantity_done': 1})
|
||||
pick.button_validate()
|
||||
qty_del_validated = sum(sol.qty_delivered for sol in order.order_line)
|
||||
self.assertEqual(qty_del_validated, 1.0, 'The order went from warehouse to client, so it has been delivered')
|
||||
|
||||
# 1 was delivered, now create a return
|
||||
stock_return_picking_form = Form(self.env['stock.return.picking'].with_context(
|
||||
active_ids=pick.ids, active_id=pick.ids[0], active_model='stock.picking'))
|
||||
return_wiz = stock_return_picking_form.save()
|
||||
for return_move in return_wiz.product_return_moves:
|
||||
return_move.write({
|
||||
'quantity': 1,
|
||||
'to_refund': True
|
||||
})
|
||||
res = return_wiz.create_returns()
|
||||
return_pick = self.env['stock.picking'].browse(res['res_id'])
|
||||
return_pick.move_line_ids.qty_done = 1
|
||||
return_pick.button_validate() # validate return
|
||||
|
||||
# Delivered quantities to the client should be 0
|
||||
qty_del_return_validated = sum(sol.qty_delivered for sol in order.order_line)
|
||||
self.assertNotEqual(qty_del_return_validated, 1.0, "The return was validated, therefore the delivery from client to"
|
||||
" company was successful, and the client is left without his 1 product.")
|
||||
self.assertEqual(qty_del_return_validated, 0.0, "The return has processed, client doesn't have any quantity anymore")
|
||||
|
||||
Reference in New Issue
Block a user