205 lines
5.1 KiB
TypeScript
205 lines
5.1 KiB
TypeScript
import { isOneOffPrice } from "@utils/productUtils/priceUtils/classifyPriceUtils.js";
|
|
import type { Entity } from "../../models/cusModels/entityModels/entityModels.js";
|
|
import type { CustomerEntitlementFilters } from "../../models/cusProductModels/cusEntModels/cusEntModels.js";
|
|
import type { FullCusEntWithFullCusProduct } from "../../models/cusProductModels/cusEntModels/cusEntWithProduct.js";
|
|
import type { FullCustomerPrice } from "../../models/cusProductModels/cusPriceModels/cusPriceModels.js";
|
|
import { CusProductStatus } from "../../models/cusProductModels/cusProductEnums.js";
|
|
import type {
|
|
CusProduct,
|
|
FullCusProduct,
|
|
} from "../../models/cusProductModels/cusProductModels.js";
|
|
import { ProcessorType } from "../../models/genModels/genEnums.js";
|
|
import type { BillingType } from "../../models/productModels/priceModels/priceEnums.js";
|
|
import type { FullProduct } from "../../models/productModels/productModels.js";
|
|
import { cusEntMatchesEntity } from "../cusEntUtils/filterCusEntUtils.js";
|
|
import { sortCusEntsForDeduction } from "../cusEntUtils/sortCusEntsForDeduction.js";
|
|
import { getBillingType } from "../productUtils/priceUtils.js";
|
|
import { notNullish } from "../utils.js";
|
|
|
|
export const cusProductsToPrices = ({
|
|
cusProducts,
|
|
filters,
|
|
}: {
|
|
cusProducts: FullCusProduct[];
|
|
filters?: {
|
|
excludeOneOffPrices?: boolean;
|
|
};
|
|
}) => {
|
|
let prices = cusProducts.flatMap((cp) =>
|
|
cusProductToPrices({ cusProduct: cp }),
|
|
);
|
|
if (filters?.excludeOneOffPrices) {
|
|
prices = prices.filter((p) => !isOneOffPrice(p));
|
|
}
|
|
return prices;
|
|
};
|
|
|
|
export const cusProductsToCusPrices = ({
|
|
cusProducts,
|
|
inStatuses,
|
|
billingType,
|
|
}: {
|
|
cusProducts: FullCusProduct[];
|
|
inStatuses?: CusProductStatus[];
|
|
billingType?: BillingType;
|
|
}) => {
|
|
const cusPrices: FullCustomerPrice[] = [];
|
|
|
|
for (const cusProduct of cusProducts) {
|
|
if (inStatuses && !inStatuses.includes(cusProduct.status)) {
|
|
continue;
|
|
}
|
|
|
|
let prices = cusProduct.customer_prices;
|
|
if (billingType) {
|
|
prices = prices.filter(
|
|
(cp) => getBillingType(cp.price.config) === billingType,
|
|
);
|
|
}
|
|
|
|
cusPrices.push(...prices);
|
|
}
|
|
|
|
return cusPrices;
|
|
};
|
|
|
|
export const cusProductsToCusEnts = ({
|
|
cusProducts,
|
|
inStatuses = [CusProductStatus.Active, CusProductStatus.PastDue],
|
|
reverseOrder = false,
|
|
featureId,
|
|
internalFeatureId,
|
|
featureIds,
|
|
entity,
|
|
customerEntitlementFilters,
|
|
isRefund = false,
|
|
}: {
|
|
cusProducts: FullCusProduct[];
|
|
inStatuses?: CusProductStatus[];
|
|
reverseOrder?: boolean;
|
|
featureId?: string;
|
|
internalFeatureId?: string;
|
|
featureIds?: string[];
|
|
entity?: Entity;
|
|
customerEntitlementFilters?: CustomerEntitlementFilters;
|
|
isRefund?: boolean;
|
|
}) => {
|
|
let cusEnts: FullCusEntWithFullCusProduct[] = [];
|
|
|
|
for (const cusProduct of cusProducts) {
|
|
if (!inStatuses.includes(cusProduct.status)) continue;
|
|
|
|
cusEnts.push(
|
|
...cusProduct.customer_entitlements.map((cusEnt) => ({
|
|
...cusEnt,
|
|
customer_product: cusProduct,
|
|
})),
|
|
);
|
|
}
|
|
|
|
if (featureId) {
|
|
cusEnts = cusEnts.filter(
|
|
(cusEnt) => cusEnt.entitlement.feature.id === featureId,
|
|
);
|
|
}
|
|
|
|
if (internalFeatureId) {
|
|
cusEnts = cusEnts.filter(
|
|
(cusEnt) => cusEnt.entitlement.internal_feature_id === internalFeatureId,
|
|
);
|
|
}
|
|
|
|
if (featureIds) {
|
|
cusEnts = cusEnts.filter((cusEnt) =>
|
|
featureIds.includes(cusEnt.entitlement.feature.id),
|
|
);
|
|
}
|
|
|
|
if (entity) {
|
|
cusEnts = cusEnts.filter((cusEnt) =>
|
|
cusEntMatchesEntity({
|
|
cusEnt: cusEnt,
|
|
entity,
|
|
}),
|
|
);
|
|
}
|
|
|
|
sortCusEntsForDeduction({
|
|
cusEnts,
|
|
reverseOrder,
|
|
entityId: entity?.id,
|
|
isRefund,
|
|
// customerEntitlementFilters,
|
|
});
|
|
|
|
if (
|
|
customerEntitlementFilters?.cusEntIds &&
|
|
customerEntitlementFilters.cusEntIds.length > 0
|
|
) {
|
|
cusEnts = cusEnts.filter((cusEnt) =>
|
|
customerEntitlementFilters.cusEntIds?.includes(cusEnt.id),
|
|
);
|
|
}
|
|
|
|
if (notNullish(customerEntitlementFilters?.interval)) {
|
|
cusEnts = cusEnts.filter(
|
|
(cusEnt) =>
|
|
cusEnt.entitlement.interval === customerEntitlementFilters.interval,
|
|
);
|
|
}
|
|
|
|
return cusEnts as FullCusEntWithFullCusProduct[];
|
|
};
|
|
|
|
export const cusProductToPrices = ({
|
|
cusProduct,
|
|
billingType,
|
|
}: {
|
|
cusProduct: FullCusProduct;
|
|
billingType?: BillingType;
|
|
}) => {
|
|
let prices = cusProduct.customer_prices.map((cp) => cp.price);
|
|
|
|
if (billingType) {
|
|
prices = prices.filter((p) => getBillingType(p.config) === billingType);
|
|
}
|
|
|
|
return prices;
|
|
};
|
|
|
|
export const cusProductToEnts = ({
|
|
cusProduct,
|
|
}: {
|
|
cusProduct: FullCusProduct;
|
|
}) => {
|
|
return cusProduct.customer_entitlements.map((ce) => ce.entitlement);
|
|
};
|
|
|
|
export const cusProductToProduct = ({
|
|
cusProduct,
|
|
}: {
|
|
cusProduct: FullCusProduct;
|
|
}) => {
|
|
return {
|
|
...cusProduct.product,
|
|
prices: cusProductToPrices({ cusProduct }),
|
|
entitlements: cusProductToEnts({ cusProduct }),
|
|
free_trial: cusProduct.free_trial,
|
|
} as FullProduct;
|
|
};
|
|
|
|
export const cusProductToCusEnts = ({
|
|
customerProduct,
|
|
}: {
|
|
customerProduct: FullCusProduct;
|
|
}): FullCusEntWithFullCusProduct[] => {
|
|
return customerProduct.customer_entitlements.map((cusEnt) => ({
|
|
...cusEnt,
|
|
customer_product: customerProduct,
|
|
}));
|
|
};
|
|
|
|
export const cusProductToProcessorType = (cusProduct: CusProduct) => {
|
|
return cusProduct.processor?.type ?? ProcessorType.Stripe;
|
|
};
|