diff --git a/addons/pos_loyalty/static/src/overrides/models/loyalty.js b/addons/pos_loyalty/static/src/overrides/models/loyalty.js index 423ab9941d1..12d3fff1241 100644 --- a/addons/pos_loyalty/static/src/overrides/models/loyalty.js +++ b/addons/pos_loyalty/static/src/overrides/models/loyalty.js @@ -1364,7 +1364,7 @@ patch(Order.prototype, { } let freeQty; if (reward.program_id.trigger == "auto") { - if (this._isRewardProductPartOfRules(reward, product)) { + if (this._isRewardProductPartOfRules(reward, product) && reward.program_id.applies_on !== 'future') { // OPTIMIZATION: Pre-calculate the factors for each reward-product combination during the loading. // For points not based on quantity, need to normalize the points to compute free quantity. const appliedRulesIds = this.couponPointChanges[coupon_id].appliedRules; @@ -1421,7 +1421,7 @@ patch(Order.prototype, { }, _computePotentialFreeProductQty(reward, product, remainingPoints) { if (reward.program_id.trigger == "auto") { - if (this._isRewardProductPartOfRules(reward, product)) { + if (this._isRewardProductPartOfRules(reward, product) && reward.program_id.applies_on !== 'future') { const line = this.get_orderlines().find( (line) => line.reward_product_id === product.id ); diff --git a/addons/pos_loyalty/static/tests/tours/PosLoyaltyTour.js b/addons/pos_loyalty/static/tests/tours/PosLoyaltyTour.js index 86de859c0ec..dbc4061a2be 100644 --- a/addons/pos_loyalty/static/tests/tours/PosLoyaltyTour.js +++ b/addons/pos_loyalty/static/tests/tours/PosLoyaltyTour.js @@ -334,3 +334,51 @@ registry.category("web_tour.tours").add('PosLoyaltyTour10', { PosLoyalty.isRewardButtonHighlighted(false), ].flat(), }); + +registry.category("web_tour.tours").add('PosLoyaltyTour11.1', { + test: true, + url: '/pos/web', + steps: () => + [ + ProductScreen.clickHomeCategory(), + ProductScreen.confirmOpeningPopup(), + + ProductScreen.clickPartnerButton(), + ProductScreen.clickCustomer('AAA Partner'), + PosLoyalty.customerIs('AAA Partner'), + ProductScreen.addOrderline('Product Test', '3'), + ProductScreen.totalAmountIs('150.00'), + PosLoyalty.isRewardButtonHighlighted(false), + PosLoyalty.finalizeOrder('Cash', '150'), + ].flat(), +}); + +registry.category("web_tour.tours").add('PosLoyaltyTour11.2', { + test: true, + url: '/pos/web', + steps: () => + [ + ProductScreen.clickPartnerButton(), + ProductScreen.clickCustomer('AAA Partner'), + PosLoyalty.customerIs('AAA Partner'), + ProductScreen.clickDisplayedProduct('Product Test'), + ProductScreen.totalAmountIs('50.00'), + PosLoyalty.isRewardButtonHighlighted(false), + PosLoyalty.enterCode('123456'), + PosLoyalty.isRewardButtonHighlighted(true), + PosLoyalty.clickRewardButton(), + SelectionPopup.clickItem('Free Product'), + PosLoyalty.hasRewardLine('Free Product', '-1.00'), + PosLoyalty.isRewardButtonHighlighted(true), + PosLoyalty.clickRewardButton(), + SelectionPopup.clickItem('Free Product'), + PosLoyalty.hasRewardLine('Free Product', '-2.00'), + PosLoyalty.isRewardButtonHighlighted(true), + PosLoyalty.clickRewardButton(), + SelectionPopup.clickItem('Free Product'), + PosLoyalty.hasRewardLine('Free Product', '-3.00'), + PosLoyalty.isRewardButtonHighlighted(false), + ProductScreen.totalAmountIs('50.00'), + PosLoyalty.finalizeOrder('Cash', '50'), + ].flat(), +}); diff --git a/addons/pos_loyalty/tests/test_frontend.py b/addons/pos_loyalty/tests/test_frontend.py index 890e82efac9..541692e3796 100644 --- a/addons/pos_loyalty/tests/test_frontend.py +++ b/addons/pos_loyalty/tests/test_frontend.py @@ -1514,3 +1514,65 @@ class TestUi(TestPointOfSaleHttpCommon): "PosLoyaltyTour10", login="pos_user", ) + + def test_loyalty_program_with_next_order_coupon_free_product(self): + self.env['loyalty.program'].search([]).write({'active': False}) + + free_product = self.env['product.product'].create({ + 'name': 'Free Product', + 'type': 'product', + 'list_price': 1, + 'available_in_pos': True, + 'taxes_id': False, + }) + self.env['product.product'].create({ + 'name': 'Product Test', + 'type': 'product', + 'list_price': 50, + 'available_in_pos': True, + 'taxes_id': False, + }) + + loyalty_program = self.env['loyalty.program'].create({ + 'name': 'Next Order Coupon Program', + 'program_type': 'next_order_coupons', + 'applies_on': 'future', + 'trigger': 'auto', + 'portal_visible': True, + 'rule_ids': [(0, 0, { + 'reward_point_mode': 'unit', + 'minimum_amount': 100, + 'minimum_qty': 0, + })], + 'reward_ids': [(0, 0, { + 'reward_type': 'product', + 'reward_product_id': free_product.id, + 'reward_product_qty': 1, + 'required_points': 1, + })], + }) + + self.env['res.partner'].create({'name': 'AAA Partner'}) + self.pos_user.write({ + 'groups_id': [ + (4, self.env.ref('stock.group_stock_user').id), + ] + }) + self.main_pos_config.open_ui() + self.start_tour( + "/pos/web?config_id=%d" % self.main_pos_config.id, + "PosLoyaltyTour11.1", + login="pos_user", + ) + coupon = loyalty_program.coupon_ids + self.assertEqual(len(coupon), 1, "Coupon not generated") + self.assertEqual(coupon.points, 3, "Coupon not generated with correct points") + coupon.write({"code": "123456"}) + + self.main_pos_config.open_ui() + self.start_tour( + "/pos/web?config_id=%d" % self.main_pos_config.id, + "PosLoyaltyTour11.2", + login="pos_user", + ) + self.assertEqual(coupon.points, 0, "Coupon not used")