feat: added rollover response to get customer

This commit is contained in:
John Yeo
2025-07-24 17:11:54 +01:00
parent 2ac37ba00e
commit 6f2a747d42
4 changed files with 134 additions and 24 deletions

View File

@@ -129,21 +129,6 @@ export const handleUsagePrices = async ({
let ent = relatedCusEnt.entitlement;
let rolloverUpdate = getRolloverUpdates({
cusEnt: relatedCusEnt,
nextResetAt: usageSub.current_period_end * 1000,
});
// console.log(
// "Rollover update received in handleUsagePrices:",
// rolloverUpdate.toInsert.map((rollover) => ({
// id: rollover.id,
// balance: rollover.balance,
// entities: rollover.entities.map((entity) => `${entity.id}: ${entity.balance}`).join(", "),
// expires_at: rollover.expires_at ? new Date(rollover.expires_at).toISOString() : null,
// }))
// );
let resetBalancesUpdate = getResetBalancesUpdate({
cusEnt: relatedCusEnt,
allowance: ent.interval == EntInterval.Lifetime ? 0 : ent.allowance!,
@@ -161,6 +146,11 @@ export const handleUsagePrices = async ({
},
});
let rolloverUpdate = getRolloverUpdates({
cusEnt: relatedCusEnt,
nextResetAt: usageSub.current_period_end * 1000,
});
if (rolloverUpdate?.toInsert && rolloverUpdate.toInsert.length > 0) {
await RolloverService.insert({
db,

View File

@@ -3,6 +3,7 @@ import {
CusEntResponse,
CusEntResponseSchema,
CusEntResponseV2,
CusRollover,
Feature,
FeatureType,
FullCustomerEntitlement,
@@ -66,7 +67,9 @@ export const featuresToObject = ({
usageLimit = undefined;
}
featureObject[featureId] = {
// console.log(`Feature ${featureId} list:`, relatedEnts);
let cusFeature: CusEntResponseV2 = {
id: featureId,
name: feature.name,
type: featureType,
@@ -79,7 +82,6 @@ export const featuresToObject = ({
next_reset_at: getEarliestNextResetAt(relatedEnts),
interval: relatedEnts.length == 1 ? relatedEnts[0].interval : "multiple",
overage_allowed: relatedEnts.some((e) => e.overage_allowed),
// rollovers: relatedEnts.flatMap((e) => e.rollovers),
breakdown:
!unlimited && relatedEnts.length > 1
? relatedEnts.map((e) => ({
@@ -96,7 +98,13 @@ export const featuresToObject = ({
credit_amount: s.credit_amount,
}))
: undefined,
rollovers: relatedEnts
.flatMap((e) => e.rollovers)
.filter(notNullish) as CusRollover[],
};
featureObject[featureId] = cusFeature;
}
return featureObject;

View File

@@ -69,6 +69,100 @@ export const getV1EntitlementsRes = ({
return res;
};
export const getRolloverFields = ({
cusEnt,
entityId,
}: {
cusEnt: FullCustomerEntitlement;
entityId?: string;
}) => {
let hasRollover = notNullish(cusEnt.entitlement.rollover);
if (!hasRollover) {
return null;
}
if (cusEnt.entitlement.entity_feature_id) {
if (entityId) {
return cusEnt.rollovers.reduce(
(acc, rollover) => {
if (rollover.entities[entityId]) {
return {
balance: acc.balance + rollover.entities[entityId].balance,
usage: acc.usage + rollover.entities[entityId].usage,
rollovers: [
...acc.rollovers,
{
balance: rollover.entities[entityId].balance,
usage: rollover.entities[entityId].usage,
expires_at: rollover.expires_at,
},
],
};
}
return acc;
},
{
balance: 0,
usage: 0,
rollovers: [] as any[],
}
);
} else {
return cusEnt.rollovers.reduce(
(acc, rollover) => {
let newBalance = 0;
let newUsage = 0;
for (const entityId in rollover.entities) {
newBalance += rollover.entities[entityId].balance;
newUsage += rollover.entities[entityId].usage;
}
return {
balance: acc.balance + newBalance,
usage: acc.usage + newUsage,
rollovers: [
...acc.rollovers,
{
balance: newBalance,
usage: newUsage,
expires_at: rollover.expires_at,
},
],
};
},
{
balance: 0,
usage: 0,
rollovers: [] as any[],
}
);
}
} else {
return cusEnt.rollovers.reduce(
(acc, rollover) => {
return {
balance: acc.balance + rollover.balance,
usage: acc.usage + rollover.usage,
rollovers: [
...acc.rollovers,
{
balance: rollover.balance,
usage: rollover.usage,
expires_at: rollover.expires_at,
},
],
};
},
{
balance: 0,
usage: 0,
rollovers: [] as any[],
}
);
}
};
// IMPORTANT FUNCTION
export const getCusBalances = async ({
cusEntsWithCusProduct,
@@ -170,11 +264,6 @@ export const getCusBalances = async ({
});
data[key].balance += balance || 0;
// let totalRolloverBalance = cusEnt.rollovers.reduce((acc, rollover) => {
// return acc + (rollover.balance || 0);
// }, 0);
// data[key].balance += totalRolloverBalance;
data[key].adjustment += adjustment || 0;
let total =
@@ -188,6 +277,17 @@ export const getCusBalances = async ({
data[key].total += total;
data[key].unused += unused || 0;
let rollover = getRolloverFields({
cusEnt,
entityId: entity?.id,
});
if (rollover) {
data[key].balance += rollover.balance;
data[key].total += rollover.balance + rollover.usage;
data[key].rollovers = rollover.rollovers;
}
if (org.config.api_version >= BREAK_API_VERSION) {
if (
!data[key].next_reset_at ||
@@ -261,5 +361,9 @@ export const getCusBalances = async ({
});
}
// if (org.api_version == APIVersion.v1) {
// }
return balances as CusFeatureBalance[];
};

View File

@@ -2,6 +2,11 @@ import { z } from "zod";
import { EntInterval } from "../../productModels/entModels/entEnums.js";
import { ProductItemFeatureType } from "../../productV2Models/productItemModels/productItemModels.js";
export const CusRolloverSchema = z.object({
balance: z.number(),
expires_at: z.number(),
});
export const CusEntResponseSchema = z.object({
feature_id: z.string(),
interval: z.nativeEnum(EntInterval).nullish(),
@@ -12,6 +17,7 @@ export const CusEntResponseSchema = z.object({
next_reset_at: z.number().nullish(),
overage_allowed: z.boolean().nullish(),
usage_limit: z.number().nullish(),
rollovers: z.array(CusRolloverSchema).nullish(),
});
export const CoreCusFeatureResponseSchema = z.object({
@@ -31,7 +37,7 @@ export const CoreCusFeatureResponseSchema = z.object({
usage: z.number().nullish(),
included_usage: z.number().nullish(),
next_reset_at: z.number().nullish(),
}),
})
)
.nullish(),
credit_schema: z
@@ -39,11 +45,12 @@ export const CoreCusFeatureResponseSchema = z.object({
z.object({
feature_id: z.string(),
credit_amount: z.number(),
}),
})
)
.nullish(),
usage_limit: z.number().nullish(),
rollovers: z.array(CusRolloverSchema).nullish(),
});
export const CusEntResponseV2Schema = z
@@ -68,3 +75,4 @@ export const CheckResponseSchema = z
export type CusEntResponse = z.infer<typeof CusEntResponseSchema>;
export type CusEntResponseV2 = z.infer<typeof CusEntResponseV2Schema>;
export type CheckResponse = z.infer<typeof CheckResponseSchema>;
export type CusRollover = z.infer<typeof CusRolloverSchema>;