mirror of
https://github.com/fosrl/pangolin.git
synced 2026-05-17 06:24:32 +00:00
Handle trial limit lifecycle
This commit is contained in:
@@ -16,6 +16,7 @@ import { customers, db, subscriptions } from "@server/db";
|
|||||||
import { eq } from "drizzle-orm";
|
import { eq } from "drizzle-orm";
|
||||||
import logger from "@server/logger";
|
import logger from "@server/logger";
|
||||||
import { generateId } from "@server/auth/sessions/app";
|
import { generateId } from "@server/auth/sessions/app";
|
||||||
|
import { handleSubscriptionLifesycle } from "../subscriptionLifecycle";
|
||||||
|
|
||||||
export async function handleCustomerCreated(
|
export async function handleCustomerCreated(
|
||||||
customer: Stripe.Customer
|
customer: Stripe.Customer
|
||||||
@@ -62,6 +63,13 @@ export async function handleCustomerCreated(
|
|||||||
expiresAt: trialExpiresAt,
|
expiresAt: trialExpiresAt,
|
||||||
trial: true
|
trial: true
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// update to the business limits for the trial
|
||||||
|
await handleSubscriptionLifesycle(
|
||||||
|
customer.metadata.orgId,
|
||||||
|
"active",
|
||||||
|
"tier3"
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
logger.info(`Customer with ID ${customer.id} created successfully.`);
|
logger.info(`Customer with ID ${customer.id} created successfully.`);
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ function getLimitSetForSubscriptionType(
|
|||||||
export async function handleSubscriptionLifesycle(
|
export async function handleSubscriptionLifesycle(
|
||||||
orgId: string,
|
orgId: string,
|
||||||
status: string,
|
status: string,
|
||||||
subType: SubscriptionType | null
|
subType: SubscriptionType | null = null
|
||||||
) {
|
) {
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case "active":
|
case "active":
|
||||||
|
|||||||
@@ -24,13 +24,18 @@ import { fromError } from "zod-validation-error";
|
|||||||
import { sendEmail } from "@server/emails";
|
import { sendEmail } from "@server/emails";
|
||||||
import NotifyTrialExpiring from "@server/emails/templates/NotifyTrialExpiring";
|
import NotifyTrialExpiring from "@server/emails/templates/NotifyTrialExpiring";
|
||||||
import config from "@server/lib/config";
|
import config from "@server/lib/config";
|
||||||
|
import { handleSubscriptionLifesycle } from "../billing/subscriptionLifecycle";
|
||||||
|
|
||||||
const sendTrialNotificationParamsSchema = z.object({
|
const sendTrialNotificationParamsSchema = z.object({
|
||||||
orgId: z.string()
|
orgId: z.string()
|
||||||
});
|
});
|
||||||
|
|
||||||
const sendTrialNotificationBodySchema = z.object({
|
const sendTrialNotificationBodySchema = z.object({
|
||||||
notificationType: z.enum(["trial_ending_5d", "trial_ending_24h", "trial_ended"]),
|
notificationType: z.enum([
|
||||||
|
"trial_ending_5d",
|
||||||
|
"trial_ending_24h",
|
||||||
|
"trial_ended"
|
||||||
|
]),
|
||||||
orgName: z.string(),
|
orgName: z.string(),
|
||||||
trialEndsAt: z.number(),
|
trialEndsAt: z.number(),
|
||||||
billingLink: z.string().optional()
|
billingLink: z.string().optional()
|
||||||
@@ -69,9 +74,7 @@ async function getOrgAdmins(orgId: string) {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
const byUserId = new Map(
|
const byUserId = new Map(admins.map((a) => [a.userId, a]));
|
||||||
admins.map((a) => [a.userId, a])
|
|
||||||
);
|
|
||||||
const orgAdmins = Array.from(byUserId.values()).filter(
|
const orgAdmins = Array.from(byUserId.values()).filter(
|
||||||
(admin) => admin.email && admin.email.length > 0
|
(admin) => admin.email && admin.email.length > 0
|
||||||
);
|
);
|
||||||
@@ -108,8 +111,12 @@ export async function sendTrialNotification(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const { orgId } = parsedParams.data;
|
const { orgId } = parsedParams.data;
|
||||||
const { notificationType, orgName, trialEndsAt, billingLink: bodyBillingLink } =
|
const {
|
||||||
parsedBody.data;
|
notificationType,
|
||||||
|
orgName,
|
||||||
|
trialEndsAt,
|
||||||
|
billingLink: bodyBillingLink
|
||||||
|
} = parsedBody.data;
|
||||||
|
|
||||||
// Verify organization exists
|
// Verify organization exists
|
||||||
const org = await db
|
const org = await db
|
||||||
@@ -146,13 +153,17 @@ export async function sendTrialNotification(
|
|||||||
bodyBillingLink ??
|
bodyBillingLink ??
|
||||||
`${config.getRawConfig().app.dashboard_url}/${orgId}/settings/billing`;
|
`${config.getRawConfig().app.dashboard_url}/${orgId}/settings/billing`;
|
||||||
|
|
||||||
const trialEndsAtFormatted = new Date(trialEndsAt * 1000).toLocaleDateString(
|
const trialEndsAtFormatted = new Date(
|
||||||
"en-US",
|
trialEndsAt * 1000
|
||||||
{ year: "numeric", month: "long", day: "numeric" }
|
).toLocaleDateString("en-US", {
|
||||||
);
|
year: "numeric",
|
||||||
|
month: "long",
|
||||||
|
day: "numeric"
|
||||||
|
});
|
||||||
|
|
||||||
let daysRemaining: number | null;
|
let daysRemaining: number | null;
|
||||||
let subject: string;
|
let subject: string;
|
||||||
|
let resetLimits = false;
|
||||||
|
|
||||||
if (notificationType === "trial_ending_5d") {
|
if (notificationType === "trial_ending_5d") {
|
||||||
daysRemaining = 5;
|
daysRemaining = 5;
|
||||||
@@ -163,6 +174,7 @@ export async function sendTrialNotification(
|
|||||||
} else {
|
} else {
|
||||||
daysRemaining = null;
|
daysRemaining = null;
|
||||||
subject = "Your trial has ended";
|
subject = "Your trial has ended";
|
||||||
|
resetLimits = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
let emailsSent = 0;
|
let emailsSent = 0;
|
||||||
@@ -201,6 +213,14 @@ export async function sendTrialNotification(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (resetLimits) {
|
||||||
|
// this will only fire if they have not upgraded yet because when upgrading we delete the trial
|
||||||
|
await handleSubscriptionLifesycle(orgId, "cancled");
|
||||||
|
logger.debug(
|
||||||
|
`Trial ended for org ${orgId}, limits reset to free tier`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return response<SendTrialNotificationResponse>(res, {
|
return response<SendTrialNotificationResponse>(res, {
|
||||||
data: {
|
data: {
|
||||||
success: true,
|
success: true,
|
||||||
@@ -221,4 +241,4 @@ export async function sendTrialNotification(
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user