fix: override getClaimableRewards to correctly display product rewards for manual membership programs
This commit is contained in:
parent
1f85ab68bc
commit
1a1ad81a55
@ -115,5 +115,76 @@ patch(PosOrder.prototype, {
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Override to fix free product rewards for manual_membership (subscription) programs.
|
||||
*
|
||||
* Odoo's base _computeUnclaimedFreeProductQty returns Math.min(available, freeQty).
|
||||
* `available` = qty of the reward product already in the current order.
|
||||
* For subscription programs (e.g. Makan Pagi Gratis), the free breakfast product is
|
||||
* NOT in the order yet — so available=0, freeQty=0 and the reward is never shown.
|
||||
*
|
||||
* Fix: after the base getClaimableRewards runs, we re-evaluate manual_membership
|
||||
* programs that were silently skipped and inject their product rewards using the
|
||||
* raw point-based qty (points / required_points), so the cashier can select them
|
||||
* from the Rewards popup and the product is added to the order automatically.
|
||||
*/
|
||||
getClaimableRewards(coupon_id = false, program_id = false, auto = false) {
|
||||
const baseResult = super.getClaimableRewards(...arguments);
|
||||
|
||||
// Auto mode is the background reward sweep — don't alter it.
|
||||
if (auto) {
|
||||
return baseResult;
|
||||
}
|
||||
|
||||
// Collect program IDs already present so we don't add duplicates.
|
||||
const presentProgramIds = new Set(
|
||||
baseResult.map((r) => r.reward?.program_id?.id)
|
||||
);
|
||||
|
||||
const couponPointChanges = this.uiState.couponPointChanges;
|
||||
const extraRewards = [];
|
||||
|
||||
for (const pe of Object.values(couponPointChanges)) {
|
||||
const program = this.models['loyalty.program'].get(pe.program_id);
|
||||
if (!program || !program.manual_membership) {
|
||||
continue;
|
||||
}
|
||||
if (presentProgramIds.has(program.id)) {
|
||||
continue;
|
||||
}
|
||||
if (coupon_id && pe.coupon_id !== coupon_id) {
|
||||
continue;
|
||||
}
|
||||
if (program_id && pe.program_id !== program_id) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const points = this._getRealCouponPoints(pe.coupon_id);
|
||||
for (const reward of program.reward_ids) {
|
||||
if (points < reward.required_points) {
|
||||
continue;
|
||||
}
|
||||
if (reward.reward_type !== 'product') {
|
||||
// Non-product rewards are already handled by base logic.
|
||||
continue;
|
||||
}
|
||||
// Compute how many free items can be claimed from remaining points.
|
||||
const freeQty = Math.floor(
|
||||
(points / reward.required_points) * (reward.reward_product_qty || 1)
|
||||
);
|
||||
if (freeQty <= 0) {
|
||||
continue;
|
||||
}
|
||||
extraRewards.push({
|
||||
coupon_id: pe.coupon_id,
|
||||
reward: reward,
|
||||
potentialQty: freeQty,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return [...baseResult, ...extraRewards];
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user