fix: handle trials and resubscribing (#1897)

This commit is contained in:
Lucas Smith
2025-07-14 12:31:06 +10:00
committed by GitHub
parent 55abecc526
commit ca9a70ced5
3 changed files with 33 additions and 20 deletions

View File

@ -1,13 +0,0 @@
import { z } from 'zod';
export const ZEarlyAdopterCheckoutMetadataSchema = z.object({
name: z.string(),
email: z.string(),
signatureText: z.string(),
signatureDataUrl: z.string().optional(),
source: z.literal('marketing'),
});
export type TEarlyAdopterCheckoutMetadataSchema = z.infer<
typeof ZEarlyAdopterCheckoutMetadataSchema
>;

View File

@ -81,17 +81,34 @@ export const onSubscriptionCreated = async ({ subscription }: OnSubscriptionCrea
const status = match(subscription.status) const status = match(subscription.status)
.with('active', () => SubscriptionStatus.ACTIVE) .with('active', () => SubscriptionStatus.ACTIVE)
.with('trialing', () => SubscriptionStatus.ACTIVE)
.with('past_due', () => SubscriptionStatus.PAST_DUE) .with('past_due', () => SubscriptionStatus.PAST_DUE)
.otherwise(() => SubscriptionStatus.INACTIVE); .otherwise(() => SubscriptionStatus.INACTIVE);
await prisma.subscription.create({ const periodEnd =
data: { subscription.status === 'trialing' && subscription.trial_end
? new Date(subscription.trial_end * 1000)
: new Date(subscription.current_period_end * 1000);
await prisma.subscription.upsert({
where: {
organisationId,
},
create: {
organisationId, organisationId,
status, status,
customerId, customerId,
planId: subscription.id, planId: subscription.id,
priceId: subscription.items.data[0].price.id, priceId: subscription.items.data[0].price.id,
periodEnd: new Date(subscription.current_period_end * 1000), periodEnd,
cancelAtPeriodEnd: subscription.cancel_at_period_end,
},
update: {
status,
customerId,
planId: subscription.id,
priceId: subscription.items.data[0].price.id,
periodEnd,
cancelAtPeriodEnd: subscription.cancel_at_period_end, cancelAtPeriodEnd: subscription.cancel_at_period_end,
}, },
}); });
@ -172,14 +189,17 @@ const handleOrganisationUpdate = async ({ customerId, claim }: HandleOrganisatio
} }
// Todo: logging // Todo: logging
if (organisation.subscription) { if (
console.error('Organisation already has a subscription'); organisation.subscription &&
organisation.subscription.status !== SubscriptionStatus.INACTIVE
) {
console.error('Organisation already has an active subscription');
// This should never happen // This should never happen
throw Response.json( throw Response.json(
{ {
success: false, success: false,
message: `Organisation already has a subscription`, message: `Organisation already has an active subscription`,
} satisfies StripeWebhookResponse, } satisfies StripeWebhookResponse,
{ status: 500 }, { status: 500 },
); );

View File

@ -83,9 +83,15 @@ export const onSubscriptionUpdated = async ({
const status = match(subscription.status) const status = match(subscription.status)
.with('active', () => SubscriptionStatus.ACTIVE) .with('active', () => SubscriptionStatus.ACTIVE)
.with('trialing', () => SubscriptionStatus.ACTIVE)
.with('past_due', () => SubscriptionStatus.PAST_DUE) .with('past_due', () => SubscriptionStatus.PAST_DUE)
.otherwise(() => SubscriptionStatus.INACTIVE); .otherwise(() => SubscriptionStatus.INACTIVE);
const periodEnd =
subscription.status === 'trialing' && subscription.trial_end
? new Date(subscription.trial_end * 1000)
: new Date(subscription.current_period_end * 1000);
await prisma.$transaction(async (tx) => { await prisma.$transaction(async (tx) => {
await tx.subscription.update({ await tx.subscription.update({
where: { where: {
@ -96,7 +102,7 @@ export const onSubscriptionUpdated = async ({
status: status, status: status,
planId: subscription.id, planId: subscription.id,
priceId: subscription.items.data[0].price.id, priceId: subscription.items.data[0].price.id,
periodEnd: new Date(subscription.current_period_end * 1000), periodEnd,
cancelAtPeriodEnd: subscription.cancel_at_period_end, cancelAtPeriodEnd: subscription.cancel_at_period_end,
}, },
}); });