feat: WIP stripe billing refactor update for 2025

pull/715/head
Travis Fischer 2025-05-18 03:11:45 +07:00
rodzic ed0867a3b9
commit 8ea3a4f4b6
4 zmienionych plików z 15 dodań i 12 usunięć

Wyświetl plik

@ -87,10 +87,10 @@ export const consumers = pgTable(
stripeStatus: text(),
// Main Stripe Subscription id
stripeSubscriptionId: stripeId(),
_stripeSubscriptionId: stripeId(),
// [lineItemSlug: string]: string
stripeSubscriptionLineItemIdMap: jsonb()
_stripeSubscriptionLineItemIdMap: jsonb()
.$type<Record<string, string>>()
.default({})
.notNull(),
@ -132,7 +132,7 @@ export const consumerRelationsSchema: z.ZodType<ConsumerRelationFields> =
z.enum(['user', 'project', 'deployment'])
export const consumerSelectSchema = createSelectSchema(consumers, {
stripeSubscriptionLineItemIdMap: z.record(z.string(), z.string()),
_stripeSubscriptionLineItemIdMap: z.record(z.string(), z.string()),
deploymentId: (schema) =>
schema.refine((id) => validators.deploymentId(id), {
@ -145,6 +145,8 @@ export const consumerSelectSchema = createSelectSchema(consumers, {
})
})
.omit({
_stripeSubscriptionId: true,
_stripeSubscriptionLineItemIdMap: true,
_stripeCustomerId: true
})
.extend({

Wyświetl plik

@ -341,7 +341,7 @@ export const pricingPlanMapSchema = z
export type PricingPlanMap = z.infer<typeof pricingPlanMapSchema>
// TODO
// export const stripeSubscriptionLineItemIdMapSchema = z
// export const _stripeSubscriptionLineItemIdMapSchema = z
// .record(pricingPlanLineItemHashSchema, z.string().describe('Stripe LineItem id'))
// .describe('Map from internal PricingPlanLineItem **hash** to Stripe LineItem id')
// .openapi('StripeSubscriptionLineItemMap')

Wyświetl plik

@ -33,6 +33,7 @@ export async function upsertConsumer(
if (!consumerId) {
assert(projectId, 400, 'Missing required "deploymentId"')
assert(plan, 400, 'Missing required "plan"')
}
const [{ user, stripeCustomer }, existingConsumer] = await Promise.all([
@ -113,8 +114,8 @@ export async function upsertConsumer(
;[consumer] = await db.insert(schema.consumers).values({
plan,
userId,
deploymentId,
projectId,
deploymentId,
// TODO: refactor / improve token generation
token: sha256().slice(0, 24),
_stripeCustomerId: stripeCustomer.id

Wyświetl plik

@ -53,17 +53,17 @@ export async function upsertStripeSubscription(
? deployment.pricingPlans.find((pricingPlan) => pricingPlan.slug === plan)
: undefined
const action: 'create' | 'update' | 'cancel' = consumer.stripeSubscriptionId
const action: 'create' | 'update' | 'cancel' = consumer._stripeSubscriptionId
? plan
? 'update'
: 'cancel'
: 'create'
let subscription: Stripe.Subscription | undefined
if (consumer.stripeSubscriptionId) {
if (consumer._stripeSubscriptionId) {
// customer has an existing subscription
const existing = await stripe.subscriptions.retrieve(
consumer.stripeSubscriptionId,
consumer._stripeSubscriptionId,
...stripeConnectParams
)
const existingItems = existing.items.data
@ -155,7 +155,7 @@ export async function upsertStripeSubscription(
assert(
items.length || !plan,
500,
`Error updating stripe subscription "${consumer.stripeSubscriptionId}"`
`Error updating stripe subscription "${consumer._stripeSubscriptionId}"`
)
for (const item of items) {
@ -182,7 +182,7 @@ export async function upsertStripeSubscription(
}
subscription = await stripe.subscriptions.update(
consumer.stripeSubscriptionId,
consumer._stripeSubscriptionId,
update,
...stripeConnectParams
)
@ -246,7 +246,7 @@ export async function upsertStripeSubscription(
...stripeConnectParams
)
consumer.stripeSubscriptionId = subscription.id
consumer._stripeSubscriptionId = subscription.id
}
assert(subscription, 500, 'Missing stripe subscription')
@ -258,7 +258,7 @@ export async function upsertStripeSubscription(
consumerUpdate.stripeStatus = subscription.status
} else {
// TODO
consumerUpdate.stripeSubscriptionId = null
consumerUpdate._stripeSubscriptionId = null
consumerUpdate.stripeStatus = 'cancelled'
}