Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion apps/sim/app/api/billing/switch-plan/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ export async function POST(request: NextRequest) {
quantity: currentQuantity,
},
],
proration_behavior: 'create_prorations',
proration_behavior: 'always_invoice',
Comment thread
icecrasher321 marked this conversation as resolved.
})
}

Expand Down
23 changes: 23 additions & 0 deletions apps/sim/lib/billing/webhooks/invoices.ts
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,15 @@ export async function handleInvoicePaymentSucceeded(event: Stripe.Event) {
return
}

// Skip proration invoices (e.g. from mid-cycle plan upgrades) — only process cycle renewals
if (invoice.billing_reason && invoice.billing_reason !== 'subscription_cycle') {
logger.info('Skipping non-cycle invoice payment succeeded', {
invoiceId: invoice.id,
billingReason: invoice.billing_reason,
})
return
}
Comment thread
icecrasher321 marked this conversation as resolved.
Outdated

const records = await db
.select()
.from(subscriptionTable)
Expand Down Expand Up @@ -556,6 +565,20 @@ export async function handleInvoicePaymentFailed(event: Stripe.Event) {
return
}

// Skip proration invoices (e.g. from mid-cycle plan upgrades) — don't block users over proration failures.
// Overage invoices (threshold + cycle-end) bypass this guard via !isOverageInvoice and still block.
if (
!isOverageInvoice &&
invoice.billing_reason &&
invoice.billing_reason !== 'subscription_cycle'
) {
logger.info('Skipping non-cycle invoice payment failure', {
invoiceId: invoice.id,
billingReason: invoice.billing_reason,
})
return
}
Comment thread
icecrasher321 marked this conversation as resolved.
Outdated

// Extract and validate customer ID
const customerId = invoice.customer
if (!customerId || typeof customerId !== 'string') {
Expand Down
Loading