From dfd52fe1cc972f2dd69e054a92f8cac40ca55921 Mon Sep 17 00:00:00 2001 From: Suherdy Yacob Date: Fri, 29 May 2026 15:19:59 +0700 Subject: [PATCH] fix: add orphan reward line cleanup and implement optional chaining for program_id access in POS loyalty logic --- static/src/app/models/pos_order.js | 13 +++++++++---- .../control_buttons/control_buttons.js | 4 ++-- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/static/src/app/models/pos_order.js b/static/src/app/models/pos_order.js index c5bd7bb..d9a0361 100644 --- a/static/src/app/models/pos_order.js +++ b/static/src/app/models/pos_order.js @@ -361,6 +361,11 @@ patch(PosOrder.prototype, { const otherRewards = []; const paymentRewards = []; for (const line of otherRewardLines) { + // Skip (and delete) orphaned reward lines where program_id is missing + if (!line.reward_id || !line.reward_id.program_id) { + line.delete(); + continue; + } const claimedReward = { reward: line.reward_id, coupon_id: line.coupon_id?.id, @@ -373,8 +378,8 @@ patch(PosOrder.prototype, { reward_identifier_code: line.reward_identifier_code, }; if ( - claimedReward.reward.program_id.program_type === "gift_card" || - claimedReward.reward.program_id.program_type === "ewallet" + claimedReward.reward.program_id?.program_type === "gift_card" || + claimedReward.reward.program_id?.program_type === "ewallet" ) { paymentRewards.push(claimedReward); } else if (claimedReward.reward.reward_type === "product") { @@ -418,7 +423,7 @@ patch(PosOrder.prototype, { continue; } if ( - claimedReward.reward.program_id.program_type === "coupons" && + claimedReward.reward.program_id?.program_type === "coupons" && this.lines.find( (rewardline) => rewardline.reward_id?.id === claimedReward.reward.id ) @@ -428,7 +433,7 @@ patch(PosOrder.prototype, { if ( claimedReward.reward.reward_product_ids?.length === 1 && allRewardsMerged.filter( - (reward) => reward.reward.program_id.id === claimedReward.reward.program_id.id + (reward) => reward.reward.program_id?.id === claimedReward.reward.program_id?.id ).length === 1 ) { delete claimedReward.args["quantity"]; diff --git a/static/src/app/screens/product_screen/control_buttons/control_buttons.js b/static/src/app/screens/product_screen/control_buttons/control_buttons.js index 7129611..f32d168 100644 --- a/static/src/app/screens/product_screen/control_buttons/control_buttons.js +++ b/static/src/app/screens/product_screen/control_buttons/control_buttons.js @@ -93,8 +93,8 @@ patch(ControlButtons.prototype, { } if ( - (reward.reward_type == "product" && reward.program_id.applies_on !== "both") || - (reward.program_id.applies_on == "both" && potentialQty) + (reward.reward_type == "product" && reward.program_id?.applies_on !== "both") || + (reward.program_id?.applies_on == "both" && potentialQty) ) { const product = args["product"] || reward.reward_product_ids[0]; await this.pos.addLineToCurrentOrder(