MCPcopy
hub / github.com/simstudioai/sim / handleInvoiceFinalized

Function handleInvoiceFinalized

apps/sim/lib/billing/webhooks/invoices.ts:982–1241  ·  view source on GitHub ↗
(event: Stripe.Event)

Source from the content-addressed store, hash-verified

980 * Note: Enterprise plans no longer have overages
981 */
982export async function handleInvoiceFinalized(event: Stripe.Event) {
983 try {
984 const invoice = event.data.object as Stripe.Invoice
985 const subscription = invoice.parent?.subscription_details?.subscription
986 const stripeSubscriptionId = typeof subscription === 'string' ? subscription : subscription?.id
987 if (!stripeSubscriptionId) {
988 logger.info('No subscription found on invoice; skipping finalized handler', {
989 invoiceId: invoice.id,
990 })
991 return
992 }
993 if (invoice.billing_reason && invoice.billing_reason !== 'subscription_cycle') return
994
995 const records = await db
996 .select()
997 .from(subscriptionTable)
998 .where(eq(subscriptionTable.stripeSubscriptionId, stripeSubscriptionId))
999 .limit(1)
1000
1001 if (records.length === 0) return
1002 const sub = records[0]
1003
1004 const invoicePeriod = getSubscriptionLinePeriod(invoice, stripeSubscriptionId)
1005 if (!invoicePeriod) {
1006 logger.error('Missing subscription line period on subscription cycle invoice', {
1007 invoiceId: invoice.id,
1008 stripeSubscriptionId,
1009 })
1010 if (isEnterprise(sub.plan)) {
1011 await resetUsageForSubscription({ plan: sub.plan, referenceId: sub.referenceId })
1012 }
1013 return
1014 }
1015
1016 if (isEnterprise(sub.plan)) {
1017 await resetUsageForSubscription({
1018 plan: sub.plan,
1019 referenceId: sub.referenceId,
1020 periodStart: invoicePeriod.periodStart,
1021 periodEnd: invoicePeriod.periodEnd,
1022 })
1023 return
1024 }
1025
1026 await stripeWebhookIdempotency.executeWithIdempotency(
1027 'invoice-finalized',
1028 event.id,
1029 async () => {
1030 const stripe = requireStripeClient()
1031 const periodStart = Math.floor(invoicePeriod.periodStart.getTime() / 1000)
1032 const periodEnd = Math.floor(invoicePeriod.periodEnd.getTime() / 1000)
1033 const billingPeriod = new Date(periodEnd * 1000).toISOString().slice(0, 7)
1034
1035 const totalOverage = await calculateSubscriptionOverage({
1036 ...sub,
1037 periodStart: new Date(periodStart * 1000),
1038 periodEnd: new Date(periodEnd * 1000),
1039 })

Callers 1

auth.tsFile · 0.90

Calls 15

isEnterpriseFunction · 0.90
requireStripeClientFunction · 0.90
isSubscriptionOrgScopedFunction · 0.90
toNumberFunction · 0.90
toDecimalFunction · 0.90
infoMethod · 0.80
errorMethod · 0.80

Tested by

no test coverage detected