Files
cfw-autumn/server/src/internal/customers/attach/attachUtils/mapOptionsList.ts
2026-01-07 14:41:48 +00:00

96 lines
2.3 KiB
TypeScript

import {
ErrCode,
type Feature,
type FeatureOptions,
type FullCusProduct,
type Price,
type UsagePriceConfig,
} from "@autumn/shared";
import { Decimal } from "decimal.js";
import { findPrepaidPrice } from "@/internal/products/prices/priceUtils/findPriceUtils.js";
import { isFreeProduct, isOneOff } from "@/internal/products/productUtils.js";
import RecaseError from "@/utils/errorUtils.js";
/**
* @deprecated Use setupFeatureQuantitiesContext from billing/v2/setup instead
*/
export const mapOptionsList = ({
optionsInput,
features,
prices,
curCusProduct,
}: {
optionsInput?: FeatureOptions[]; // options input
features: Feature[];
prices: Price[];
curCusProduct?: FullCusProduct;
}) => {
const newOptionsList: FeatureOptions[] = [];
for (const options of optionsInput || []) {
const feature = features.find(
(feature) => feature.id === options.feature_id,
);
if (!feature) {
throw new RecaseError({
message: `Feature ${options.feature_id} passed into options but not found`,
code: ErrCode.FeatureNotFound,
});
}
const prepaidPrice = findPrepaidPrice({
prices,
internalFeatureId: feature.internal_id,
});
if (!prepaidPrice) {
throw new RecaseError({
message: `No prepaid price found for feature ${feature.id}`,
code: ErrCode.PriceNotFound,
});
}
// const ent = getPriceEntitlement(prepaidPrice, entitlements)
const config = prepaidPrice.config as UsagePriceConfig;
const dividedQuantity = new Decimal(options.quantity!)
.div(config.billing_units || 1)
.ceil()
.toNumber();
console.log(
`Quantity passed in: ${options.quantity}, billing units: ${config.billing_units}, divided quantity: ${dividedQuantity}`,
);
newOptionsList.push({
...options,
internal_feature_id: feature.internal_id,
quantity: dividedQuantity,
});
}
// If product is one off, return
if (isOneOff(prices) || isFreeProduct(prices)) return newOptionsList;
const curOptionsList = curCusProduct?.options || [];
for (const option of curOptionsList) {
const inNewOptions = newOptionsList.find(
(newOption) => newOption.feature_id === option.feature_id,
);
const prepaidPriceExists = findPrepaidPrice({
prices,
internalFeatureId: option.internal_feature_id!,
});
if (!inNewOptions && prepaidPriceExists) {
newOptionsList.push(option);
}
}
return newOptionsList;
};