(params: {
organizationId: string
logger: Logger
})
| 26 | * All organizations are expected to have Stripe subscriptions. |
| 27 | */ |
| 28 | export async function syncOrganizationBillingCycle(params: { |
| 29 | organizationId: string |
| 30 | logger: Logger |
| 31 | }): Promise<Date> { |
| 32 | const { organizationId, logger } = params |
| 33 | |
| 34 | const organization = await db.query.org.findFirst({ |
| 35 | where: eq(schema.org.id, organizationId), |
| 36 | columns: { |
| 37 | stripe_customer_id: true, |
| 38 | current_period_start: true, |
| 39 | current_period_end: true, |
| 40 | }, |
| 41 | }) |
| 42 | |
| 43 | if (!organization) { |
| 44 | throw new Error(`Organization ${organizationId} not found`) |
| 45 | } |
| 46 | |
| 47 | if (!organization.stripe_customer_id) { |
| 48 | throw new Error( |
| 49 | `Organization ${organizationId} does not have a Stripe customer ID`, |
| 50 | ) |
| 51 | } |
| 52 | |
| 53 | const now = new Date() |
| 54 | |
| 55 | try { |
| 56 | const subscriptions = await stripeServer.subscriptions.list({ |
| 57 | customer: organization.stripe_customer_id, |
| 58 | status: 'active', |
| 59 | limit: 1, |
| 60 | }) |
| 61 | |
| 62 | if (subscriptions.data.length === 0) { |
| 63 | throw new Error( |
| 64 | `No active Stripe subscription found for organization ${organizationId}`, |
| 65 | ) |
| 66 | } |
| 67 | |
| 68 | const subscription = subscriptions.data[0] |
| 69 | const stripeCurrentStart = new Date( |
| 70 | subscription.current_period_start * 1000, |
| 71 | ) |
| 72 | const stripeCurrentEnd = new Date(subscription.current_period_end * 1000) |
| 73 | |
| 74 | // Check if we need to update the stored billing cycle dates |
| 75 | const needsUpdate = |
| 76 | !organization.current_period_start || |
| 77 | !organization.current_period_end || |
| 78 | Math.abs( |
| 79 | stripeCurrentStart.getTime() - |
| 80 | organization.current_period_start.getTime(), |
| 81 | ) > |
| 82 | 60 * 1000 || |
| 83 | Math.abs( |
| 84 | stripeCurrentEnd.getTime() - organization.current_period_end.getTime(), |
| 85 | ) > |
no test coverage detected