fix: usage limits for v1 api
This commit is contained in:
11
server/src/external/autumn/autumnCli.ts
vendored
11
server/src/external/autumn/autumnCli.ts
vendored
@@ -435,17 +435,16 @@ export class AutumnInt {
|
||||
|
||||
stripe = {
|
||||
connect: async (params: {
|
||||
testApiKey: string;
|
||||
liveApiKey: string;
|
||||
successUrl: string;
|
||||
defaultCurrency: string;
|
||||
secret_key: string;
|
||||
success_url: string;
|
||||
default_currency: string;
|
||||
}) => {
|
||||
const data = await this.post(`/org/stripe`, params);
|
||||
const data = await this.post(`/organization/stripe`, params);
|
||||
return data;
|
||||
},
|
||||
|
||||
delete: async () => {
|
||||
const data = await this.delete(`/org/stripe`);
|
||||
const data = await this.delete(`/organization/stripe`);
|
||||
return data;
|
||||
},
|
||||
};
|
||||
|
||||
@@ -67,7 +67,9 @@ apiRouter.post("/setup_payment", handleSetupPayment);
|
||||
// Analytics
|
||||
apiRouter.use("/query", analyticsRouter);
|
||||
apiRouter.use("/platform", platformRouter);
|
||||
|
||||
// Used for tests...
|
||||
apiRouter.post("/organization/stripe", handleConnectStripe);
|
||||
// apiRouter.delete("/org/stripe", handleDeleteStripe);
|
||||
apiRouter.delete("/organization/stripe", handleDeleteStripe);
|
||||
|
||||
export { apiRouter };
|
||||
|
||||
@@ -2,6 +2,7 @@ import {
|
||||
getFeatureBalance,
|
||||
cusEntsContainFeature,
|
||||
getUnlimitedAndUsageAllowed,
|
||||
getPaidFeatureBalance,
|
||||
} from "@/internal/customers/cusProducts/cusEnts/cusEntUtils.js";
|
||||
import { featureToCreditSystem } from "@/internal/features/creditSystemUtils.js";
|
||||
import {
|
||||
@@ -88,6 +89,8 @@ export const getV1CheckResponse = ({
|
||||
internalFeatureId: feature.internal_id!,
|
||||
});
|
||||
|
||||
console.log(`Feature ${feature.id}, Usage allowed: ${usageAllowed}`);
|
||||
|
||||
if (unlimited || usageAllowed) {
|
||||
balances.push({
|
||||
feature_id: feature.id,
|
||||
@@ -103,7 +106,6 @@ export const getV1CheckResponse = ({
|
||||
}),
|
||||
});
|
||||
allowed = true;
|
||||
// continue;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -116,6 +118,11 @@ export const getV1CheckResponse = ({
|
||||
entityId,
|
||||
});
|
||||
|
||||
let totalPaidAllowance = getPaidFeatureBalance({
|
||||
cusEnts,
|
||||
internalFeatureId: feature.internal_id!,
|
||||
});
|
||||
|
||||
let newBalance: any = {
|
||||
feature_id: feature.id,
|
||||
required,
|
||||
@@ -129,7 +136,7 @@ export const getV1CheckResponse = ({
|
||||
balances.push(newBalance);
|
||||
|
||||
// allowed = allowed && actual! >= required;
|
||||
allowed = actual! >= required;
|
||||
allowed = actual! + (totalPaidAllowance || 0) >= required;
|
||||
|
||||
if (allowed) {
|
||||
break;
|
||||
|
||||
@@ -32,6 +32,7 @@ import {
|
||||
getSummedEntityBalances,
|
||||
} from "./entBalanceUtils.js";
|
||||
import { Decimal } from "decimal.js";
|
||||
import { logger } from "better-auth";
|
||||
|
||||
export const getCusEntMasterBalance = ({
|
||||
cusEnt,
|
||||
@@ -343,9 +344,11 @@ export const getResetBalance = ({
|
||||
export const getUnlimitedAndUsageAllowed = ({
|
||||
cusEnts,
|
||||
internalFeatureId,
|
||||
includeUsageLimit = true,
|
||||
}: {
|
||||
cusEnts: FullCustomerEntitlement[];
|
||||
internalFeatureId: string;
|
||||
includeUsageLimit?: boolean;
|
||||
}) => {
|
||||
// Unlimited
|
||||
|
||||
@@ -360,7 +363,7 @@ export const getUnlimitedAndUsageAllowed = ({
|
||||
(ent) =>
|
||||
ent.internal_feature_id === internalFeatureId &&
|
||||
ent.usage_allowed &&
|
||||
nullish(ent.entitlement.usage_limit)
|
||||
(includeUsageLimit ? nullish(ent.entitlement.usage_limit) : true)
|
||||
);
|
||||
|
||||
return { unlimited, usageAllowed };
|
||||
@@ -424,6 +427,32 @@ export const getFeatureBalance = ({
|
||||
return balance;
|
||||
};
|
||||
|
||||
export const getPaidFeatureBalance = ({
|
||||
cusEnts,
|
||||
internalFeatureId,
|
||||
}: {
|
||||
cusEnts: FullCustomerEntitlement[];
|
||||
internalFeatureId: string;
|
||||
}) => {
|
||||
let paidAllowance = 0;
|
||||
try {
|
||||
for (const cusEnt of cusEnts) {
|
||||
if (cusEnt.internal_feature_id !== internalFeatureId) continue;
|
||||
|
||||
if (notNullish(cusEnt.entitlement.usage_limit)) {
|
||||
paidAllowance = new Decimal(paidAllowance)
|
||||
.plus(cusEnt.entitlement.usage_limit!)
|
||||
.minus(cusEnt.entitlement.allowance || 0)
|
||||
.toNumber();
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error(`Failed to get paid feature balance`, { error });
|
||||
}
|
||||
|
||||
return paidAllowance;
|
||||
};
|
||||
|
||||
export const cusEntsContainFeature = ({
|
||||
cusEnts,
|
||||
feature,
|
||||
|
||||
@@ -11,7 +11,10 @@ import {
|
||||
import { getCusEntsInFeatures } from "@/internal/customers/cusUtils/cusUtils.js";
|
||||
|
||||
import { featureToCreditSystem } from "@/internal/features/creditSystemUtils.js";
|
||||
import { getFeatureBalance } from "@/internal/customers/cusProducts/cusEnts/cusEntUtils.js";
|
||||
import {
|
||||
getFeatureBalance,
|
||||
getPaidFeatureBalance,
|
||||
} from "@/internal/customers/cusProducts/cusEnts/cusEntUtils.js";
|
||||
import { Decimal } from "decimal.js";
|
||||
|
||||
import {
|
||||
|
||||
@@ -86,10 +86,9 @@ export const clearOrg = async ({
|
||||
} catch (error) {}
|
||||
try {
|
||||
await autumn.stripe.connect({
|
||||
testApiKey: process.env.STRIPE_TEST_KEY!,
|
||||
liveApiKey: process.env.STRIPE_TEST_KEY!,
|
||||
successUrl: "https://useautumn.com",
|
||||
defaultCurrency: "usd",
|
||||
secret_key: process.env.STRIPE_TEST_KEY!,
|
||||
success_url: "https://useautumn.com",
|
||||
default_currency: "usd",
|
||||
});
|
||||
} catch (error: any) {
|
||||
console.error("Error reconnecting stripe", error.message);
|
||||
|
||||
@@ -11,10 +11,15 @@ export const formatTimestamp = (timestamp: number | null | undefined) => {
|
||||
|
||||
export const formatUnixToDate = (
|
||||
unix: number | null | undefined,
|
||||
excludeYear = false,
|
||||
excludeYear = false
|
||||
) => {
|
||||
if (!unix) return "";
|
||||
return format(new Date(unix), excludeYear ? "d MMM" : "d MMM yyyy");
|
||||
try {
|
||||
const date = format(new Date(unix), excludeYear ? "d MMM" : "d MMM yyyy");
|
||||
return date;
|
||||
} catch (error) {
|
||||
return "";
|
||||
}
|
||||
};
|
||||
|
||||
export const formatUnixToDateTime = (unix: number | null | undefined) => {
|
||||
|
||||
@@ -45,20 +45,21 @@ export const AttachInfo = () => {
|
||||
);
|
||||
});
|
||||
|
||||
let text = `You are switching this customer to version ${product.version} of ${product.name}.`;
|
||||
if (preview.due_next_cycle?.due_at) {
|
||||
text += `Their features will update immediately and from ${formatUnixToDate(preview.due_next_cycle?.due_at)} onwards, they will pay any new prices${usagePriceExists ? " (including usage from the last cycle)" : ""}.`;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<span>
|
||||
You are switching this customer to version {product.version} of{" "}
|
||||
{product.name}. Their features will update immediately and from{" "}
|
||||
{format(preview.due_next_cycle?.due_at, "d MMM")} onwards, they will
|
||||
pay any new prices
|
||||
{usagePriceExists ? " (including usage from the last cycle)" : ""}.
|
||||
{/* You are switching this customer to version {product.version} of{" "}
|
||||
{product.name}. */}
|
||||
{text}
|
||||
</span>
|
||||
</>
|
||||
);
|
||||
|
||||
const text = `You are switching this customer to version ${product.version} of ${product.name}.`;
|
||||
|
||||
// let text = `The customer is currently on ${currentProduct.name} v${currentProduct.version}. Switching to v${product.version} will update the customer's features immediately, and from ${formatUnixToDate(preview.due_next_cycle.due_at)} onwards they will pay any new prices`;
|
||||
|
||||
// if (usagePriceExists) {
|
||||
|
||||
Reference in New Issue
Block a user