@@ -50,6 +50,34 @@ async function restoreMemberProSubscriptions(organizationId: string): Promise<nu
5050 return restoredCount
5151}
5252
53+ /**
54+ * Cleanup organization when team/enterprise subscription is deleted.
55+ * - Restores member Pro subscriptions
56+ * - Deletes the organization
57+ * - Syncs usage limits for former members (resets to free or Pro tier)
58+ */
59+ async function cleanupOrganizationSubscription ( organizationId : string ) : Promise < {
60+ restoredProCount : number
61+ membersSynced : number
62+ } > {
63+ // Get member userIds before deletion (needed for limit syncing after org deletion)
64+ const memberUserIds = await db
65+ . select ( { userId : member . userId } )
66+ . from ( member )
67+ . where ( eq ( member . organizationId , organizationId ) )
68+
69+ const restoredProCount = await restoreMemberProSubscriptions ( organizationId )
70+
71+ await db . delete ( organization ) . where ( eq ( organization . id , organizationId ) )
72+
73+ // Sync usage limits for former members (now free or Pro tier)
74+ for ( const m of memberUserIds ) {
75+ await syncUsageLimitsFromSubscription ( m . userId )
76+ }
77+
78+ return { restoredProCount, membersSynced : memberUserIds . length }
79+ }
80+
5381/**
5482 * Handle new subscription creation - reset usage if transitioning from free to paid
5583 */
@@ -137,33 +165,23 @@ export async function handleSubscriptionDeleted(subscription: {
137165 const totalOverage = await calculateSubscriptionOverage ( subscription )
138166 const stripe = requireStripeClient ( )
139167
140- // Enterprise plans have no overages - reset usage, restore Pro, sync limits, delete org
168+ // Enterprise plans have no overages - reset usage and cleanup org
141169 if ( subscription . plan === 'enterprise' ) {
142- // Get member userIds before any changes (needed for limit syncing after org deletion)
143- const memberUserIds = await db
144- . select ( { userId : member . userId } )
145- . from ( member )
146- . where ( eq ( member . organizationId , subscription . referenceId ) )
147-
148170 await resetUsageForSubscription ( {
149171 plan : subscription . plan ,
150172 referenceId : subscription . referenceId ,
151173 } )
152- const restoredProCount = await restoreMemberProSubscriptions ( subscription . referenceId )
153-
154- await db . delete ( organization ) . where ( eq ( organization . id , subscription . referenceId ) )
155174
156- // Sync usage limits for former members (now free or Pro tier)
157- for ( const m of memberUserIds ) {
158- await syncUsageLimitsFromSubscription ( m . userId )
159- }
175+ const { restoredProCount, membersSynced } = await cleanupOrganizationSubscription (
176+ subscription . referenceId
177+ )
160178
161179 logger . info ( 'Successfully processed enterprise subscription cancellation' , {
162180 subscriptionId : subscription . id ,
163181 stripeSubscriptionId,
164182 restoredProCount,
165183 organizationDeleted : true ,
166- membersSynced : memberUserIds . length ,
184+ membersSynced,
167185 } )
168186 return
169187 }
@@ -270,27 +288,19 @@ export async function handleSubscriptionDeleted(subscription: {
270288 referenceId : subscription . referenceId ,
271289 } )
272290
273- // For team: restore member Pro subscriptions, sync limits, delete organization
291+ // Plan-specific cleanup after billing
274292 let restoredProCount = 0
275293 let organizationDeleted = false
276294 let membersSynced = 0
277- if ( subscription . plan === 'team' ) {
278- // Get member userIds before deletion (needed for limit syncing)
279- const memberUserIds = await db
280- . select ( { userId : member . userId } )
281- . from ( member )
282- . where ( eq ( member . organizationId , subscription . referenceId ) )
283-
284- restoredProCount = await restoreMemberProSubscriptions ( subscription . referenceId )
285295
286- await db . delete ( organization ) . where ( eq ( organization . id , subscription . referenceId ) )
296+ if ( subscription . plan === 'team' ) {
297+ const cleanup = await cleanupOrganizationSubscription ( subscription . referenceId )
298+ restoredProCount = cleanup . restoredProCount
299+ membersSynced = cleanup . membersSynced
287300 organizationDeleted = true
288-
289- // Sync usage limits for former members (now free or Pro tier)
290- for ( const m of memberUserIds ) {
291- await syncUsageLimitsFromSubscription ( m . userId )
292- }
293- membersSynced = memberUserIds . length
301+ } else if ( subscription . plan === 'pro' ) {
302+ await syncUsageLimitsFromSubscription ( subscription . referenceId )
303+ membersSynced = 1
294304 }
295305
296306 // Note: better-auth's Stripe plugin already updates status to 'canceled' before calling this handler
@@ -299,6 +309,7 @@ export async function handleSubscriptionDeleted(subscription: {
299309 logger . info ( 'Successfully processed subscription cancellation' , {
300310 subscriptionId : subscription . id ,
301311 stripeSubscriptionId,
312+ plan : subscription . plan ,
302313 totalOverage,
303314 restoredProCount,
304315 organizationDeleted,
0 commit comments