chore: ran tests
This commit is contained in:
@@ -10,14 +10,14 @@ fi
|
||||
|
||||
$MOCHA_CMD \
|
||||
'tests/attach/migrations/*.ts' \
|
||||
'tests/attach/newVersion/*.ts' \
|
||||
'tests/attach/upgradeOld/*.ts' \
|
||||
'tests/attach/others/*.ts' \
|
||||
'tests/attach/updateEnts/*.ts' \
|
||||
'tests/advanced/check/*.ts' \
|
||||
'tests/attach/others/*.ts'
|
||||
# 'tests/attach/entities/*.ts' \
|
||||
# 'tests/attach/newVersion/*.ts' \
|
||||
# 'tests/attach/upgradeOld/*.ts' \
|
||||
# 'tests/attach/others/*.ts' \
|
||||
# 'tests/attach/updateEnts/*.ts' \
|
||||
# 'tests/advanced/check/*.ts' \
|
||||
# 'tests/attach/others/*.ts'
|
||||
# # 'tests/attach/entities/*.ts' \
|
||||
|
||||
$MOCHA_CMD 'tests/attach/prepaid/*.ts' \
|
||||
'tests/interval/upgrade/*.ts' \
|
||||
'tests/interval/multiSub/*.ts'
|
||||
# $MOCHA_CMD 'tests/attach/prepaid/*.ts' \
|
||||
# 'tests/interval/upgrade/*.ts' \
|
||||
# 'tests/interval/multiSub/*.ts'
|
||||
|
||||
@@ -36,14 +36,14 @@ import { checkCusSubCorrect } from "./utils/checkUtils/checkCustomerCorrect.js";
|
||||
|
||||
const { db } = initDrizzle({ maxConnections: 5 });
|
||||
|
||||
const orgSlugs = process.env.ORG_SLUGS!.split(",");
|
||||
let orgSlugs = process.env.ORG_SLUGS!.split(",");
|
||||
const skipEmails = process.env.SKIP_EMAILS!.split(",");
|
||||
const skipIds = [
|
||||
"cus_2tXCCwC6iyiftgA6ndSo1Ubb2dx",
|
||||
"DxG668K7uDd0Vahk54YWjvCGVgf2",
|
||||
];
|
||||
|
||||
// orgSlugs = ["welcome-back-1747670264"];
|
||||
orgSlugs = ["nithiiyan_skhanthan_52620936"];
|
||||
// let customerId = null;
|
||||
const customerId = null;
|
||||
|
||||
|
||||
@@ -20,7 +20,10 @@ import { handleOAuthCallback } from "./internal/orgs/handlers/stripeHandlers/han
|
||||
import { honoOrgRouter } from "./internal/orgs/orgRouter.js";
|
||||
import { platformBetaRouter } from "./internal/platform/platformBeta/platformBetaRouter.js";
|
||||
import { internalProductRouter } from "./internal/products/internalProductRouter.js";
|
||||
import { honoProductRouter } from "./internal/products/productRouter.js";
|
||||
import {
|
||||
honoProductRouter,
|
||||
migrationRouter,
|
||||
} from "./internal/products/productRouter.js";
|
||||
import { auth } from "./utils/auth.js";
|
||||
|
||||
const ALLOWED_ORIGINS = [
|
||||
@@ -92,6 +95,7 @@ export const createHonoApp = () => {
|
||||
app.use("/v1/*", queryMiddleware());
|
||||
|
||||
// API Routes
|
||||
app.route("v1", migrationRouter);
|
||||
app.post("/v1/entitled", ...handleCheck);
|
||||
app.post("/v1/check", ...handleCheck);
|
||||
app.route("v1/customers", cusRouter);
|
||||
|
||||
@@ -12,13 +12,11 @@ import { expressCusRouter } from "../customers/cusRouter.js";
|
||||
import { handleCreateBillingPortal } from "../customers/handlers/handleCreateBillingPortal.js";
|
||||
import { featureRouter } from "../features/featureRouter.js";
|
||||
import { internalFeatureRouter } from "../features/internalFeatureRouter.js";
|
||||
import { migrationRouter } from "../migrations/migrationRouter.js";
|
||||
import { handleGetOrg } from "../orgs/handlers/handleGetOrg.js";
|
||||
import { platformRouter } from "../platform/platformLegacy/platformRouter.js";
|
||||
import { productBetaRouter, productRouter } from "../products/productRouter.js";
|
||||
import { componentRouter } from "./components/componentRouter.js";
|
||||
import { entityRouter } from "./entities/entityRouter.js";
|
||||
// import { checkRouter } from "./entitled/checkRouter.js";
|
||||
import { eventsRouter } from "./events/eventRouter.js";
|
||||
import { usageRouter } from "./events/usageRouter.js";
|
||||
import { invoiceRouter } from "./invoiceRouter.js";
|
||||
@@ -45,7 +43,6 @@ apiRouter.use("/internal_features", internalFeatureRouter);
|
||||
|
||||
apiRouter.use("/usage", usageRouter);
|
||||
apiRouter.use("/entities", entityRouter);
|
||||
apiRouter.use("/migrations", migrationRouter);
|
||||
|
||||
// REWARDS
|
||||
apiRouter.use("/reward_programs", rewardProgramRouter);
|
||||
@@ -56,9 +53,6 @@ apiRouter.use("/redemptions", redemptionRouter);
|
||||
apiRouter.use("", attachRouter);
|
||||
apiRouter.use("/cancel", cancelRouter);
|
||||
|
||||
// apiRouter.use("/entitled", checkRouter);
|
||||
// apiRouter.use("/check", checkRouter);
|
||||
|
||||
apiRouter.use("/events", eventsRouter);
|
||||
apiRouter.use("/track", eventsRouter);
|
||||
apiRouter.post("/setup_payment", handleSetupPayment);
|
||||
|
||||
@@ -1,162 +1,162 @@
|
||||
import {
|
||||
BillingType,
|
||||
ErrCode,
|
||||
ProductNotFoundError,
|
||||
type UsagePriceConfig,
|
||||
} from "@autumn/shared";
|
||||
import express, { type Router } from "express";
|
||||
import { MigrationService } from "@/internal/migrations/MigrationService.js";
|
||||
import { constructMigrationJob } from "@/internal/migrations/migrationUtils.js";
|
||||
import { ProductService } from "@/internal/products/ProductService.js";
|
||||
import {
|
||||
getBillingType,
|
||||
pricesOnlyOneOff,
|
||||
} from "@/internal/products/prices/priceUtils.js";
|
||||
import { isFreeProduct } from "@/internal/products/productUtils.js";
|
||||
import { JobName } from "@/queue/JobName.js";
|
||||
import { addTaskToQueue } from "@/queue/queueUtils.js";
|
||||
import RecaseError from "@/utils/errorUtils.js";
|
||||
import type {
|
||||
ExtendedRequest,
|
||||
ExtendedResponse,
|
||||
} from "@/utils/models/Request.js";
|
||||
import { routeHandler } from "@/utils/routerUtils.js";
|
||||
import { findPrepaidPrice } from "../products/prices/priceUtils/findPriceUtils.js";
|
||||
// import {
|
||||
// BillingType,
|
||||
// ErrCode,
|
||||
// ProductNotFoundError,
|
||||
// type UsagePriceConfig,
|
||||
// } from "@autumn/shared";
|
||||
// import express, { type Router } from "express";
|
||||
// import { MigrationService } from "@/internal/migrations/MigrationService.js";
|
||||
// import { constructMigrationJob } from "@/internal/migrations/migrationUtils.js";
|
||||
// import { ProductService } from "@/internal/products/ProductService.js";
|
||||
// import {
|
||||
// getBillingType,
|
||||
// pricesOnlyOneOff,
|
||||
// } from "@/internal/products/prices/priceUtils.js";
|
||||
// import { isFreeProduct } from "@/internal/products/productUtils.js";
|
||||
// import { JobName } from "@/queue/JobName.js";
|
||||
// import { addTaskToQueue } from "@/queue/queueUtils.js";
|
||||
// import RecaseError from "@/utils/errorUtils.js";
|
||||
// import type {
|
||||
// ExtendedRequest,
|
||||
// ExtendedResponse,
|
||||
// } from "@/utils/models/Request.js";
|
||||
// import { routeHandler } from "@/utils/routerUtils.js";
|
||||
// import { findPrepaidPrice } from "../products/prices/priceUtils/findPriceUtils.js";
|
||||
|
||||
export const migrationRouter: Router = express.Router();
|
||||
// export const migrationRouter: Router = express.Router();
|
||||
|
||||
export const handleMigrate = async (
|
||||
req: ExtendedRequest,
|
||||
res?: ExtendedResponse,
|
||||
) => {
|
||||
const { orgId, env, db, features } = req;
|
||||
// export const handleMigrate = async (
|
||||
// req: ExtendedRequest,
|
||||
// res?: ExtendedResponse,
|
||||
// ) => {
|
||||
// const { orgId, env, db, features } = req;
|
||||
|
||||
const { from_product_id, from_version, to_product_id, to_version } = req.body;
|
||||
// const { from_product_id, from_version, to_product_id, to_version } = req.body;
|
||||
|
||||
const fromProduct = await ProductService.getFull({
|
||||
db,
|
||||
env,
|
||||
orgId,
|
||||
idOrInternalId: from_product_id,
|
||||
version: from_version,
|
||||
});
|
||||
// const fromProduct = await ProductService.getFull({
|
||||
// db,
|
||||
// env,
|
||||
// orgId,
|
||||
// idOrInternalId: from_product_id,
|
||||
// version: from_version,
|
||||
// });
|
||||
|
||||
const toProduct = await ProductService.getFull({
|
||||
db,
|
||||
env,
|
||||
orgId,
|
||||
idOrInternalId: to_product_id,
|
||||
version: to_version,
|
||||
});
|
||||
// const toProduct = await ProductService.getFull({
|
||||
// db,
|
||||
// env,
|
||||
// orgId,
|
||||
// idOrInternalId: to_product_id,
|
||||
// version: to_version,
|
||||
// });
|
||||
|
||||
if (isFreeProduct(fromProduct.prices) && !isFreeProduct(toProduct.prices)) {
|
||||
throw new RecaseError({
|
||||
message: `Cannot migrate customers from free product to paid product`,
|
||||
code: ErrCode.InvalidRequest,
|
||||
statusCode: 400,
|
||||
});
|
||||
}
|
||||
// if (isFreeProduct(fromProduct.prices) && !isFreeProduct(toProduct.prices)) {
|
||||
// throw new RecaseError({
|
||||
// message: `Cannot migrate customers from free product to paid product`,
|
||||
// code: ErrCode.InvalidRequest,
|
||||
// statusCode: 400,
|
||||
// });
|
||||
// }
|
||||
|
||||
// Check if from product is one off, or to product is one off
|
||||
if (
|
||||
pricesOnlyOneOff(fromProduct.prices) ||
|
||||
pricesOnlyOneOff(toProduct.prices)
|
||||
) {
|
||||
const fromIsOneOff = pricesOnlyOneOff(fromProduct.prices);
|
||||
const msg = fromIsOneOff
|
||||
? `${fromProduct.name} is a one off product, cannot migrate customers on it`
|
||||
: `${toProduct.name} is a one off product, cannot migrate customers to this product`;
|
||||
// // Check if from product is one off, or to product is one off
|
||||
// if (
|
||||
// pricesOnlyOneOff(fromProduct.prices) ||
|
||||
// pricesOnlyOneOff(toProduct.prices)
|
||||
// ) {
|
||||
// const fromIsOneOff = pricesOnlyOneOff(fromProduct.prices);
|
||||
// const msg = fromIsOneOff
|
||||
// ? `${fromProduct.name} is a one off product, cannot migrate customers on it`
|
||||
// : `${toProduct.name} is a one off product, cannot migrate customers to this product`;
|
||||
|
||||
throw new RecaseError({
|
||||
message: msg,
|
||||
code: ErrCode.InvalidRequest,
|
||||
statusCode: 400,
|
||||
});
|
||||
}
|
||||
// throw new RecaseError({
|
||||
// message: msg,
|
||||
// code: ErrCode.InvalidRequest,
|
||||
// statusCode: 400,
|
||||
// });
|
||||
// }
|
||||
|
||||
// if (fromProduct.is_add_on || toProduct.is_add_on) {
|
||||
// throw new RecaseError({
|
||||
// message: `Cannot migrate customers for add on products`,
|
||||
// code: ErrCode.InvalidRequest,
|
||||
// statusCode: 400,
|
||||
// });
|
||||
// }
|
||||
// // if (fromProduct.is_add_on || toProduct.is_add_on) {
|
||||
// // throw new RecaseError({
|
||||
// // message: `Cannot migrate customers for add on products`,
|
||||
// // code: ErrCode.InvalidRequest,
|
||||
// // statusCode: 400,
|
||||
// // });
|
||||
// // }
|
||||
|
||||
for (const price of toProduct.prices) {
|
||||
const billingType = getBillingType(price.config);
|
||||
if (billingType !== BillingType.UsageInAdvance) continue;
|
||||
// for (const price of toProduct.prices) {
|
||||
// const billingType = getBillingType(price.config);
|
||||
// if (billingType !== BillingType.UsageInAdvance) continue;
|
||||
|
||||
const config = price.config as UsagePriceConfig;
|
||||
const internalFeatureId = config.internal_feature_id;
|
||||
const feature = features.find((f) => f.internal_id === internalFeatureId);
|
||||
// const config = price.config as UsagePriceConfig;
|
||||
// const internalFeatureId = config.internal_feature_id;
|
||||
// const feature = features.find((f) => f.internal_id === internalFeatureId);
|
||||
|
||||
const prepaidPrice = findPrepaidPrice({
|
||||
prices: fromProduct.prices,
|
||||
internalFeatureId,
|
||||
});
|
||||
// const prepaidPrice = findPrepaidPrice({
|
||||
// prices: fromProduct.prices,
|
||||
// internalFeatureId,
|
||||
// });
|
||||
|
||||
if (!prepaidPrice) {
|
||||
throw new RecaseError({
|
||||
message: `New product has prepaid price for feature ${feature?.name}, but old product does not, can't perform migration`,
|
||||
code: ErrCode.InvalidRequest,
|
||||
statusCode: 400,
|
||||
});
|
||||
}
|
||||
}
|
||||
// if (!prepaidPrice) {
|
||||
// throw new RecaseError({
|
||||
// message: `New product has prepaid price for feature ${feature?.name}, but old product does not, can't perform migration`,
|
||||
// code: ErrCode.InvalidRequest,
|
||||
// statusCode: 400,
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
|
||||
if (!isFreeProduct(fromProduct.prices) && isFreeProduct(toProduct.prices)) {
|
||||
throw new RecaseError({
|
||||
message: `Cannot migrate customers from paid product to free product`,
|
||||
code: ErrCode.InvalidRequest,
|
||||
statusCode: 400,
|
||||
});
|
||||
}
|
||||
// if (!isFreeProduct(fromProduct.prices) && isFreeProduct(toProduct.prices)) {
|
||||
// throw new RecaseError({
|
||||
// message: `Cannot migrate customers from paid product to free product`,
|
||||
// code: ErrCode.InvalidRequest,
|
||||
// statusCode: 400,
|
||||
// });
|
||||
// }
|
||||
|
||||
if (isFreeProduct(fromProduct.prices) && !isFreeProduct(toProduct.prices)) {
|
||||
throw new RecaseError({
|
||||
message: `Cannot migrate customers from free product to paid product`,
|
||||
code: ErrCode.InvalidRequest,
|
||||
statusCode: 400,
|
||||
});
|
||||
}
|
||||
// if (isFreeProduct(fromProduct.prices) && !isFreeProduct(toProduct.prices)) {
|
||||
// throw new RecaseError({
|
||||
// message: `Cannot migrate customers from free product to paid product`,
|
||||
// code: ErrCode.InvalidRequest,
|
||||
// statusCode: 400,
|
||||
// });
|
||||
// }
|
||||
|
||||
// 1. Create migration JOB
|
||||
const migrationJob = constructMigrationJob({
|
||||
fromProduct,
|
||||
toProduct,
|
||||
});
|
||||
// // 1. Create migration JOB
|
||||
// const migrationJob = constructMigrationJob({
|
||||
// fromProduct,
|
||||
// toProduct,
|
||||
// });
|
||||
|
||||
await MigrationService.createJob({
|
||||
db,
|
||||
data: migrationJob,
|
||||
});
|
||||
// await MigrationService.createJob({
|
||||
// db,
|
||||
// data: migrationJob,
|
||||
// });
|
||||
|
||||
if (!fromProduct || !toProduct) {
|
||||
throw new ProductNotFoundError({
|
||||
productId: !fromProduct ? from_product_id : to_product_id,
|
||||
version: !fromProduct ? from_version : to_version,
|
||||
});
|
||||
}
|
||||
// if (!fromProduct || !toProduct) {
|
||||
// throw new ProductNotFoundError({
|
||||
// productId: !fromProduct ? from_product_id : to_product_id,
|
||||
// version: !fromProduct ? from_version : to_version,
|
||||
// });
|
||||
// }
|
||||
|
||||
await addTaskToQueue({
|
||||
jobName: JobName.Migration,
|
||||
payload: {
|
||||
migrationJobId: migrationJob.id,
|
||||
},
|
||||
});
|
||||
// await addTaskToQueue({
|
||||
// jobName: JobName.Migration,
|
||||
// payload: {
|
||||
// migrationJobId: migrationJob.id,
|
||||
// },
|
||||
// });
|
||||
|
||||
if (res) {
|
||||
res.status(200).json(migrationJob);
|
||||
}
|
||||
};
|
||||
// if (res) {
|
||||
// res.status(200).json(migrationJob);
|
||||
// }
|
||||
// };
|
||||
|
||||
migrationRouter.post("", async (req: any, res: any) => {
|
||||
return routeHandler({
|
||||
req,
|
||||
res,
|
||||
action: "migrate",
|
||||
handler: async (req: ExtendedRequest, res: ExtendedResponse) => {
|
||||
await handleMigrate(req, res);
|
||||
},
|
||||
});
|
||||
});
|
||||
// migrationRouter.post("", async (req: any, res: any) => {
|
||||
// return routeHandler({
|
||||
// req,
|
||||
// res,
|
||||
// action: "migrate",
|
||||
// handler: async (req: ExtendedRequest, res: ExtendedResponse) => {
|
||||
// await handleMigrate(req, res);
|
||||
// },
|
||||
// });
|
||||
// });
|
||||
|
||||
@@ -150,8 +150,9 @@ import { handleUpdateProductV2 } from "./handlers/handleUpdateProduct/handleUpda
|
||||
|
||||
// Create a Hono app for products
|
||||
export const honoProductRouter = new Hono<HonoEnv>();
|
||||
export const migrationRouter = new Hono<HonoEnv>();
|
||||
|
||||
honoProductRouter.post("", ...createProduct);
|
||||
honoProductRouter.post("/:productId", ...handleUpdateProductV2);
|
||||
honoProductRouter.post("/:productId/copy", ...handleCopyProductV2);
|
||||
honoProductRouter.post("/migrate", ...handleMigrateProductV2);
|
||||
migrationRouter.post("migrations", ...handleMigrateProductV2);
|
||||
|
||||
@@ -21,9 +21,25 @@ import { initCustomerV3 } from "@/utils/scriptUtils/testUtils/initCustomerV3.js"
|
||||
import { initProductsV0 } from "@/utils/scriptUtils/testUtils/initProductsV0.js";
|
||||
|
||||
// UNCOMMENT FROM HERE
|
||||
const addOn = constructProduct({
|
||||
const pro = constructProduct({
|
||||
type: "pro",
|
||||
isAddOn: true,
|
||||
|
||||
items: [
|
||||
// constructFeatureItem({ featureId: TestFeature.Words, includedUsage: 100 }),
|
||||
constructArrearProratedItem({
|
||||
featureId: TestFeature.Users,
|
||||
includedUsage: 1,
|
||||
pricePerUnit: 10,
|
||||
config: {
|
||||
on_increase: OnIncrease.BillImmediately,
|
||||
on_decrease: OnDecrease.Prorate,
|
||||
},
|
||||
}),
|
||||
],
|
||||
});
|
||||
const premium = constructProduct({
|
||||
type: "premium",
|
||||
|
||||
items: [
|
||||
// constructFeatureItem({ featureId: TestFeature.Words, includedUsage: 100 }),
|
||||
constructArrearProratedItem({
|
||||
@@ -38,8 +54,8 @@ const addOn = constructProduct({
|
||||
],
|
||||
});
|
||||
|
||||
describe(`${chalk.yellowBright("temp1: Testing add ons")}`, () => {
|
||||
const customerId = "temp1";
|
||||
describe(`${chalk.yellowBright("temp: Testing add ons")}`, () => {
|
||||
const customerId = "temp";
|
||||
const autumn: AutumnInt = new AutumnInt({ version: LegacyVersion.v1_4 });
|
||||
|
||||
let stripeCli: Stripe;
|
||||
@@ -65,7 +81,7 @@ describe(`${chalk.yellowBright("temp1: Testing add ons")}`, () => {
|
||||
|
||||
await initProductsV0({
|
||||
ctx,
|
||||
products: [addOn],
|
||||
products: [pro, premium],
|
||||
prefix: customerId,
|
||||
});
|
||||
|
||||
@@ -75,31 +91,8 @@ describe(`${chalk.yellowBright("temp1: Testing add ons")}`, () => {
|
||||
test("should attach pro product", async () => {
|
||||
await autumn.attach({
|
||||
customer_id: customerId,
|
||||
product_id: addOn.id,
|
||||
product_id: pro.id,
|
||||
});
|
||||
|
||||
await autumn.entities.create(customerId, [
|
||||
{
|
||||
id: "1",
|
||||
name: "Entity 1",
|
||||
feature_id: TestFeature.Users,
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
name: "Entity 2",
|
||||
feature_id: TestFeature.Users,
|
||||
},
|
||||
]);
|
||||
|
||||
await autumn.entities.delete(customerId, "1");
|
||||
// await autumn.attach({
|
||||
// customer_id: customerId,
|
||||
// product_id: addOn.id,
|
||||
// });
|
||||
// await autumn.attach({
|
||||
// customer_id: customerId,
|
||||
// product_id: addOn.id,
|
||||
// });
|
||||
});
|
||||
|
||||
// test("should cancel one add on", async () => {
|
||||
|
||||
Reference in New Issue
Block a user