[FIX] pos_loyalty: zero division when reward product has zero price

The issue occurred when a loyalty program's rule was set to be
based on money spent, and the reward was a free product with a
sale price of zero. This caused a zero division error in the code,
resulting in the remaining points becoming NaN after the reward
was obtained in the point of sale.

opw-3253366

closes odoo/odoo#123123

X-original-commit: 1eaca074741157e42c12da22e945a1817e7ceec3
Signed-off-by: Joseph Caburnay (jcb) <jcb@odoo.com>
Signed-off-by: Pedram Bi Ria (pebr) <pebr@odoo.com>
This commit is contained in:
pedrambiria
2023-06-01 11:43:57 +02:00
parent 2afdda2576
commit 09b2dab543
3 changed files with 79 additions and 8 deletions
+14 -8
View File
@@ -1516,14 +1516,20 @@ patch(Order.prototype, "pos_loyalty.Order", {
}
return result;
}, 0);
const correction = shouldCorrectRemainingPoints
? this._getPointsCorrection(reward.program_id)
: 0;
freeQty = computeFreeQuantity(
(remainingPoints - correction) / factor,
reward.required_points / factor,
reward.reward_product_qty
);
if (factor === 0) {
freeQty = Math.floor(
(remainingPoints / reward.required_points) * reward.reward_product_qty
);
} else {
const correction = shouldCorrectRemainingPoints
? this._getPointsCorrection(reward.program_id)
: 0;
freeQty = computeFreeQuantity(
(remainingPoints - correction) / factor,
reward.required_points / factor,
reward.reward_product_qty
);
}
} else {
freeQty = Math.floor(
(remainingPoints / reward.required_points) * reward.reward_product_qty
@@ -140,3 +140,24 @@ PosLoyalty.check.orderTotalIs("6.40");
PosLoyalty.exec.finalizeOrder("Cash", "10");
registry.category("web_tour.tours").add("PosLoyaltyLoyaltyProgram2", { test: true, url: "/pos/web", steps: getSteps() });
startSteps();
ProductScreen.do.confirmOpeningPopup();
ProductScreen.do.clickHomeCategory();
// Generates 10.2 points and use points to get the reward product with zero sale price
ProductScreen.exec.addOrderline('Desk Organizer', '2');
ProductScreen.do.clickPartnerButton();
ProductScreen.do.clickCustomer('Test Partner AAA');
// At this point, the free_product program is triggered.
// The reward button should be highlighted.
PosLoyalty.check.isRewardButtonHighlighted(true);
PosLoyalty.do.claimReward("Free Product - Whiteboard Pen");
PosLoyalty.check.hasRewardLine('Free Product - Whiteboard Pen', '0.0', '1.00');
PosLoyalty.check.orderTotalIs('10.2');
PosLoyalty.exec.finalizeOrder('Cash', '10.2');
registry.category("web_tour.tours").add("PosLoyaltyLoyaltyProgram3", { test: true, url: "/pos/web", steps: getSteps() });
+44
View File
@@ -377,6 +377,50 @@ class TestUi(TestPointOfSaleHttpCommon):
reward_orderline = self.main_pos_config.current_session_id.order_ids[-1].lines.filtered(lambda line: line.is_reward_line)
self.assertEqual(len(reward_orderline.ids), 0, msg='Reference: Order4_no_reward. Last order should have no reward line.')
def test_loyalty_free_product_zero_sale_price_loyalty_program(self):
# In this program, each $ spent gives 1 point.
# 5 points can be used to get a free whiteboard pen.
# and the whiteboard pen sale price is zero
self.pos_user.write({
'groups_id': [
(4, self.env.ref('stock.group_stock_user').id),
]
})
self.whiteboard_pen.write({'lst_price': 0})
loyalty_program = self.env['loyalty.program'].create({
'name': 'Loyalty Program',
'program_type': 'loyalty',
'trigger': 'auto',
'applies_on': 'both',
'rule_ids': [(0, 0, {
'reward_point_amount': 1,
'reward_point_mode': 'money',
'minimum_qty': 1,
})],
'reward_ids': [(0, 0, {
'reward_type': 'product',
'reward_product_id': self.whiteboard_pen.id,
'reward_product_qty': 1,
'required_points': 5,
})],
})
(self.promo_programs | self.coupon_program).write({'active': False})
partner_aaa = self.env['res.partner'].create({'name': 'Test Partner AAA'})
self.start_tour(
"/pos/web?config_id=%d" % self.main_pos_config.id,
"PosLoyaltyLoyaltyProgram3",
login="pos_user",
)
aaa_loyalty_card = loyalty_program.coupon_ids.filtered(lambda coupon: coupon.partner_id.id == partner_aaa.id)
self.assertEqual(loyalty_program.pos_order_count, 1)
self.assertAlmostEqual(aaa_loyalty_card.points, 5.2)
def test_pos_loyalty_tour_max_amount(self):
"""Test the loyalty program with a maximum amount and product with different taxe."""