Files
cfw-autumn/shared/utils/cusUtils/fullCusUtils/fullCustomerToCustomerEntitlements.ts

103 lines
2.8 KiB
TypeScript

import type { Entity } from "../../../models/cusModels/entityModels/entityModels.js";
import type { FullCustomer } from "../../../models/cusModels/fullCusModel.js";
import type { CustomerEntitlementFilters } from "../../../models/cusProductModels/cusEntModels/cusEntModels.js";
import type { FullCusEntWithFullCusProduct } from "../../../models/cusProductModels/cusEntModels/cusEntWithProduct.js";
import { CusProductStatus } from "../../../models/cusProductModels/cusProductEnums.js";
import { cusEntMatchesEntity } from "../../cusEntUtils/filterCusEntUtils.js";
import { sortCusEntsForDeduction } from "../../cusEntUtils/sortCusEntsForDeduction.js";
import { notNullish } from "../../utils.js";
export const fullCustomerToCustomerEntitlements = ({
fullCustomer,
inStatuses = [CusProductStatus.Active, CusProductStatus.PastDue],
reverseOrder = false,
featureId,
featureIds,
entity,
customerEntitlementFilters,
isRefund = false,
}: {
fullCustomer: FullCustomer;
inStatuses?: CusProductStatus[];
reverseOrder?: boolean;
featureId?: string;
featureIds?: string[];
entity?: Entity;
customerEntitlementFilters?: CustomerEntitlementFilters;
isRefund?: boolean;
}) => {
const cusProducts = fullCustomer.customer_products;
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,
})),
);
}
for (const cusEnt of fullCustomer.extra_customer_entitlements || []) {
cusEnts.push({
...cusEnt,
customer_product: null,
});
}
if (featureId) {
cusEnts = cusEnts.filter(
(cusEnt) => cusEnt.entitlement.feature.id === featureId,
);
}
if (featureIds) {
cusEnts = cusEnts.filter((cusEnt) =>
featureIds.includes(cusEnt.entitlement.feature.id),
);
}
if (entity) {
cusEnts = cusEnts.filter((cusEnt) =>
cusEntMatchesEntity({
cusEnt: cusEnt,
entity,
}),
);
}
// Filter out expired entitlements (applies to loose entitlements with expires_at)
// This is necessary because cached fullCustomer may contain entitlements that have since expired
const now = Date.now();
cusEnts = cusEnts.filter(
(cusEnt) => !cusEnt.expires_at || cusEnt.expires_at > now,
);
sortCusEntsForDeduction({
cusEnts,
reverseOrder,
entityId: entity?.id,
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[];
};