Phase8: Auto bill credit card
All checks were successful
Build and Push / build (push) Successful in 1m45s

This commit is contained in:
2026-05-27 22:20:13 +02:00
parent a6c3c42ec9
commit 9243beddd3
2 changed files with 30 additions and 26 deletions

View File

@@ -525,8 +525,23 @@ export async function POST(request: Request) {
// Build the billing snapshot from the org's address (already // Build the billing snapshot from the org's address (already
// fetched above for the wizard's billing-address resolution). // fetched above for the wizard's billing-address resolution).
// The snapshot is what the invoice + Stripe customer use. // The snapshot is what the invoice + Stripe customer use.
const billingSnapshot: InvoiceBillingSnapshot = orgBilling //
? { // 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, companyName: orgBilling.companyName,
contactName: orgBilling.contactName ?? null, contactName: orgBilling.contactName ?? null,
streetAddress: orgBilling.streetAddress, streetAddress: orgBilling.streetAddress,
@@ -536,17 +551,6 @@ export async function POST(request: Request) {
vatNumber: orgBilling.vatNumber ?? null, vatNumber: orgBilling.vatNumber ?? null,
billingEmail: orgBilling.billingEmail, billingEmail: orgBilling.billingEmail,
notes: orgBilling.notes ?? null, 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,
}; };
// Locale for the invoice + PDF — pick from the org's country // Locale for the invoice + PDF — pick from the org's country

View File

@@ -4203,7 +4203,7 @@ export async function getTenantRequestForSetupFlow(
[requestId] [requestId]
); );
return result.rows.length > 0 return result.rows.length > 0
? rowToTenantRequest(result.rows[0]) ? mapRow(result.rows[0])
: null; : null;
} }
@@ -4231,7 +4231,7 @@ export async function createTenantRequestPendingPayment(params: {
soulMd?: string; soulMd?: string;
agentsMd?: string | null; agentsMd?: string | null;
packages: string[]; packages: string[];
billingAddress: Record<string, unknown>; billingAddress: BillingAddress;
billingNotes?: string; billingNotes?: string;
encryptedSecrets?: Buffer | null; encryptedSecrets?: Buffer | null;
isPersonal: boolean; isPersonal: boolean;
@@ -4267,7 +4267,7 @@ export async function createTenantRequestPendingPayment(params: {
params.isPersonal, params.isPersonal,
] ]
); );
return rowToTenantRequest(result.rows[0]); return mapRow(result.rows[0]);
} }
/** /**