mirror of
https://github.com/formbricks/formbricks.git
synced 2026-02-21 18:18:48 -06:00
feat: updated org limits data migration (#4329)
This commit is contained in:
@@ -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();
|
||||
@@ -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",
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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(),
|
||||
|
||||
Reference in New Issue
Block a user