From 895c7601d2c12abd52fb897e70f30d72ca8a24c1 Mon Sep 17 00:00:00 2001 From: roen-odoo <roen@odoo.com> Date: Tue, 25 Apr 2023 15:00:05 +0000 Subject: [PATCH] [FIX] pos_sale: remove auto promotion from settled orders Current behavior: When you apply a promotion on a sale order, then settle it in a PoS session, the promotion will be applied two times. One time from the sale order, and one from the PoS. Steps to reproduce: - Create a promotion program with a discount of 50% with no code needed - Add the promotion program to the PoS - Create a sale order with a product of 200$ and apply the promotion - The total price of the order should be 100$ - Settle the sale order in a PoS session - The promotion is applied twice and the total price is 50$ instead of 100$ opw-3247545 closes odoo/odoo#119673 Signed-off-by: Joseph Caburnay (jcb) <jcb@odoo.com> --- .../SaleOrderManagementScreen.js | 3 +- .../static/tests/tours/pos_sale_tours.js | 10 +++++ addons/pos_sale/tests/test_pos_sale_flow.py | 42 +++++++++++++++++++ 3 files changed, 54 insertions(+), 1 deletion(-) diff --git a/addons/pos_sale/static/src/js/OrderManagementScreen/SaleOrderManagementScreen.js b/addons/pos_sale/static/src/js/OrderManagementScreen/SaleOrderManagementScreen.js index 1b6af4b99b4b..f13542a2df59 100644 --- a/addons/pos_sale/static/src/js/OrderManagementScreen/SaleOrderManagementScreen.js +++ b/addons/pos_sale/static/src/js/OrderManagementScreen/SaleOrderManagementScreen.js @@ -293,7 +293,8 @@ odoo.define('pos_sale.SaleOrderManagementScreen', function (require) { sale_order[0].amount_unpaid = saleOrdersAmountUnpaid[sale_order[0].id]; const sale_lines = await this._getSOLines(sale_order[0].order_line); - sale_order[0].order_line = sale_lines; + const promo_products_to_remove = this.env.pos.promo_programs.flatMap(program => program.promo_code_usage === 'no_code_needed' ? program.discount_line_product_id[0] : []); + sale_order[0].order_line = sale_lines.filter(line => !promo_products_to_remove.includes(line.product_id[0])); return sale_order[0]; } diff --git a/addons/pos_sale/static/tests/tours/pos_sale_tours.js b/addons/pos_sale/static/tests/tours/pos_sale_tours.js index b410ff33065a..a6f3355812e3 100644 --- a/addons/pos_sale/static/tests/tours/pos_sale_tours.js +++ b/addons/pos_sale/static/tests/tours/pos_sale_tours.js @@ -42,4 +42,14 @@ odoo.define('pos_sale.tour', function (require) { ReceiptScreen.check.isShown(); Tour.register('PosSettleOrder2', { test: true, url: '/pos/ui' }, getSteps()); + + + startSteps(); + + ProductScreen.do.confirmOpeningPopup(); + ProductScreen.do.clickQuotationButton(); + ProductScreen.do.selectFirstOrder(); + ProductScreen.check.totalAmountIs(100); + + Tour.register('PosSettleOrderWithPromotions', { test: true, url: '/pos/ui' }, getSteps()); }); diff --git a/addons/pos_sale/tests/test_pos_sale_flow.py b/addons/pos_sale/tests/test_pos_sale_flow.py index 07561bd52928..8b2db558ad0d 100644 --- a/addons/pos_sale/tests/test_pos_sale_flow.py +++ b/addons/pos_sale/tests/test_pos_sale_flow.py @@ -119,3 +119,45 @@ class TestPoSSale(TestPointOfSaleHttpCommon): 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) + + def test_settle_order_with_promotions(self): + self.promotion_program = self.env['coupon.program'].create({ + 'name': '50% on current order', + 'program_type': 'promotion_program', + 'promo_code_usage': 'no_code_needed', + 'reward_type': 'discount', + 'discount_type': 'percentage', + 'discount_percentage': 50, + 'discount_apply_on': 'on_order', + }) + + self.product = self.env['product.product'].create({ + 'name': 'Product', + 'available_in_pos': True, + 'type': 'product', + 'lst_price': 200.0, + 'taxes_id': False, + }) + + sale_order = self.env['sale.order'].create({ + 'partner_id': self.env.ref('base.res_partner_2').id, + 'order_line': [(0, 0, { + 'product_id': self.product.id, + 'name': self.product.name, + 'product_uom_qty': 1, + 'product_uom': self.env.ref('uom.product_uom_unit').id, + 'price_unit': self.product.lst_price, + })], + }) + + #validate the sale order + sale_order.recompute_coupon_lines() + sale_order.action_confirm() + + #add the promo program to the pos config + self.main_pos_config.write({ + 'use_coupon_programs': True, + 'promo_program_ids': [(6, 0, [self.promotion_program.id])], + }) + self.main_pos_config.open_session_cb() + self.start_tour("/pos/ui?config_id=%d" % self.main_pos_config.id, 'PosSettleOrderWithPromotions', login="accountman") -- GitLab