feat: updated org limits data migration (#4329)

This commit is contained in:
Piyush Gupta
2024-11-19 15:40:26 +05:30
committed by GitHub
parent 36cf16ce90
commit 97377fe8bd
4 changed files with 189 additions and 5 deletions

View File

@@ -0,0 +1,183 @@
/* eslint-disable no-console -- logging is allowed in migration scripts */
import { PrismaClient } from "@prisma/client";
const prisma = new PrismaClient();
const TRANSACTION_TIMEOUT = 3 * 60 * 1000; // 3 minutes in milliseconds
type Plan = "free" | "startup" | "scale";
interface TOrganization {
id: string;
billing: {
plan: Plan;
limits: {
monthly: {
responses: number;
miu: number;
};
};
};
}
export const BILLING_LIMITS = {
free: {
RESPONSES: 1500,
MIU: 2000,
},
startup: {
RESPONSES: 5000,
MIU: 7500,
},
scale: {
RESPONSES: 10000,
MIU: 30000,
},
} as const;
async function runMigration(): Promise<void> {
const startTime = Date.now();
console.log("Starting data migration...");
await prisma.$transaction(
async (transactionPrisma) => {
const organizations = (await transactionPrisma.organization.findMany({
where: {
OR: [
{
AND: [
{
billing: {
path: ["plan"],
equals: "free",
},
},
{
billing: {
path: ["limits", "monthly", "miu"],
not: 2000,
},
},
{
billing: {
path: ["limits", "monthly", "responses"],
not: 1500,
},
},
],
},
{
AND: [
{
billing: {
path: ["plan"],
equals: "startup",
},
},
{
billing: {
path: ["limits", "monthly", "miu"],
not: 7500,
},
},
{
billing: {
path: ["limits", "monthly", "responses"],
not: 5000,
},
},
],
},
{
AND: [
{
billing: {
path: ["plan"],
equals: "scale",
},
},
{
billing: {
path: ["limits", "monthly", "miu"],
not: 30000,
},
},
{
billing: {
path: ["limits", "monthly", "responses"],
not: 10000,
},
},
],
},
],
},
select: {
id: true,
billing: true,
},
})) as TOrganization[];
const updationPromises = [];
for (const organization of organizations) {
const plan = organization.billing.plan;
const limits = BILLING_LIMITS[plan];
let billing = organization.billing;
billing = {
...billing,
limits: {
...billing.limits,
monthly: {
...billing.limits.monthly,
responses: limits.RESPONSES,
miu: limits.MIU,
},
},
};
const updatePromise = transactionPrisma.organization.update({
where: {
id: organization.id,
},
data: {
billing,
},
});
updationPromises.push(updatePromise);
}
await Promise.all(updationPromises);
console.log(`Updated ${organizations.length.toString()} organizations`);
},
{
timeout: TRANSACTION_TIMEOUT,
}
);
const endTime = Date.now();
console.log(`Data migration completed. Total time: ${((endTime - startTime) / 1000).toFixed(2)}s`);
}
function handleError(error: unknown): void {
console.error("An error occurred during migration:", error);
process.exit(1);
}
function handleDisconnectError(): void {
console.error("Failed to disconnect Prisma client");
process.exit(1);
}
function main(): void {
runMigration()
.catch(handleError)
.finally(() => {
prisma.$disconnect().catch(handleDisconnectError);
});
}
main();

View File

@@ -55,7 +55,8 @@
"data-migration:migrate-survey-types": "ts-node ./data-migrations/20241002123456_migrate_survey_types/data-migration.ts",
"data-migration:v2.6": "pnpm data-migration:add-display-id-to-response && pnpm data-migration:address-question && pnpm data-migration:advanced-logic && pnpm data-migration:segments-actions-cleanup && pnpm data-migration:migrate-survey-types",
"data-migration:add-teams": "ts-node ./data-migrations/20241107161932_add_teams/data-migration.ts",
"data-migration:v2.7": "pnpm data-migration:add-teams"
"data-migration:v2.7": "pnpm data-migration:add-teams",
"data-migration:update-org-limits": "ts-node ./data-migrations/20241118123456_update_org_limits/data-migration.ts"
},
"dependencies": {
"@prisma/client": "5.20.0",

View File

@@ -460,8 +460,8 @@ model Organization {
name String
memberships Membership[]
products Product[]
/// @zod.custom(imports.ZTeamBilling)
/// [TeamBilling]
/// @zod.custom(imports.ZOrganizationBilling)
/// [OrganizationBilling]
billing Json
invites Invite[]
isAIEnabled Boolean @default(false)

View File

@@ -22,8 +22,8 @@ export const ZOrganizationBilling = z.object({
period: ZOrganizationBillingPeriod.default("monthly"),
limits: ZOrganizationBillingPlanLimits.default({
monthly: {
responses: 500,
miu: 1000,
responses: 1500,
miu: 2000,
},
}),
periodStart: z.date(),