[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:
@@ -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(),
|
||||
});
|
||||
|
||||
@@ -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",
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user