diff --git a/addons/sale_stock/models/stock.py b/addons/sale_stock/models/stock.py index 9aba0b8203a..71f4ea96539 100644 --- a/addons/sale_stock/models/stock.py +++ b/addons/sale_stock/models/stock.py @@ -79,7 +79,7 @@ class StockPicking(models.Model): sale_order = move.picking_id.sale_id # Creates new SO line only when pickings linked to a sale order and # for moves with qty. done and not already linked to a SO line. - if not sale_order or move.sale_line_id or not move.quantity_done: + if not sale_order or move.location_dest_id.usage != 'customer' or move.sale_line_id or not move.quantity_done: continue product = move.product_id so_line_vals = { diff --git a/addons/sale_stock/tests/test_sale_stock.py b/addons/sale_stock/tests/test_sale_stock.py index a29407bb7d0..8c873f963fe 100644 --- a/addons/sale_stock/tests/test_sale_stock.py +++ b/addons/sale_stock/tests/test_sale_stock.py @@ -853,6 +853,90 @@ class TestSaleStock(TestSaleCommon, ValuationReconciliationTestCommon): so_line_2.price_unit, 70.0, "Should get the product price as the invoice policy is on qty. delivered") + def test_14_delivered_qty_in_multistep(self): + """ Creates a sale order with delivery in two-step. Process the pick & + ship and check we don't have extra SO line. Then, do the same but with + adding a extra move and check only one extra SO line was created. + """ + # Set the delivery in two steps. + warehouse = self.company_data['default_warehouse'] + warehouse.delivery_steps = 'pick_ship' + # Configure a product with invoicing policy on order. + product_inv_on_order = self.env['product.product'].create({ + 'name': 'Shenaniffluffy', + 'type': 'consu', + 'invoice_policy': 'order', + 'list_price': 55.0, + }) + # Create a sale order. + sale_order = self._get_new_sale_order() + # Confirms the sale order, then valids pick and delivery. + sale_order.action_confirm() + self.assertTrue(sale_order.picking_ids) + self.assertEqual(len(sale_order.order_line), 1) + self.assertEqual(sale_order.order_line.qty_delivered, 0) + pick = sale_order.picking_ids.filtered(lambda p: p.picking_type_code == 'internal') + delivery = sale_order.picking_ids.filtered(lambda p: p.picking_type_code == 'outgoing') + + picking_form = Form(pick) + with picking_form.move_line_ids_without_package.edit(0) as move: + move.qty_done = 10 + pick = picking_form.save() + pick.button_validate() + + picking_form = Form(delivery) + with picking_form.move_line_ids_without_package.edit(0) as move: + move.qty_done = 10 + delivery = picking_form.save() + delivery.button_validate() + + # Check no new sale order line was created. + self.assertEqual(len(sale_order.order_line), 1) + self.assertEqual(sale_order.order_line.product_uom_qty, 10) + self.assertEqual(sale_order.order_line.qty_delivered, 10) + self.assertEqual(sale_order.order_line.price_unit, 70.0) + + # Creates a second sale order. + sale_order = self._get_new_sale_order() + # Confirms the sale order then add a new line for an another product in the pick/out. + sale_order.action_confirm() + self.assertTrue(sale_order.picking_ids) + self.assertEqual(len(sale_order.order_line), 1) + self.assertEqual(sale_order.order_line.qty_delivered, 0) + pick = sale_order.picking_ids.filtered(lambda p: p.picking_type_code == 'internal') + delivery = sale_order.picking_ids.filtered(lambda p: p.picking_type_code == 'outgoing') + + picking_form = Form(pick) + with picking_form.move_line_ids_without_package.edit(0) as move: + move.qty_done = 10 + with picking_form.move_line_ids_without_package.new() as new_move: + new_move.product_id = product_inv_on_order + new_move.qty_done = 10 + pick = picking_form.save() + pick.button_validate() + + picking_form = Form(delivery) + with picking_form.move_line_ids_without_package.edit(0) as move: + move.qty_done = 10 + with picking_form.move_line_ids_without_package.new() as new_move: + new_move.product_id = product_inv_on_order + new_move.qty_done = 10 + delivery = picking_form.save() + delivery.button_validate() + + # Check a new sale order line was correctly created. + self.assertEqual(len(sale_order.order_line), 2) + so_line_1 = sale_order.order_line[0] + so_line_2 = sale_order.order_line[1] + self.assertEqual(so_line_1.product_id.id, self.company_data['product_delivery_no'].id) + self.assertEqual(so_line_1.product_uom_qty, 10) + self.assertEqual(so_line_1.qty_delivered, 10) + self.assertEqual(so_line_1.price_unit, 70.0) + self.assertEqual(so_line_2.product_id.id, product_inv_on_order.id) + self.assertEqual(so_line_2.product_uom_qty, 0) + self.assertEqual(so_line_2.qty_delivered, 10) + self.assertEqual(so_line_2.price_unit, 0) + def test_08_sale_return_qty_and_cancel(self): """ Test a SO with a product on delivery with a 5 quantity.