[FIX] pos_loyalty: handle many2one field in reward product domain

Before this commit, if you added a domain to a loyalty reward with
one of many2one fields like [("categ_id", "ilike", "test")], it wasn't
possible to open the PoS.

This commit addresses this limitation by replacing the many2one fields
with their corresponding value. To do this the product's field type is
loaded to ensure that this improvement applies exclusively to many2one
fields.

However, it's important to note that this improvement currently handles
only "one-level" of related many2one fields. Any domain that appears
like ("categ_id.foo", "ilike", "foo-val") won't function as expected.

opw-3473103

closes odoo/odoo#134811

X-original-commit: d0a6ab8d1f89f0dd2aa6641c63b6973ae7c753ad
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-09-08 15:26:10 +00:00
parent ac8b080234
commit 5e81b3e3d2
4 changed files with 94 additions and 0 deletions
+4
View File
@@ -115,6 +115,10 @@ class PosSession(models.Model):
product_id_to_program_ids[product['id']].append(program['id'])
loaded_data['product_id_to_program_ids'] = product_id_to_program_ids
product_product_fields = self.env['product.product'].fields_get(self._loader_params_product_product()['search_params']['fields'])
loaded_data['field_types'] = {
'product.product': {f:v['type'] for f, v in product_product_fields.items()}
}
def _loader_params_product_product(self):
params = super()._loader_params_product_product()
@@ -207,6 +207,7 @@ patch(PosStore.prototype, {
reward.all_discount_product_ids = new Set(reward.all_discount_product_ids);
}
this.fieldTypes = loadedData['field_types'];
await super._processData(loadedData);
this.productId2ProgramIds = loadedData["product_id_to_program_ids"];
this.programs = loadedData["loyalty.program"] || []; //TODO: rename to `loyaltyPrograms` etc
@@ -234,6 +235,15 @@ 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) {
@@ -198,3 +198,25 @@ registry.category("web_tour.tours").add("PosLoyaltySpecificDiscountWithFreeProdu
return getSteps();
},
});
registry
.category("web_tour.tours")
.add("PosLoyaltySpecificDiscountWithRewardProductDomainTour", {
test: true,
url: "/pos/web",
steps: () => {
startSteps();
ProductScreen.do.confirmOpeningPopup();
ProductScreen.do.clickHomeCategory();
ProductScreen.do.clickDisplayedProduct('Product A');
ProductScreen.check.selectedOrderlineHas('Product A', '1.00', '15.00');
PosLoyalty.check.orderTotalIs('15.00');
ProductScreen.do.clickDisplayedProduct('Product B');
ProductScreen.check.selectedOrderlineHas('Product B', '1.00', '50.00');
PosLoyalty.check.orderTotalIs('40.00');
return getSteps();
}
});
+58
View File
@@ -1122,3 +1122,61 @@ class TestUi(TestPointOfSaleHttpCommon):
"PosLoyaltyTour7",
login="pos_user",
)
def test_discount_with_reward_product_domain(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_domain': '[("categ_id", "ilike", "office")]',
})],
'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,
"PosLoyaltySpecificDiscountWithRewardProductDomainTour",
login="pos_user",
)