Phase8: Auto bill credit card
Some checks failed
Build and Push / build (push) Failing after 42s

This commit is contained in:
2026-05-27 22:06:32 +02:00
parent ad4f614130
commit ee6bb89fb6
20 changed files with 1857 additions and 122 deletions

View File

@@ -0,0 +1,72 @@
import { NextResponse } from "next/server";
import { z } from "zod";
import { requirePlatformRole } from "@/lib/session";
import {
getOrgBillingConfig,
setAutoChargeEnabled,
updateOrgBillingConfig,
} from "@/lib/db";
import { safeError } from "@/lib/errors";
/**
* POST /api/admin/billing/orgs/[orgId]/payment-mode
*
* Phase 9b-2. Admin-only override of an org's billing mode:
* - payByInvoice (boolean) — flip the customer's account to
* bank-transfer billing. Auto-charge is skipped entirely for
* these orgs; they receive the regular issued-invoice email
* and pay manually. Switching ON also implicitly stops
* attempting card charges even if a saved card exists.
* - autoChargeEnabled (boolean) — pause auto-charge without
* committing to pay-by-invoice. Useful during disputes or
* billing investigations.
*
* Either flag may be omitted; the endpoint only writes what's
* provided. Returns the updated config.
*/
const bodySchema = z.object({
payByInvoice: z.boolean().optional(),
autoChargeEnabled: z.boolean().optional(),
});
export async function POST(
request: Request,
{ params }: { params: Promise<{ orgId: string }> }
) {
try {
await requirePlatformRole();
} catch {
return NextResponse.json({ error: "Forbidden" }, { status: 403 });
}
const { orgId } = await params;
const body = await request.json().catch(() => ({}));
const parsed = bodySchema.safeParse(body);
if (!parsed.success) {
return NextResponse.json(
{ error: "Invalid request", details: parsed.error.flatten() },
{ status: 400 }
);
}
const { payByInvoice, autoChargeEnabled } = parsed.data;
if (payByInvoice === undefined && autoChargeEnabled === undefined) {
return NextResponse.json(
{ error: "Provide at least one of payByInvoice or autoChargeEnabled" },
{ status: 400 }
);
}
try {
if (payByInvoice !== undefined) {
await updateOrgBillingConfig(orgId, { payByInvoice });
}
if (autoChargeEnabled !== undefined) {
await setAutoChargeEnabled(orgId, autoChargeEnabled);
}
const cfg = await getOrgBillingConfig(orgId);
return NextResponse.json({ config: cfg });
} catch (e) {
return NextResponse.json(
{ error: safeError(e, "Failed to update payment mode") },
{ status: 500 }
);
}
}