Files
cfw-autumn/shared/utils/cusEntUtils/balanceUtils/customerEntitlementToBalancePrice.ts

68 lines
2.5 KiB
TypeScript

import type { ApiBalanceBreakdownPrice } from "@api/customers/cusFeatures/apiBalanceV1.js";
import { BillingMethod } from "@api/products/components/billingMethod.js";
import type { FullCusEntWithFullCusProduct } from "@models/cusProductModels/cusEntModels/cusEntWithProduct.js";
import {
TierBehavior,
type UsagePriceConfig,
} from "@models/productModels/priceModels/priceConfig/usagePriceConfig.js";
import { cusEntsToMaxPurchase } from "@utils/cusEntUtils/convertCusEntUtils/cusEntsToMaxPurchase.js";
import { cusEntToCusPrice } from "@utils/cusEntUtils/convertCusEntUtils/cusEntToCusPrice.js";
import { customerPriceToBillingUnits } from "@utils/cusPriceUtils/convertCustomerPrice/customerPriceToBillingUnits.js";
import {
isFixedPrice,
isPrepaidPrice,
isUsagePrice,
} from "@utils/productUtils/priceUtils/classifyPriceUtils.js";
import { addIncludedToTiers } from "@utils/productV2Utils/productItemUtils/tierUtils.js";
export const customerEntitlementToBalancePrice = ({
customerEntitlement,
}: {
customerEntitlement: FullCusEntWithFullCusProduct;
}): ApiBalanceBreakdownPrice | null => {
const cusPrice = cusEntToCusPrice({ cusEnt: customerEntitlement });
if (!cusPrice) return null;
const price = cusPrice.price;
const maxPurchase = cusEntsToMaxPurchase({ cusEnts: [customerEntitlement] });
const billingUnits = customerPriceToBillingUnits({ customerPrice: cusPrice });
const billingMethod = isPrepaidPrice(price)
? BillingMethod.Prepaid
: BillingMethod.UsageBased;
// Determine amount vs tiers
// If fixed price or usage price with single tier, use amount
// If usage price with multiple tiers, use tiers array
let amount: number | undefined;
let tiers: UsagePriceConfig["usage_tiers"] | undefined;
let tier_behavior: TierBehavior | undefined;
// Get the entitlement's allowance (included usage) to add to tier `to` values
const allowance = customerEntitlement.entitlement.allowance ?? 0;
if (isFixedPrice(price)) {
amount = price.config.amount;
} else if (isUsagePrice({ price })) {
const usageTiers = (price.config as UsagePriceConfig).usage_tiers;
if (usageTiers.length === 1) {
amount = usageTiers[0].amount;
} else {
// Internal: tier `to` does NOT include included usage.
// User-facing: tier `to` INCLUDES included usage.
tiers = addIncludedToTiers({ tiers: usageTiers, included: allowance });
tier_behavior = price.tier_behavior ?? TierBehavior.Graduated;
}
}
return {
amount,
tiers,
tier_behavior,
billing_units: billingUnits,
billing_method: billingMethod,
max_purchase: maxPurchase,
};
};