Start fixing points

This commit is contained in:
2025-09-25 21:27:28 -04:00
parent 4ea3a4aec3
commit d3e3cba087
4 changed files with 134 additions and 143 deletions

View File

@@ -48,13 +48,13 @@ const BUCKET_CASE = (() => {
return `CASE\n ${parts.join('\n ')}\n END`;
})();
const DEFAULT_POINT_DOLLAR_VALUE = 0.005; // 1000 points = $5
const DEFAULT_POINT_DOLLAR_VALUE = 0.005; // 1000 points = $5, so 200 points = $1
const DEFAULTS = {
merchantFeePercent: 2.9,
fixedCostPerOrder: 1.5,
pointsPerDollar: 0,
pointsRedemptionRate: 0,
pointsRedemptionRate: 0, // Will be calculated from actual data
pointDollarValue: DEFAULT_POINT_DOLLAR_VALUE,
};
@@ -265,8 +265,8 @@ router.post('/simulate', async (req, res) => {
${BUCKET_CASE} AS bucket_key
FROM _order o
${promoJoin}
WHERE o.summary_total > 0
AND o.summary_subtotal > 0
WHERE o.summary_shipping > 0
AND o.summary_total > 0
AND o.order_status NOT IN (15)
AND o.ship_method_selected <> 'holdit'
AND o.ship_country = ?
@@ -302,7 +302,7 @@ router.post('/simulate', async (req, res) => {
GROUP BY order_id
) AS c ON c.order_id = f.order_id
LEFT JOIN (
SELECT order_id, SUM(discount_amount_points) AS points_redeemed
SELECT order_id, SUM(discount_amount) AS points_redeemed
FROM order_discounts
WHERE discount_type = 20 AND discount_active = 1
GROUP BY order_id
@@ -366,11 +366,54 @@ router.post('/simulate', async (req, res) => {
? totals.pointsAwarded / totals.subtotal
: 0;
const redemptionRate = config.points.redemptionRate != null
? config.points.redemptionRate
: totals.pointsAwarded > 0
? Math.min(1, totals.pointsRedeemed / totals.pointsAwarded)
: 0;
// Calculate redemption rate with extended lookback to account for redemption lag
let calculatedRedemptionRate = 0;
if (config.points.redemptionRate != null) {
calculatedRedemptionRate = config.points.redemptionRate;
} else if (totals.pointsAwarded > 0) {
// Use a 12-month lookback to capture more realistic redemption patterns
const extendedStartDt = startDt.minus({ months: 12 });
const extendedRedemptionQuery = `
SELECT SUM(od.discount_amount) as extended_redemptions
FROM order_discounts od
JOIN _order o ON od.order_id = o.order_id
WHERE od.discount_type = 20 AND od.discount_active = 1
AND o.order_status NOT IN (15)
AND o.ship_country = ?
AND o.date_placed BETWEEN ? AND ?
AND o.order_cid IN (
SELECT DISTINCT order_cid
FROM _order
WHERE date_placed BETWEEN ? AND ?
AND order_status NOT IN (15)
AND summary_points > 0
)
`;
try {
const [extendedRows] = await connection.execute(extendedRedemptionQuery, [
shipCountry,
formatDateForSql(extendedStartDt),
formatDateForSql(endDt),
formatDateForSql(startDt),
formatDateForSql(endDt)
]);
const extendedRedemptions = Number(extendedRows[0]?.extended_redemptions || 0);
// Convert dollar redemptions to points using the correct conversion rate (200 points = $1)
const extendedRedemptionsInPoints = extendedRedemptions * 200;
if (extendedRedemptionsInPoints > 0) {
calculatedRedemptionRate = Math.min(1, extendedRedemptionsInPoints / totals.pointsAwarded);
} else {
throw new Error('Unable to calculate redemption rate: no redemption data found in extended lookback period');
}
} catch (error) {
console.error('Failed to calculate redemption rate:', error);
throw error; // Let it fail instead of using fallback
}
}
const redemptionRate = calculatedRedemptionRate;
const pointDollarValue = config.points.pointDollarValue || DEFAULT_POINT_DOLLAR_VALUE;