Skip to content
Snippets Groups Projects
Commit fb1b607f authored by Joseph Caburnay's avatar Joseph Caburnay Committed by Pedram (PEBR)
Browse files

[FIX] pos_loyalty: free product rewards for order type rules


The `_computeUnclaimedFreeProductQty` method was not properly computing
reward quantities for order type rules. This commit fixes the
computation to handle order type rules separately, allowing free
product rewards to be granted as expected.

The computation now also takes into account which rules were actually
used when calculating points. It will ignore any rules that were not
used in the points calculation when determining free product rewards.
This ensures the rewards match the rules that contributed to points
for the order.

opw-3492083

closes odoo/odoo#134557

Signed-off-by: default avatarJoseph Caburnay (jcb) <jcb@odoo.com>
parent a84ed11a
No related branches found
No related tags found
No related merge requests found
......@@ -21,6 +21,9 @@ function _newRandomRewardCode() {
}
let nextId = -1;
let pointsForProgramsCountedRules = {};
export class PosLoyaltyCard {
/**
* @param {string} code coupon code
......@@ -682,6 +685,7 @@ const PosLoyaltyOrder = (Order) => class PosLoyaltyOrder extends Order {
program_id: program.id,
coupon_id: coupon.id,
barcode: pa.barcode,
appliedRules: pointsForProgramsCountedRules[program.id]
};
}
}
......@@ -851,6 +855,7 @@ const PosLoyaltyOrder = (Order) => class PosLoyaltyOrder extends Order {
* @returns {Object} Containing the points gained per program
*/
pointsForPrograms(programs) {
pointsForProgramsCountedRules = {};
const totalTaxed = this.get_total_with_tax();
const totalUntaxed = this.get_total_without_tax();
const totalsPerProgram = Object.fromEntries(programs.map((program) => [program.id, {'untaxed': totalUntaxed, 'taxed': totalTaxed}]));
......@@ -916,6 +921,10 @@ const PosLoyaltyOrder = (Order) => class PosLoyaltyOrder extends Order {
// For example, when refunding an ewallet payment. See TicketScreen override in this addon.
continue;
}
if (!(program.id in pointsForProgramsCountedRules)) {
pointsForProgramsCountedRules[program.id] = [];
}
pointsForProgramsCountedRules[program.id].push(rule.id)
if (program.applies_on === 'future' && rule.reward_point_split && rule.reward_point_mode !== 'order') {
// In this case we count the points per rule
if (rule.reward_point_mode === 'unit') {
......@@ -1445,23 +1454,29 @@ const PosLoyaltyOrder = (Order) => class PosLoyaltyOrder extends Order {
if (this._isRewardProductPartOfRules(reward, product)) {
// OPTIMIZATION: Pre-calculate the factors for each reward-product combination during the loading.
// For points not based on quantity, need to normalize the points to compute free quantity.
const factor = reward.program_id.rules.reduce((result, rule) => {
const appliedRulesIds = this.couponPointChanges[coupon_id].appliedRules;
const appliedRules = appliedRulesIds !== undefined
? reward.program_id.rules.filter(rule => appliedRulesIds.includes(rule.id))
: reward.program_id.rules;
let factor = 0;
let orderPoints = 0;
for (const rule of appliedRules) {
if (rule.any_product || rule.valid_product_ids.has(product.id)) {
if (rule.reward_point_mode === 'order') {
result += rule.reward_point_amount;
orderPoints += rule.reward_point_amount;
} else if (rule.reward_point_mode === 'money') {
result += round_precision(rule.reward_point_amount * product.lst_price, 0.01);
factor += round_precision(rule.reward_point_amount * product.lst_price, 0.01);
} else if (rule.reward_point_mode === 'unit') {
result += rule.reward_point_amount;
factor += rule.reward_point_amount;
}
}
return result;
}, 0)
}
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);
freeQty = computeFreeQuantity((remainingPoints - correction - orderPoints) / factor, reward.required_points / factor, reward.reward_product_qty);
freeQty += Math.floor((orderPoints / reward.required_points) * reward.reward_product_qty);
}
} else {
freeQty = Math.floor((remainingPoints / reward.required_points) * reward.reward_product_qty);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment