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