diff --git a/addons/sale_mrp/models/sale_order_line.py b/addons/sale_mrp/models/sale_order_line.py index cd8b0f49362..88ac368b33d 100644 --- a/addons/sale_mrp/models/sale_order_line.py +++ b/addons/sale_mrp/models/sale_order_line.py @@ -119,14 +119,13 @@ class SaleOrderLine(models.Model): # kits that are currently in delivery bom = self.env['mrp.bom']._bom_find(self.product_id, bom_type='phantom')[self.product_id] if bom: - if not self.product_uom_qty or (previous_product_uom_qty and not previous_product_uom_qty.get(self.id, 0.0)): - return (previous_product_uom_qty and previous_product_uom_qty.get(self.id, 0.0)) or self.qty_delivered moves = self.move_ids.filtered(lambda r: r.state != 'cancel' and not r.scrapped) filters = { 'incoming_moves': lambda m: m.location_dest_id.usage == 'customer' and (not m.origin_returned_move_id or (m.origin_returned_move_id and m.to_refund)), 'outgoing_moves': lambda m: m.location_dest_id.usage != 'customer' and m.to_refund } - order_qty = self.product_uom._compute_quantity(self.product_uom_qty, bom.product_uom_id) + order_qty = previous_product_uom_qty.get(self.id, 0) if previous_product_uom_qty else self.product_uom_qty + order_qty = self.product_uom._compute_quantity(order_qty, bom.product_uom_id) qty = moves._compute_kit_quantities(self.product_id, order_qty, bom, filters) return bom.product_uom_id._compute_quantity(qty, self.product_uom) return super(SaleOrderLine, self)._get_qty_procurement(previous_product_uom_qty=previous_product_uom_qty) diff --git a/addons/sale_mrp/tests/test_sale_mrp_flow.py b/addons/sale_mrp/tests/test_sale_mrp_flow.py index 1d4dea1e30a..9c330ae7286 100644 --- a/addons/sale_mrp/tests/test_sale_mrp_flow.py +++ b/addons/sale_mrp/tests/test_sale_mrp_flow.py @@ -2110,3 +2110,52 @@ class TestSaleMrpFlow(ValuationReconciliationTestCommon): {'product_id': self.component_f.id, 'product_uom_qty': 0}, {'product_id': self.component_g.id, 'product_uom_qty': 0}, ]) + + def test_kit_return_and_decrease_sol_qty_to_zero(self): + """ + Create and confirm a SO with a kit product. + Deliver & Return the components + Set the SOL qty to 0 + """ + stock_location = self.company_data['default_warehouse'].lot_stock_id + + grp_uom = self.env.ref('uom.group_uom') + self.env.user.write({'groups_id': [(4, grp_uom.id)]}) + + # 10 kit_3 = 10 x compo_f + 20 x compo_g + self.env['stock.quant']._update_available_quantity(self.component_f, stock_location, 10) + self.env['stock.quant']._update_available_quantity(self.component_g, stock_location, 20) + + so_form = Form(self.env['sale.order']) + so_form.partner_id = self.partner_a + with so_form.order_line.new() as line: + line.product_id = self.kit_3 + line.product_uom_qty = 2 + line.product_uom = self.uom_ten + so = so_form.save() + so.action_confirm() + + delivery = so.picking_ids + for m in delivery.move_ids: + m.quantity_done = m.product_uom_qty + delivery.button_validate() + + self.assertEqual(delivery.state, 'done') + self.assertEqual(so.order_line.qty_delivered, 2) + + ctx = {'active_id': delivery.id, 'active_model': 'stock.picking'} + return_wizard = Form(self.env['stock.return.picking'].with_context(ctx)).save() + return_picking_id, dummy = return_wizard._create_returns() + return_picking = self.env['stock.picking'].browse(return_picking_id) + for m in return_picking.move_ids: + m.quantity_done = m.product_uom_qty + return_picking.button_validate() + + self.assertEqual(return_picking.state, 'done') + self.assertEqual(so.order_line.qty_delivered, 0) + + with Form(so) as so_form: + with so_form.order_line.edit(0) as line: + line.product_uom_qty = 0 + + self.assertEqual(so.picking_ids, delivery | return_picking)