[FIX] pos_loyalty: fix discount reward on specific category

When using a loyalty program reward with a discount on a specific
product category in PoS, it was not being applied correctly.

The reward contained a discount_product_domain with the category ids.
However in PoS the many2one fields are replaced with the
corresponding values https://github.com/odoo/odoo/commit/e7632a3bcfa60fa416fff5e2e9daaf2571c5f7f1.

To fix this, I replace the ids in the discount_product_domain with
the category name values before sending to the PoS.

opw-3502703

closes odoo/odoo#145016

X-original-commit: 494a07251c23dd7e30980dd5a455f1b37daea16f
Signed-off-by: Joseph Caburnay (jcb) <jcb@odoo.com>
Signed-off-by: Pedram Bi Ria (pebr) <pebr@odoo.com>
This commit is contained in:
Pedram (PEBR)
2023-12-12 19:23:56 +00:00
parent 8bfc6bcb3a
commit 3dbfa57c41
4 changed files with 104 additions and 10 deletions
+26 -1
View File
@@ -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)
@@ -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) {
@@ -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(),
});
+58
View File
@@ -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",
)