From 9243beddd3c68683340a7a4bef3c6069c68c99b5 Mon Sep 17 00:00:00 2001 From: admin Date: Wed, 27 May 2026 22:20:13 +0200 Subject: [PATCH] Phase8: Auto bill credit card --- src/app/api/onboarding/route.ts | 50 ++++++++++++++++++--------------- src/lib/db.ts | 6 ++-- 2 files changed, 30 insertions(+), 26 deletions(-) diff --git a/src/app/api/onboarding/route.ts b/src/app/api/onboarding/route.ts index 7b33dbf..77245bf 100644 --- a/src/app/api/onboarding/route.ts +++ b/src/app/api/onboarding/route.ts @@ -525,29 +525,33 @@ export async function POST(request: Request) { // Build the billing snapshot from the org's address (already // fetched above for the wizard's billing-address resolution). // The snapshot is what the invoice + Stripe customer use. - const billingSnapshot: InvoiceBillingSnapshot = orgBilling - ? { - companyName: orgBilling.companyName, - contactName: orgBilling.contactName ?? null, - streetAddress: orgBilling.streetAddress, - postalCode: orgBilling.postalCode, - city: orgBilling.city, - country: orgBilling.country, - vatNumber: orgBilling.vatNumber ?? null, - billingEmail: orgBilling.billingEmail, - notes: orgBilling.notes ?? null, - } - : { - companyName, - contactName: contactName, - streetAddress: billingAddress.streetAddress, - postalCode: billingAddress.postalCode, - city: billingAddress.city, - country: billingAddress.country, - vatNumber: billingAddress.vatNumber ?? null, - billingEmail: billingAddress.billingEmail, - notes: null, - }; + // + // orgBilling MUST exist here: the auto-pay pre-check above + // requires a saved Stripe PaymentMethod, which can only be + // created via ensureStripeCustomerForOrg, which requires + // org_billing. If it's missing the system is in an inconsistent + // state we shouldn't paper over. + if (!orgBilling) { + console.error( + `Paid-fee onboarding path reached without org_billing for org ${user.orgId} — auto-pay pre-check should have prevented this.` + ); + await deletePendingPaymentRequest(tenantRequest.id).catch(() => undefined); + return NextResponse.json( + { error: "Billing record missing. Please re-save your billing details on /settings/billing." }, + { status: 500 } + ); + } + const billingSnapshot: InvoiceBillingSnapshot = { + companyName: orgBilling.companyName, + contactName: orgBilling.contactName ?? null, + streetAddress: orgBilling.streetAddress, + postalCode: orgBilling.postalCode, + city: orgBilling.city, + country: orgBilling.country, + vatNumber: orgBilling.vatNumber ?? null, + billingEmail: orgBilling.billingEmail, + notes: orgBilling.notes ?? null, + }; // Locale for the invoice + PDF — pick from the org's country // using the same heuristic the auto-cron uses. diff --git a/src/lib/db.ts b/src/lib/db.ts index 85189b6..04540c5 100644 --- a/src/lib/db.ts +++ b/src/lib/db.ts @@ -4203,7 +4203,7 @@ export async function getTenantRequestForSetupFlow( [requestId] ); return result.rows.length > 0 - ? rowToTenantRequest(result.rows[0]) + ? mapRow(result.rows[0]) : null; } @@ -4231,7 +4231,7 @@ export async function createTenantRequestPendingPayment(params: { soulMd?: string; agentsMd?: string | null; packages: string[]; - billingAddress: Record; + billingAddress: BillingAddress; billingNotes?: string; encryptedSecrets?: Buffer | null; isPersonal: boolean; @@ -4267,7 +4267,7 @@ export async function createTenantRequestPendingPayment(params: { params.isPersonal, ] ); - return rowToTenantRequest(result.rows[0]); + return mapRow(result.rows[0]); } /**