fix: usage_limits field returned in get customer and check
This commit is contained in:
14
server/src/external/resend/resendUtils.ts
vendored
14
server/src/external/resend/resendUtils.ts
vendored
@@ -41,11 +41,25 @@ export const sendTextEmail = async ({
|
||||
if (error) {
|
||||
logger.error(`Error sending email`, {
|
||||
error,
|
||||
data: {
|
||||
from,
|
||||
fromEmail,
|
||||
to,
|
||||
subject,
|
||||
body,
|
||||
},
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error(`Error sending email`, {
|
||||
error,
|
||||
data: {
|
||||
from,
|
||||
fromEmail,
|
||||
to,
|
||||
subject,
|
||||
body,
|
||||
},
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
|
||||
@@ -5,21 +5,16 @@ import {
|
||||
type Feature,
|
||||
FeatureType,
|
||||
type FullCustomerEntitlement,
|
||||
type Organization,
|
||||
} from "@autumn/shared";
|
||||
|
||||
import {
|
||||
cusEntsContainFeature,
|
||||
getFeatureBalance,
|
||||
getUnlimitedAndUsageAllowed,
|
||||
} from "@/internal/customers/cusProducts/cusEnts/cusEntUtils.js";
|
||||
import { getFeatureBalance } from "@/internal/customers/cusProducts/cusEnts/cusEntUtils.js";
|
||||
|
||||
import { Router } from "express";
|
||||
import { StatusCodes } from "http-status-codes";
|
||||
import { handleEventSent } from "../events/eventRouter.js";
|
||||
import { featureToCreditSystem } from "@/internal/features/creditSystemUtils.js";
|
||||
import { notNullish } from "@/utils/genUtils.js";
|
||||
import { SuccessCode } from "@autumn/shared";
|
||||
|
||||
import { handleProductCheck } from "./handlers/handleProductCheck.js";
|
||||
import { getBooleanEntitledResult } from "./checkUtils.js";
|
||||
import { getCheckPreview } from "./getCheckPreview.js";
|
||||
@@ -183,6 +178,7 @@ checkRouter.post("", async (req: any, res: any) => {
|
||||
org,
|
||||
cusProducts,
|
||||
requiredBalance,
|
||||
apiVersion,
|
||||
});
|
||||
|
||||
const { allowed, balance } = v2Response;
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
import {
|
||||
getFeatureBalance,
|
||||
getUnlimitedAndUsageAllowed,
|
||||
} from "@/internal/customers/cusProducts/cusEnts/cusEntUtils.js";
|
||||
import { getUnlimitedAndUsageAllowed } from "@/internal/customers/cusProducts/cusEnts/cusEntUtils.js";
|
||||
import { cusEntMatchesFeature } from "@/internal/customers/cusProducts/cusEnts/cusEntUtils/findCusEntUtils.js";
|
||||
import { getCusBalances } from "@/internal/customers/cusUtils/cusFeatureResponseUtils/getCusBalances.js";
|
||||
import { balancesToFeatureResponse } from "@/internal/customers/cusUtils/cusFeatureResponseUtils/balancesToFeatureResponse.js";
|
||||
import {
|
||||
CheckResponseSchema,
|
||||
Feature,
|
||||
FeatureType,
|
||||
FullCusEntWithFullCusProduct,
|
||||
FullCusProduct,
|
||||
FullCustomer,
|
||||
@@ -16,7 +12,6 @@ import {
|
||||
SuccessCode,
|
||||
} from "@autumn/shared";
|
||||
import { notNullish } from "@/utils/genUtils.js";
|
||||
import { freeTrialsAreSame } from "@/internal/products/free-trials/freeTrialUtils.js";
|
||||
|
||||
export const getFeatureToUse = ({
|
||||
creditSystems,
|
||||
@@ -59,6 +54,7 @@ export const getV2CheckResponse = async ({
|
||||
org,
|
||||
cusProducts,
|
||||
requiredBalance,
|
||||
apiVersion,
|
||||
}: {
|
||||
fullCus: FullCustomer;
|
||||
cusEnts: FullCusEntWithFullCusProduct[];
|
||||
@@ -67,6 +63,7 @@ export const getV2CheckResponse = async ({
|
||||
org: Organization;
|
||||
cusProducts: FullCusProduct[];
|
||||
requiredBalance?: number;
|
||||
apiVersion: number;
|
||||
}) => {
|
||||
// 1. Get the feature to use
|
||||
const featureToUse = getFeatureToUse({
|
||||
@@ -92,6 +89,7 @@ export const getV2CheckResponse = async ({
|
||||
cusPrices,
|
||||
org,
|
||||
entity: fullCus.entity,
|
||||
apiVersion,
|
||||
});
|
||||
|
||||
let cusFeatures = balancesToFeatureResponse({
|
||||
@@ -99,37 +97,40 @@ export const getV2CheckResponse = async ({
|
||||
balances,
|
||||
});
|
||||
|
||||
// cusFeature.balance += overage_limit
|
||||
|
||||
const cusFeature = cusFeatures[featureToUse.id] || {};
|
||||
|
||||
let allowed = false;
|
||||
let totalUsageLimit = 0;
|
||||
console.log(featureCusEnts.length);
|
||||
for (const ent of featureCusEnts) {
|
||||
totalUsageLimit += ent.entitlement.usage_limit || 0;
|
||||
}
|
||||
|
||||
console.log("Feature Balance", cusFeature.balance);
|
||||
console.log("Total Usage Limit", totalUsageLimit);
|
||||
console.log("Required Balance", requiredBalance);
|
||||
console.log("Current Usage", cusFeature.usage);
|
||||
let totalPaidUsageAllowance = featureCusEnts.reduce((acc, ce) => {
|
||||
let ent = ce.entitlement;
|
||||
if (notNullish(ent.usage_limit)) {
|
||||
return acc + ent.usage_limit! - (ent.allowance || 0);
|
||||
}
|
||||
return acc;
|
||||
}, 0);
|
||||
|
||||
if (
|
||||
(cusFeature && unlimited) ||
|
||||
usageAllowed ||
|
||||
cusFeature.balance >= (requiredBalance || 1)
|
||||
// cusFeature.balance >= (requiredBalance || 1)
|
||||
cusFeature.balance + totalPaidUsageAllowance >= (requiredBalance || 1)
|
||||
) {
|
||||
allowed = true;
|
||||
}
|
||||
|
||||
console.log("Included Usage", cusFeature.included_usage);
|
||||
// let totalUsageLimit = 0;
|
||||
|
||||
if (totalUsageLimit > 0) {
|
||||
if ((cusFeature.balance - (requiredBalance || 1)) < -(totalUsageLimit - (cusFeature.included_usage || 0))) {
|
||||
allowed = false;
|
||||
}
|
||||
}
|
||||
// for (const ent of featureCusEnts) {
|
||||
// totalUsageLimit += ent.entitlement.usage_limit || 0;
|
||||
// }
|
||||
// if (totalUsageLimit > 0) {
|
||||
// if (
|
||||
// cusFeature.balance - (requiredBalance || 1) <
|
||||
// -(totalUsageLimit - (cusFeature.included_usage || 0))
|
||||
// ) {
|
||||
// allowed = false;
|
||||
// }
|
||||
// }
|
||||
|
||||
return CheckResponseSchema.parse({
|
||||
customer_id: fullCus.id,
|
||||
|
||||
@@ -351,7 +351,10 @@ export const getUnlimitedAndUsageAllowed = ({
|
||||
);
|
||||
|
||||
const usageAllowed = cusEnts.some(
|
||||
(ent) => ent.internal_feature_id === internalFeatureId && ent.usage_allowed,
|
||||
(ent) =>
|
||||
ent.internal_feature_id === internalFeatureId &&
|
||||
ent.usage_allowed &&
|
||||
nullish(ent.entitlement.usage_limit),
|
||||
);
|
||||
|
||||
return { unlimited, usageAllowed };
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
getCusFeatureType,
|
||||
isCreditSystem,
|
||||
} from "@/internal/features/featureUtils.js";
|
||||
import { notNullish } from "@/utils/genUtils.js";
|
||||
|
||||
export const sumValues = (
|
||||
entList: CusEntResponse[],
|
||||
@@ -46,6 +47,7 @@ export const featuresToObject = ({
|
||||
entList: CusEntResponse[];
|
||||
}) => {
|
||||
let featureObject: Record<string, CusEntResponseV2> = {};
|
||||
|
||||
for (let entRes of entList) {
|
||||
let feature = features.find((f) => f.id == entRes.feature_id)!;
|
||||
let featureType = getCusFeatureType({ feature });
|
||||
@@ -57,7 +59,13 @@ export const featuresToObject = ({
|
||||
if (featureObject[featureId]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
let includedUsage = sumValues(relatedEnts, "included_usage");
|
||||
let usageLimit: number | undefined = sumValues(relatedEnts, "usage_limit");
|
||||
if (notNullish(usageLimit) && usageLimit === includedUsage) {
|
||||
usageLimit = undefined;
|
||||
}
|
||||
|
||||
featureObject[featureId] = {
|
||||
id: featureId,
|
||||
name: feature.name,
|
||||
@@ -66,7 +74,7 @@ export const featuresToObject = ({
|
||||
balance: unlimited ? null : sumValues(relatedEnts, "balance"),
|
||||
usage: sumValues(relatedEnts, "usage"),
|
||||
included_usage: sumValues(relatedEnts, "included_usage"),
|
||||
usage_limit: sumValues(relatedEnts, "usage_limit"),
|
||||
usage_limit: usageLimit,
|
||||
|
||||
next_reset_at: getEarliestNextResetAt(relatedEnts),
|
||||
interval: relatedEnts.length == 1 ? relatedEnts[0].interval : "multiple",
|
||||
|
||||
@@ -63,6 +63,7 @@ export const getV1EntitlementsRes = ({
|
||||
res.next_reset_at =
|
||||
isBoolean || unlimited ? undefined : cusEnt.next_reset_at;
|
||||
res.allowance = isBoolean || unlimited ? undefined : 0;
|
||||
res.usage_limit = isBoolean || unlimited ? undefined : 0;
|
||||
}
|
||||
|
||||
return res;
|
||||
@@ -74,6 +75,7 @@ export const getCusBalances = async ({
|
||||
cusPrices,
|
||||
org,
|
||||
entity,
|
||||
apiVersion,
|
||||
}: {
|
||||
cusEntsWithCusProduct: (FullCustomerEntitlement & {
|
||||
customer_product: FullCusProduct;
|
||||
@@ -81,6 +83,7 @@ export const getCusBalances = async ({
|
||||
cusPrices: FullCustomerPrice[];
|
||||
org: Organization;
|
||||
entity?: Entity;
|
||||
apiVersion: number;
|
||||
}) => {
|
||||
const data: Record<string, any> = {};
|
||||
const features = cusEntsWithCusProduct.map(
|
||||
@@ -116,7 +119,7 @@ export const getCusBalances = async ({
|
||||
});
|
||||
|
||||
// 1. Initialize balance object
|
||||
if (!data[key] && org.api_version == APIVersion.v1) {
|
||||
if (!data[key] && apiVersion == APIVersion.v1) {
|
||||
data[key] = getV1EntitlementsRes({
|
||||
org,
|
||||
cusEnt,
|
||||
@@ -146,13 +149,13 @@ export const getCusBalances = async ({
|
||||
used: isBoolean ? undefined : unlimited ? null : 0,
|
||||
unused: 0,
|
||||
overage_allowed: usageAllowed,
|
||||
usage_limit: ent.usage_limit ?? null,
|
||||
};
|
||||
|
||||
if (org.config.api_version >= BREAK_API_VERSION) {
|
||||
data[key].next_reset_at =
|
||||
isBoolean || unlimited ? undefined : cusEnt.next_reset_at;
|
||||
data[key].allowance = isBoolean || unlimited ? undefined : 0;
|
||||
data[key].usage_limit = isBoolean || unlimited ? undefined : 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -179,7 +182,6 @@ export const getCusBalances = async ({
|
||||
|
||||
data[key].total += total;
|
||||
data[key].unused += unused || 0;
|
||||
// data[key].overage_limit = ent.usage_limit;
|
||||
|
||||
if (org.config.api_version >= BREAK_API_VERSION) {
|
||||
if (
|
||||
@@ -197,6 +199,13 @@ export const getCusBalances = async ({
|
||||
});
|
||||
|
||||
data[key].allowance += (resetBalance || 0) * count;
|
||||
|
||||
let usageLimit = ent.usage_limit;
|
||||
if (notNullish(usageLimit)) {
|
||||
data[key].usage_limit += usageLimit;
|
||||
} else {
|
||||
data[key].usage_limit += ent.allowance || 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,9 +15,7 @@ import {
|
||||
Organization,
|
||||
FullCustomer,
|
||||
CusExpand,
|
||||
RewardType,
|
||||
RewardResponse,
|
||||
CouponDurationType,
|
||||
EntityResponseSchema,
|
||||
} from "@autumn/shared";
|
||||
import { getCusInvoices } from "./cusUtils.js";
|
||||
@@ -77,6 +75,7 @@ export const getCustomerDetails = async ({
|
||||
cusEntsWithCusProduct: cusEnts,
|
||||
cusPrices: cusProductsToCusPrices({ cusProducts, inStatuses }),
|
||||
org,
|
||||
apiVersion,
|
||||
});
|
||||
|
||||
let subIds = cusProducts.flatMap(
|
||||
|
||||
@@ -27,7 +27,8 @@ export const sendMigrationEmail = safeResend({
|
||||
|
||||
console.log("Sending migration email");
|
||||
await sendTextEmail({
|
||||
from: "John",
|
||||
from: `Autumn`,
|
||||
fromEmail: "hey",
|
||||
to: "johnyeocx@gmail.com",
|
||||
subject: `Migration Job Finished -- ${migrationJob.id}`,
|
||||
body: `
|
||||
|
||||
@@ -134,7 +134,7 @@ export const createEntityForCusProduct = async ({
|
||||
) {
|
||||
throw new RecaseError({
|
||||
message: `Cannot create ${inputEntities.length} entities for feature ${feature.name} as it would exceed the usage limit.`,
|
||||
code: ErrCode.InvalidInputs,
|
||||
code: ErrCode.FeatureLimitReached,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -49,7 +49,6 @@ export const auth = betterAuth({
|
||||
"http://localhost:3000",
|
||||
"https://app.useautumn.com",
|
||||
"https://*.useautumn.com",
|
||||
process.env.CLIENT_URL!,
|
||||
],
|
||||
emailAndPassword: {
|
||||
enabled: true,
|
||||
|
||||
@@ -2,7 +2,7 @@ import chalk from "chalk";
|
||||
import Stripe from "stripe";
|
||||
import { AutumnInt } from "@/external/autumn/autumnCli.js";
|
||||
import { initCustomer } from "@/utils/scriptUtils/initCustomer.js";
|
||||
import { APIVersion, AppEnv, Organization } from "@autumn/shared";
|
||||
import { APIVersion, AppEnv, ErrCode, Organization } from "@autumn/shared";
|
||||
|
||||
import { DrizzleCli } from "@/db/initDrizzle.js";
|
||||
import { setupBefore } from "tests/before.js";
|
||||
@@ -11,19 +11,22 @@ import { constructProduct } from "@/utils/scriptUtils/createTestProducts.js";
|
||||
import { constructArrearProratedItem } from "@/utils/scriptUtils/constructItem.js";
|
||||
import { TestFeature } from "tests/setup/v2Features.js";
|
||||
import { addPrefixToProducts, runAttachTest } from "tests/attach/utils.js";
|
||||
import { expectAutumnError } from "tests/utils/expectUtils/expectErrUtils.js";
|
||||
import { expect } from "chai";
|
||||
|
||||
const userItem = constructArrearProratedItem({
|
||||
featureId: TestFeature.Users,
|
||||
pricePerUnit: 50,
|
||||
includedUsage: 0,
|
||||
usageLimit: 2,
|
||||
});
|
||||
|
||||
export let pro = constructProduct({
|
||||
items: [
|
||||
constructArrearProratedItem({
|
||||
featureId: TestFeature.Users,
|
||||
pricePerUnit: 50,
|
||||
usageLimit: 2,
|
||||
}),
|
||||
],
|
||||
items: [userItem],
|
||||
type: "pro",
|
||||
});
|
||||
|
||||
const testCase = "entity1";
|
||||
const testCase = "usageLimit1";
|
||||
|
||||
describe(`${chalk.yellowBright(`${testCase}: Testing entities`)}`, () => {
|
||||
let customerId = testCase;
|
||||
@@ -34,29 +37,6 @@ describe(`${chalk.yellowBright(`${testCase}: Testing entities`)}`, () => {
|
||||
|
||||
let curUnix = new Date().getTime();
|
||||
|
||||
const entities = [
|
||||
{
|
||||
id: "1",
|
||||
name: "Entity 1",
|
||||
featureId: TestFeature.Users,
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
name: "Entity 1",
|
||||
featureId: TestFeature.Users,
|
||||
},
|
||||
{
|
||||
id: "3",
|
||||
name: "Entity 1",
|
||||
featureId: TestFeature.Users,
|
||||
},
|
||||
{
|
||||
id: "4",
|
||||
name: "Entity 1",
|
||||
featureId: TestFeature.Users,
|
||||
},
|
||||
];
|
||||
|
||||
before(async function () {
|
||||
await setupBefore(this);
|
||||
const { autumnJs } = this;
|
||||
@@ -92,6 +72,29 @@ describe(`${chalk.yellowBright(`${testCase}: Testing entities`)}`, () => {
|
||||
testClockId = testClockId1!;
|
||||
});
|
||||
|
||||
const entities = [
|
||||
{
|
||||
id: "1",
|
||||
name: "Entity 1",
|
||||
feature_id: TestFeature.Users,
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
name: "Entity 2",
|
||||
feature_id: TestFeature.Users,
|
||||
},
|
||||
{
|
||||
id: "3",
|
||||
name: "Entity 3",
|
||||
feature_id: TestFeature.Users,
|
||||
},
|
||||
{
|
||||
id: "4",
|
||||
name: "Entity 4",
|
||||
feature_id: TestFeature.Users,
|
||||
},
|
||||
];
|
||||
|
||||
it("should attach pro product", async function () {
|
||||
await runAttachTest({
|
||||
autumn,
|
||||
@@ -103,4 +106,44 @@ describe(`${chalk.yellowBright(`${testCase}: Testing entities`)}`, () => {
|
||||
env,
|
||||
});
|
||||
});
|
||||
it("should create more entities than the limit and hit error", async function () {
|
||||
await expectAutumnError({
|
||||
errCode: ErrCode.FeatureLimitReached,
|
||||
func: async () => {
|
||||
await autumn.entities.create(customerId, entities);
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it("should create entities one by one, then hit usage limit", async function () {
|
||||
await autumn.entities.create(customerId, entities[0]);
|
||||
await autumn.entities.create(customerId, entities[1]);
|
||||
|
||||
await expectAutumnError({
|
||||
errCode: ErrCode.FeatureLimitReached,
|
||||
func: async () => {
|
||||
await autumn.entities.create(customerId, entities[2]);
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it("should have correct check and get customer value", async function () {
|
||||
const check = await autumn.check({
|
||||
customer_id: customerId,
|
||||
feature_id: TestFeature.Users,
|
||||
});
|
||||
const customer = await autumn.customers.get(customerId);
|
||||
|
||||
console.log(check);
|
||||
console.log(customer);
|
||||
|
||||
expect(check.balance).to.equal(-2);
|
||||
// @ts-ignore
|
||||
expect(check.usage_limit).to.equal(userItem.usage_limit);
|
||||
|
||||
// @ts-ignore
|
||||
expect(customer.features[TestFeature.Users].usage_limit).to.equal(
|
||||
userItem.usage_limit,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
145
server/tests/advanced/usageLimit/usageLimit2.ts
Normal file
145
server/tests/advanced/usageLimit/usageLimit2.ts
Normal file
@@ -0,0 +1,145 @@
|
||||
import chalk from "chalk";
|
||||
import Stripe from "stripe";
|
||||
import { AutumnInt } from "@/external/autumn/autumnCli.js";
|
||||
import { initCustomer } from "@/utils/scriptUtils/initCustomer.js";
|
||||
import { APIVersion, AppEnv, ErrCode, Organization } from "@autumn/shared";
|
||||
|
||||
import { DrizzleCli } from "@/db/initDrizzle.js";
|
||||
import { setupBefore } from "tests/before.js";
|
||||
import { createProducts } from "tests/utils/productUtils.js";
|
||||
import { constructProduct } from "@/utils/scriptUtils/createTestProducts.js";
|
||||
import { constructArrearProratedItem } from "@/utils/scriptUtils/constructItem.js";
|
||||
import { TestFeature } from "tests/setup/v2Features.js";
|
||||
import { addPrefixToProducts, runAttachTest } from "tests/attach/utils.js";
|
||||
import { expectAutumnError } from "tests/utils/expectUtils/expectErrUtils.js";
|
||||
import { expect } from "chai";
|
||||
|
||||
const userItem = constructArrearProratedItem({
|
||||
featureId: TestFeature.Users,
|
||||
pricePerUnit: 50,
|
||||
includedUsage: 0,
|
||||
usageLimit: 2,
|
||||
});
|
||||
|
||||
export let pro = constructProduct({
|
||||
items: [userItem],
|
||||
type: "pro",
|
||||
});
|
||||
|
||||
const testCase = "entity1";
|
||||
|
||||
describe(`${chalk.yellowBright(`${testCase}: Testing entities`)}`, () => {
|
||||
let customerId = testCase;
|
||||
let autumn: AutumnInt = new AutumnInt({ version: APIVersion.v1_4 });
|
||||
let testClockId: string;
|
||||
let db: DrizzleCli, org: Organization, env: AppEnv;
|
||||
let stripeCli: Stripe;
|
||||
|
||||
let curUnix = new Date().getTime();
|
||||
|
||||
before(async function () {
|
||||
await setupBefore(this);
|
||||
const { autumnJs } = this;
|
||||
db = this.db;
|
||||
org = this.org;
|
||||
env = this.env;
|
||||
|
||||
stripeCli = this.stripeCli;
|
||||
|
||||
addPrefixToProducts({
|
||||
products: [pro],
|
||||
prefix: testCase,
|
||||
});
|
||||
|
||||
await createProducts({
|
||||
autumn,
|
||||
products: [pro],
|
||||
customerId,
|
||||
db,
|
||||
orgId: org.id,
|
||||
env,
|
||||
});
|
||||
|
||||
const { testClockId: testClockId1 } = await initCustomer({
|
||||
autumn: autumnJs,
|
||||
customerId,
|
||||
db,
|
||||
org,
|
||||
env,
|
||||
attachPm: "success",
|
||||
});
|
||||
|
||||
testClockId = testClockId1!;
|
||||
});
|
||||
|
||||
const entities = [
|
||||
{
|
||||
id: "1",
|
||||
name: "Entity 1",
|
||||
feature_id: TestFeature.Users,
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
name: "Entity 2",
|
||||
feature_id: TestFeature.Users,
|
||||
},
|
||||
{
|
||||
id: "3",
|
||||
name: "Entity 3",
|
||||
feature_id: TestFeature.Users,
|
||||
},
|
||||
{
|
||||
id: "4",
|
||||
name: "Entity 4",
|
||||
feature_id: TestFeature.Users,
|
||||
},
|
||||
];
|
||||
|
||||
it("should attach pro product", async function () {
|
||||
await runAttachTest({
|
||||
autumn,
|
||||
customerId,
|
||||
product: pro,
|
||||
stripeCli,
|
||||
db,
|
||||
org,
|
||||
env,
|
||||
});
|
||||
});
|
||||
it("should create more entities than the limit and hit error", async function () {
|
||||
await expectAutumnError({
|
||||
errCode: ErrCode.FeatureLimitReached,
|
||||
func: async () => {
|
||||
await autumn.entities.create(customerId, entities);
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it("should create entities one by one, then hit usage limit", async function () {
|
||||
await autumn.entities.create(customerId, entities[0]);
|
||||
await autumn.entities.create(customerId, entities[1]);
|
||||
|
||||
await expectAutumnError({
|
||||
errCode: ErrCode.FeatureLimitReached,
|
||||
func: async () => {
|
||||
await autumn.entities.create(customerId, entities[2]);
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it("should have correct check and get customer value", async function () {
|
||||
const check = await autumn.check({
|
||||
customer_id: customerId,
|
||||
feature_id: TestFeature.Users,
|
||||
});
|
||||
expect(check.balance).to.equal(-2);
|
||||
// @ts-ignore
|
||||
expect(check.usage_limit).to.equal(userItem.usage_limit);
|
||||
|
||||
const customer = await autumn.customers.get(customerId);
|
||||
// @ts-ignore
|
||||
expect(customer.features[TestFeature.Users].usage_limit).to.equal(
|
||||
userItem.usage_limit,
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -17,7 +17,6 @@ export const ErrCode = {
|
||||
|
||||
// General
|
||||
InvalidInputs: "invalid_inputs",
|
||||
LimitsReached: "limits_reached",
|
||||
InvalidRequest: "invalid_request",
|
||||
InvalidExpand: "invalid_expand",
|
||||
|
||||
@@ -30,6 +29,7 @@ export const ErrCode = {
|
||||
InvalidFeature: "invalid_feature",
|
||||
DuplicateFeatureId: "duplicate_feature_id",
|
||||
InvalidEventName: "invalid_event_name",
|
||||
FeatureLimitReached: "feature_limit_reached",
|
||||
|
||||
// Internal
|
||||
InternalError: "internal_error",
|
||||
|
||||
@@ -119,7 +119,7 @@ export const SignIn = () => {
|
||||
Continue with Google
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
{/* <Button
|
||||
variant="auth"
|
||||
onClick={handleGoogleSignIn}
|
||||
isLoading={googleLoading}
|
||||
@@ -129,7 +129,7 @@ export const SignIn = () => {
|
||||
className={height}
|
||||
>
|
||||
Continue with Stripe
|
||||
</Button>
|
||||
</Button> */}
|
||||
|
||||
{/* Divider */}
|
||||
<div className="relative">
|
||||
|
||||
Reference in New Issue
Block a user