diff --git a/addons/pos_loyalty/models/pos_session.py b/addons/pos_loyalty/models/pos_session.py index 83e0285df3c..2387cc5e486 100644 --- a/addons/pos_loyalty/models/pos_session.py +++ b/addons/pos_loyalty/models/pos_session.py @@ -3,6 +3,8 @@ from odoo import models from odoo.osv.expression import OR +import ast +import json class PosSession(models.Model): _inherit = 'pos.session' @@ -57,7 +59,30 @@ class PosSession(models.Model): return self.env['loyalty.rule'].search_read(**params['search_params']) def _get_pos_ui_loyalty_reward(self, params): - return self.env['loyalty.reward'].search_read(**params['search_params']) + rewards = self.env['loyalty.reward'].search_read(**params['search_params']) + for reward in rewards: + reward['reward_product_domain'] = self._replace_ilike_with_in(reward['reward_product_domain']) + return rewards + + def _replace_ilike_with_in(self, domain_str): + if domain_str == "null": + return domain_str + + domain = ast.literal_eval(domain_str) + + for index, condition in enumerate(domain): + if isinstance(condition, (list, tuple)) and len(condition) == 3: + field_name, operator, value = condition + field = self.env['product.product']._fields.get(field_name) + + if field and field.type == 'many2one' and operator in ('ilike', 'not ilike'): + comodel = self.env[field.comodel_name] + matching_ids = list(comodel._name_search(value, [], operator, limit=None)) + + new_operator = 'in' if operator == 'ilike' else 'not in' + domain[index] = [field_name, new_operator, matching_ids] + + return json.dumps(domain) def _get_pos_ui_product_product(self, params): result = super()._get_pos_ui_product_product(params) diff --git a/addons/pos_loyalty/static/src/overrides/models/pos_store.js b/addons/pos_loyalty/static/src/overrides/models/pos_store.js index 9bcadb9756d..481734d9947 100644 --- a/addons/pos_loyalty/static/src/overrides/models/pos_store.js +++ b/addons/pos_loyalty/static/src/overrides/models/pos_store.js @@ -235,15 +235,6 @@ patch(PosStore.prototype, { try { products - .map(product => { - const modifiedProduct = { ...product }; - Object.keys(modifiedProduct).forEach(key => { - if (this.fieldTypes['product.product'][key] === 'many2one') { - modifiedProduct[key] = modifiedProduct[key][1]; - } - }); - return modifiedProduct; - }) .filter((product) => domain.contains(product)) .forEach((product) => reward.all_discount_product_ids.add(product.id)); } catch (error) { diff --git a/addons/pos_loyalty/static/tests/tours/PosLoyaltyTour.js b/addons/pos_loyalty/static/tests/tours/PosLoyaltyTour.js index d6fa3f0d628..54e2865fdbb 100644 --- a/addons/pos_loyalty/static/tests/tours/PosLoyaltyTour.js +++ b/addons/pos_loyalty/static/tests/tours/PosLoyaltyTour.js @@ -268,3 +268,23 @@ registry.category("web_tour.tours").add('PosLoyaltyTour8', { ProductScreen.totalAmountIs('50.00'), ].flat(), }); + + +registry + .category("web_tour.tours") + .add("PosLoyaltySpecificDiscountCategoryTour", { + test: true, + url: "/pos/web", + steps: () => [ + ProductScreen.confirmOpeningPopup(), + ProductScreen.clickHomeCategory(), + + ProductScreen.clickDisplayedProduct('Product A'), + ProductScreen.selectedOrderlineHas('Product A', '1.00', '15.00'), + PosLoyalty.orderTotalIs('15.00'), + + ProductScreen.clickDisplayedProduct('Product B'), + ProductScreen.selectedOrderlineHas('Product B', '1.00', '50.00'), + PosLoyalty.orderTotalIs('40.00'), + ].flat(), + }); diff --git a/addons/pos_loyalty/tests/test_frontend.py b/addons/pos_loyalty/tests/test_frontend.py index 0742f386690..c2d01abc2c8 100644 --- a/addons/pos_loyalty/tests/test_frontend.py +++ b/addons/pos_loyalty/tests/test_frontend.py @@ -1322,3 +1322,61 @@ class TestUi(TestPointOfSaleHttpCommon): "PosLoyaltyTour8", login="pos_user", ) + + def test_discount_specific_products(self): + self.env['loyalty.program'].search([]).write({'active': False}) + + product_category_base = self.env.ref('product.product_category_1') + product_category_1 = self.env['product.category'].create({ + 'name': 'Office furnitures', + 'parent_id': product_category_base.id + }) + + self.productA = self.env['product.product'].create( + { + 'name': 'Product A', + 'type': 'product', + 'list_price': 15, + 'available_in_pos': True, + 'taxes_id': False, + 'categ_id': product_category_base.id + } + ) + + self.productB = self.env['product.product'].create( + { + 'name': 'Product B', + 'type': 'product', + 'list_price': 50, + 'available_in_pos': True, + 'taxes_id': False, + 'categ_id': product_category_1.id + } + ) + + self.env['loyalty.program'].create({ + 'name': 'Discount on Specific Products', + 'program_type': 'promotion', + 'trigger': 'auto', + 'applies_on': 'current', + 'rule_ids': [(0, 0, { + 'reward_point_mode': 'order', + 'minimum_qty': 1, + })], + 'reward_ids': [(0, 0, { + 'reward_type': 'discount', + 'required_points': 1, + 'discount': 50, + 'discount_mode': 'percent', + 'discount_applicability': 'specific', + 'discount_product_category_id': product_category_1.id, + })], + 'pos_config_ids': [Command.link(self.main_pos_config.id)], + }) + + self.main_pos_config.open_ui() + self.start_tour( + "/pos/web?config_id=%d" % self.main_pos_config.id, + "PosLoyaltySpecificDiscountCategoryTour", + login="pos_user", + )