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,29 +525,33 @@ 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
companyName: orgBilling.companyName, // requires a saved Stripe PaymentMethod, which can only be
contactName: orgBilling.contactName ?? null, // created via ensureStripeCustomerForOrg, which requires
streetAddress: orgBilling.streetAddress, // org_billing. If it's missing the system is in an inconsistent
postalCode: orgBilling.postalCode, // state we shouldn't paper over.
city: orgBilling.city, if (!orgBilling) {
country: orgBilling.country, console.error(
vatNumber: orgBilling.vatNumber ?? null, `Paid-fee onboarding path reached without org_billing for org ${user.orgId} — auto-pay pre-check should have prevented this.`
billingEmail: orgBilling.billingEmail, );
notes: orgBilling.notes ?? null, await deletePendingPaymentRequest(tenantRequest.id).catch(() => undefined);
} return NextResponse.json(
: { { error: "Billing record missing. Please re-save your billing details on /settings/billing." },
companyName, { status: 500 }
contactName: contactName, );
streetAddress: billingAddress.streetAddress, }
postalCode: billingAddress.postalCode, const billingSnapshot: InvoiceBillingSnapshot = {
city: billingAddress.city, companyName: orgBilling.companyName,
country: billingAddress.country, contactName: orgBilling.contactName ?? null,
vatNumber: billingAddress.vatNumber ?? null, streetAddress: orgBilling.streetAddress,
billingEmail: billingAddress.billingEmail, postalCode: orgBilling.postalCode,
notes: null, 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 // Locale for the invoice + PDF — pick from the org's country
// using the same heuristic the auto-cron uses. // using the same heuristic the auto-cron uses.

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]);
} }
/** /**