163 lines
4.7 KiB
TypeScript
163 lines
4.7 KiB
TypeScript
// 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 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 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,
|
|
// });
|
|
|
|
// 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`;
|
|
|
|
// 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,
|
|
// // });
|
|
// // }
|
|
|
|
// 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 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 (!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,
|
|
// });
|
|
// }
|
|
|
|
// // 1. Create migration JOB
|
|
// const migrationJob = constructMigrationJob({
|
|
// fromProduct,
|
|
// toProduct,
|
|
// });
|
|
|
|
// 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,
|
|
// });
|
|
// }
|
|
|
|
// await addTaskToQueue({
|
|
// jobName: JobName.Migration,
|
|
// payload: {
|
|
// migrationJobId: migrationJob.id,
|
|
// },
|
|
// });
|
|
|
|
// 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);
|
|
// },
|
|
// });
|
|
// });
|