Skip to content

Commit 4d5a657

Browse files
committed
Use expiration date for cancellations
1 parent 832485b commit 4d5a657

File tree

2 files changed

+41
-8
lines changed

2 files changed

+41
-8
lines changed

services/WebhookService.ts

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ const handleCheckoutSessionCompleted = async (session: Stripe.Checkout.Session):
4444
status: 'active',
4545
license_type: productConfig.licenseType,
4646
stripe_payment_id: session.subscription as string,
47+
expiration_date: undefined,
4748
updated_at: new Date()
4849
})
4950
return
@@ -57,6 +58,7 @@ const handleCheckoutSessionCompleted = async (session: Stripe.Checkout.Session):
5758
await LicenseRepo.updateLicense(existingSubscriptionLicense.id, {
5859
status: 'active',
5960
stripe_payment_id: session.subscription as string,
61+
expiration_date: undefined,
6062
updated_at: new Date()
6163
})
6264
console.log('Existing subscription license updated')
@@ -70,6 +72,7 @@ const handleCheckoutSessionCompleted = async (session: Stripe.Checkout.Session):
7072
purchase_date: new Date(),
7173
stripe_customer_id: customerId,
7274
stripe_payment_id: session.subscription as string,
75+
expiration_date: undefined,
7376
})
7477
console.log(`License created for user ${userId} with checkout session ${session.id}`)
7578

@@ -106,30 +109,46 @@ const handleCheckoutSessionCompleted = async (session: Stripe.Checkout.Session):
106109

107110
const handleSubscriptionUpdated = async (subscription: Stripe.Subscription): Promise<void> => {
108111
console.log('subscription', subscription)
112+
113+
// Get license info
114+
const license = await LicenseRepo.getLicenseByCustomerId(subscription.customer as string)
115+
116+
if (!license) {
117+
console.warn(`No license found for customer ${subscription.customer}`)
118+
return
119+
}
120+
109121
// Check if subscription was just marked for cancellation
110-
if (subscription.cancel_at_period_end) {
122+
if (subscription.cancel_at_period_end && subscription.cancel_at) {
111123
console.log(`Subscription ${subscription.id} marked for cancellation at period end`)
112124

125+
// Set expiration date to when subscription will cancel
126+
const expirationDate = new Date(subscription.cancel_at * 1000)
127+
await LicenseRepo.updateLicense(license.id, {
128+
expiration_date: expirationDate,
129+
updated_at: new Date()
130+
})
131+
132+
console.log(`Expiration date set to ${expirationDate.toISOString()} for license ${license.id}`)
133+
113134
// Send Discord notification for cancellation request
114135
try {
115136
const notificationEngine = getNotificationEngine()
116137

117-
// Get license info to get user_id
118-
const license = await LicenseRepo.getLicenseByCustomerId(subscription.customer as string)
119-
120138
await notificationEngine.sendNotification({
121139
type: 'subscription_cancelled',
122140
user: {
123-
id: license?.user_id || 'unknown',
141+
id: license.user_id || 'unknown',
124142
email: 'N/A' // Email not available in subscription object
125143
},
126144
referenceId: `subscription_cancel_requested_${subscription.id}`,
127145
data: {
128146
subscription_id: subscription.id,
129147
customer_id: subscription.customer,
130-
license_id: license?.id,
131-
cancel_at: subscription.cancel_at ? new Date(subscription.cancel_at * 1000) : null,
148+
license_id: license.id,
149+
cancel_at: subscription.cancel_at,
132150
cancel_at_period_end: subscription.cancel_at_period_end,
151+
expiration_date: expirationDate,
133152
status: subscription.status,
134153
message: 'User requested cancellation - will expire at period end'
135154
}
@@ -140,6 +159,19 @@ const handleSubscriptionUpdated = async (subscription: Stripe.Subscription): Pro
140159
console.error('Failed to send Discord notification for cancellation request:', error)
141160
// Don't throw - we don't want Discord failures to break webhook processing
142161
}
162+
} else {
163+
// Subscription was reactivated or updated - remove expiration date if it exists
164+
if (license.expiration_date) {
165+
console.log(`Subscription ${subscription.id} reactivated - removing expiration date`)
166+
167+
await LicenseRepo.updateLicense(license.id, {
168+
expiration_date: undefined,
169+
status: 'active',
170+
updated_at: new Date()
171+
})
172+
173+
console.log(`Expiration date removed for license ${license.id}`)
174+
}
143175
}
144176
}
145177

@@ -154,6 +186,7 @@ const handleSubscriptionDeleted = async (subscription: Stripe.Subscription): Pro
154186

155187
// Send Discord notification for subscription cancellation
156188
try {
189+
157190
const notificationEngine = getNotificationEngine()
158191

159192
await notificationEngine.sendNotification({

types/notifications.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import type { PaidUserRecord, NewUserRecord, InactiveUserRecord } from './jobs'
22

33
export type { PaidUserRecord, NewUserRecord, InactiveUserRecord } from './jobs'
44

5-
export type NotificationType = 'paid_user' | 'new_user' | 'inactive_user' | 'weekly_report' | 'payment_failed' | 'checkout_completed' | 'subscription_cancelled'
5+
export type NotificationType = 'paid_user' | 'new_user' | 'inactive_user' | 'weekly_report' | 'payment_failed' | 'checkout_completed' | 'subscription_cancelled' | 'subscription_expired'
66
export type NotificationChannel = 'discord' | 'email' | 'slack' | 'sms'
77

88
export interface BaseUserRecord {

0 commit comments

Comments
 (0)