91 lines
2.8 KiB
TypeScript
91 lines
2.8 KiB
TypeScript
import { DateFormatter } from "@internationalized/date";
|
|
import type { PrismaClient } from "@trigger.dev/database";
|
|
import { prisma } from "~/db.server";
|
|
import { featuresForRequest } from "~/features.server";
|
|
import { DeleteProjectService } from "./deleteProject.server";
|
|
import { getCurrentPlan } from "./platform.v3.server";
|
|
import { controlPlaneResolver } from "~/v3/runOpsMigration/controlPlaneResolver.server";
|
|
|
|
export class DeleteOrganizationService {
|
|
#prismaClient: PrismaClient;
|
|
|
|
constructor(prismaClient: PrismaClient = prisma) {
|
|
this.#prismaClient = prismaClient;
|
|
}
|
|
|
|
public async call({
|
|
organizationSlug,
|
|
userId,
|
|
request,
|
|
}: {
|
|
organizationSlug: string;
|
|
userId: string;
|
|
request: Request;
|
|
}) {
|
|
const organization = await this.#prismaClient.organization.findFirst({
|
|
include: {
|
|
projects: true,
|
|
members: true,
|
|
},
|
|
where: {
|
|
slug: organizationSlug,
|
|
members: { some: { userId: userId } },
|
|
},
|
|
});
|
|
|
|
if (!organization) {
|
|
throw new Error("Organization not found");
|
|
}
|
|
|
|
if (organization.deletedAt) {
|
|
throw new Error("Organization already deleted");
|
|
}
|
|
|
|
//Check if they have an active subscription
|
|
const { isManagedCloud } = featuresForRequest(request);
|
|
const currentPlan = isManagedCloud ? await getCurrentPlan(organization.id) : undefined;
|
|
|
|
if (currentPlan && currentPlan.v3Subscription && currentPlan.v3Subscription.isPaying) {
|
|
//they've cancelled and that date hasn't passed yet
|
|
if (
|
|
currentPlan.v3Subscription.canceledAt &&
|
|
new Date(currentPlan.v3Subscription.canceledAt) > new Date()
|
|
) {
|
|
//a dateformatter that produces results like "Jan 1 2024"
|
|
const dateFormatter = new DateFormatter("en-us", {
|
|
year: "numeric",
|
|
month: "short",
|
|
day: "numeric",
|
|
});
|
|
throw new Error(
|
|
`This Organization has a canceled subscription. You can delete it when the cancelation date (${dateFormatter.format(
|
|
new Date(currentPlan.v3Subscription.canceledAt)
|
|
)}) is in the past.`
|
|
);
|
|
}
|
|
|
|
throw new Error("You can't delete an Organization that has an active subscription");
|
|
}
|
|
|
|
// loop through the projects and delete them
|
|
const projectDeleteService = new DeleteProjectService();
|
|
for (const project of organization.projects) {
|
|
await projectDeleteService.call({ projectId: project.id, userId });
|
|
}
|
|
|
|
//mark the organization as deleted
|
|
await this.#prismaClient.organization.update({
|
|
where: {
|
|
id: organization.id,
|
|
},
|
|
data: {
|
|
runsEnabled: false,
|
|
deletedAt: new Date(),
|
|
},
|
|
});
|
|
|
|
// runsEnabled + the org's projects (project.deletedAt) changed; drop all cached env rows.
|
|
controlPlaneResolver.invalidateOrganization(organization.id);
|
|
}
|
|
}
|