diff --git a/addons/pos_sale/models/pos_order.py b/addons/pos_sale/models/pos_order.py index 3378b9ffeeb..acc000b5a16 100644 --- a/addons/pos_sale/models/pos_order.py +++ b/addons/pos_sale/models/pos_order.py @@ -76,7 +76,8 @@ class PosOrder(models.Model): # track the waiting pickings waiting_picking_ids = set() for so_line in so_lines: - for stock_move in so_line.move_ids.group_id.stock_move_ids: + so_line_stock_move_ids = so_line.move_ids.group_id.stock_move_ids + for stock_move in so_line.move_ids: picking = stock_move.picking_id if not picking.state in ['waiting', 'confirmed', 'assigned']: continue @@ -84,6 +85,9 @@ class PosOrder(models.Model): if float_compare(new_qty, 0, precision_rounding=stock_move.product_uom.rounding) <= 0: new_qty = 0 stock_move.product_uom_qty = so_line.compute_uom_qty(new_qty, stock_move, False) + #If the product is delivered with more than one step, we need to update the quantity of the other steps + for move in so_line_stock_move_ids.filtered(lambda m: m.state in ['waiting', 'confirmed'] and m.product_id == stock_move.product_id): + move.product_uom_qty = stock_move.product_uom_qty waiting_picking_ids.add(picking.id) def is_product_uom_qty_zero(move): diff --git a/addons/pos_sale/static/tests/tours/PosSaleTour.js b/addons/pos_sale/static/tests/tours/PosSaleTour.js index 0b42116be3c..982a8c06cce 100644 --- a/addons/pos_sale/static/tests/tours/PosSaleTour.js +++ b/addons/pos_sale/static/tests/tours/PosSaleTour.js @@ -44,3 +44,21 @@ ProductScreen.check.selectedOrderlineHas('product2', 1); ProductScreen.check.totalAmountIs("11.00"); registry.category("web_tour.tours").add('PosSettleOrderIncompatiblePartner', { test: true, url: '/pos/ui', steps: getSteps() }); + +startSteps(); + +ProductScreen.do.confirmOpeningPopup(); +ProductScreen.do.clickQuotationButton(); +ProductScreen.do.selectFirstOrder(); +ProductScreen.do.clickOrderline("Product A", "1"); +ProductScreen.check.selectedOrderlineHas('Product A', '1.00'); +ProductScreen.do.clickOrderline("Product B", "1"); +ProductScreen.do.pressNumpad('Qty 0'); +ProductScreen.check.selectedOrderlineHas('Product B', '0.00'); +ProductScreen.do.clickPayButton(); +PaymentScreen.do.clickPaymentMethod('Bank'); +PaymentScreen.check.remainingIs('0.0'); +PaymentScreen.do.clickValidate(); +ReceiptScreen.check.isShown(); + +registry.category("web_tour.tours").add('PosSettleOrder2', { test: true, url: '/pos/ui', steps: getSteps() }); diff --git a/addons/pos_sale/tests/test_pos_sale_flow.py b/addons/pos_sale/tests/test_pos_sale_flow.py index 8c416441663..86fd8a73122 100644 --- a/addons/pos_sale/tests/test_pos_sale_flow.py +++ b/addons/pos_sale/tests/test_pos_sale_flow.py @@ -102,3 +102,54 @@ class TestPoSSale(TestPointOfSaleHttpCommon): }) self.main_pos_config.open_ui() self.start_tour("/pos/ui?config_id=%d" % self.main_pos_config.id, 'PosSettleOrderIncompatiblePartner', login="accountman") + + def test_settle_order_with_different_product(self): + """This test create an order and settle it in the PoS. But only one of the product is delivered. + And we need to make sure the quantity are correctly updated on the sale order. + """ + #create 2 products + product_a = self.env['product.product'].create({ + 'name': 'Product A', + 'available_in_pos': True, + 'type': 'product', + 'lst_price': 10.0, + }) + product_b = self.env['product.product'].create({ + 'name': 'Product B', + 'available_in_pos': True, + 'type': 'product', + 'lst_price': 10.0, + }) + #create a sale order with 2 lines + sale_order = self.env['sale.order'].create({ + 'partner_id': self.env.ref('base.res_partner_2').id, + 'order_line': [(0, 0, { + 'product_id': product_a.id, + 'name': product_a.name, + 'product_uom_qty': 1, + 'product_uom': product_a.uom_id.id, + 'price_unit': product_a.lst_price, + }), (0, 0, { + 'product_id': product_b.id, + 'name': product_b.name, + 'product_uom_qty': 1, + 'product_uom': product_b.uom_id.id, + 'price_unit': product_b.lst_price, + })], + }) + sale_order.action_confirm() + + self.assertEqual(sale_order.order_line[0].qty_delivered, 0) + self.assertEqual(sale_order.order_line[1].qty_delivered, 0) + + self.main_pos_config.open_ui() + self.start_tour("/pos/ui?config_id=%d" % self.main_pos_config.id, 'PosSettleOrder2', login="accountman") + + self.assertEqual(sale_order.order_line[0].qty_delivered, 1) + self.assertEqual(sale_order.order_line[1].qty_delivered, 0) + orderline_product_a = sale_order.order_line.filtered(lambda l: l.product_id.id == product_a.id) + orderline_product_b = sale_order.order_line.filtered(lambda l: l.product_id.id == product_b.id) + # nothing to deliver for product a because already handled in pos. + self.assertEqual(orderline_product_a.move_ids.product_uom_qty, 0) + # 1 item to deliver for product b. + self.assertEqual(orderline_product_b.move_ids.product_uom_qty, 1)