Files
PolyWeather/frontend/lib/billing-utils.ts
T

70 lines
1.8 KiB
TypeScript
Raw Normal View History

export interface TerminalBilling {
planAmount: number;
pointsEnabled: boolean;
pointsPerUsdc: number;
maxDiscountUsdc: number;
pointsUsed: number;
discountAmount: number;
payAmount: number;
canRedeem: boolean;
}
export interface PointsRedemptionConfig {
enabled?: boolean;
points_per_usdc?: number;
max_discount_usdc?: number;
}
export function computeBilling(params: {
planPriceUsd: number;
totalPoints: number;
usePoints: boolean;
redemptionCfg?: PointsRedemptionConfig | null;
}): TerminalBilling {
const planAmount =
Number.isFinite(params.planPriceUsd) && params.planPriceUsd > 0
? params.planPriceUsd
: 10;
const cfg = params.redemptionCfg || {};
const pointsEnabled = cfg.enabled !== false;
const pointsPerUsdcRaw = Number(cfg.points_per_usdc ?? 500);
const pointsPerUsdc =
Number.isFinite(pointsPerUsdcRaw) && pointsPerUsdcRaw > 0
? Math.floor(pointsPerUsdcRaw)
: 500;
const maxDiscountRaw = Number(cfg.max_discount_usdc ?? 3);
const maxDiscountUsdc = Math.max(
0,
Math.min(
Math.floor(Number.isFinite(maxDiscountRaw) ? maxDiscountRaw : 3),
Math.floor(planAmount),
),
);
const maxRedeemablePoints = pointsPerUsdc * maxDiscountUsdc;
const actualRedeem = pointsEnabled
? Math.min(params.totalPoints, maxRedeemablePoints)
: 0;
const discountUnits = Math.floor(actualRedeem / pointsPerUsdc);
const pointsUsed = discountUnits * pointsPerUsdc;
const canRedeem =
pointsEnabled &&
maxDiscountUsdc > 0 &&
params.totalPoints >= pointsPerUsdc;
const applyDiscount =
params.usePoints && canRedeem && pointsUsed > 0;
return {
planAmount,
pointsEnabled,
pointsPerUsdc,
maxDiscountUsdc,
pointsUsed,
discountAmount: discountUnits,
payAmount: planAmount - (applyDiscount ? discountUnits : 0),
canRedeem,
};
}