Handle feature lifecycle for multiple orgs

This commit is contained in:
Owen
2026-02-17 21:00:48 -08:00
parent 057f82a561
commit 2b0d6de986

View File

@@ -15,7 +15,18 @@ import { SubscriptionType } from "./hooks/getSubType";
import { TierFeature, tierMatrix } from "@server/lib/billing/tierMatrix"; import { TierFeature, tierMatrix } from "@server/lib/billing/tierMatrix";
import { Tier } from "@server/types/Tiers"; import { Tier } from "@server/types/Tiers";
import logger from "@server/logger"; import logger from "@server/logger";
import { db, idp, idpOrg, loginPage, loginPageBranding, loginPageBrandingOrg, loginPageOrg, orgs, resources, roles } from "@server/db"; import {
db,
idp,
idpOrg,
loginPage,
loginPageBranding,
loginPageBrandingOrg,
loginPageOrg,
orgs,
resources,
roles
} from "@server/db";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";
/** /**
@@ -59,10 +70,7 @@ async function capRetentionDays(
} }
// Get current org settings // Get current org settings
const [org] = await db const [org] = await db.select().from(orgs).where(eq(orgs.orgId, orgId));
.select()
.from(orgs)
.where(eq(orgs.orgId, orgId));
if (!org) { if (!org) {
logger.warn(`Org ${orgId} not found when capping retention days`); logger.warn(`Org ${orgId} not found when capping retention days`);
@@ -110,18 +118,13 @@ async function capRetentionDays(
// Apply updates if needed // Apply updates if needed
if (needsUpdate) { if (needsUpdate) {
await db await db.update(orgs).set(updates).where(eq(orgs.orgId, orgId));
.update(orgs)
.set(updates)
.where(eq(orgs.orgId, orgId));
logger.info( logger.info(
`Successfully capped retention days for org ${orgId} to max ${maxRetentionDays} days` `Successfully capped retention days for org ${orgId} to max ${maxRetentionDays} days`
); );
} else { } else {
logger.debug( logger.debug(`No retention day capping needed for org ${orgId}`);
`No retention day capping needed for org ${orgId}`
);
} }
} }
@@ -134,6 +137,35 @@ export async function handleTierChange(
`Handling tier change for org ${orgId}: ${previousTier || "none"} -> ${newTier || "free"}` `Handling tier change for org ${orgId}: ${previousTier || "none"} -> ${newTier || "free"}`
); );
// Get all orgs that have this orgId as their billingOrgId
const associatedOrgs = await db
.select()
.from(orgs)
.where(eq(orgs.billingOrgId, orgId));
logger.info(
`Found ${associatedOrgs.length} org(s) associated with billing org ${orgId}`
);
// Loop over all associated orgs and apply tier changes
for (const org of associatedOrgs) {
await handleTierChangeForOrg(org.orgId, newTier, previousTier);
}
logger.info(
`Completed tier change handling for all orgs associated with billing org ${orgId}`
);
}
async function handleTierChangeForOrg(
orgId: string,
newTier: SubscriptionType | null,
previousTier?: SubscriptionType | null
): Promise<void> {
logger.info(
`Handling tier change for org ${orgId}: ${previousTier || "none"} -> ${newTier || "free"}`
);
// License subscriptions are handled separately and don't use the tier matrix // License subscriptions are handled separately and don't use the tier matrix
if (newTier === "license") { if (newTier === "license") {
logger.debug( logger.debug(
@@ -314,9 +346,7 @@ async function disableLoginPageDomain(orgId: string): Promise<void> {
); );
if (existingLoginPage) { if (existingLoginPage) {
await db await db.delete(loginPageOrg).where(eq(loginPageOrg.orgId, orgId));
.delete(loginPageOrg)
.where(eq(loginPageOrg.orgId, orgId));
await db await db
.delete(loginPage) .delete(loginPage)