// L14 follow-up: direct transition to `billed` is blocked while the billing overview module is active. // (1) billing module active (default) → transitionWorkOrder(to billed) → invalid use_billing_overview // (2) billing module disabled → direct transition allowed (legacy behaviour) // // Lauf: npx tsx scripts/test-billed-guard.ts import "dotenv/config"; import { randomUUID } from "node:crypto"; import { prisma } from "../src/server/db"; import { ServiceError } from "../src/server/services/context"; import { transitionWorkOrder } from "../src/server/services/work-orders/transition"; import { createTenant, ok, runSuite, section, type TenantFixture } from "./lib/e2e-fixture"; const SLUG = "zz-billed-guard"; async function releasedOrder(A: TenantFixture) { return prisma.workOrder.create({ data: { tenantId: A.tenantId, number: `BG-${randomUUID().slice(0, 6)}`, customerId: A.customerId, siteId: A.siteId, title: "Abrechnungsschutz", status: "released_for_billing", assignedTeamId: A.teamId, }, }); } void runSuite("Direktes Abrechnen gesperrt", [SLUG], async () => { const A = await createTenant(SLUG); section("Modul billing aktiv"); const wo1 = await releasedOrder(A); let code = "ok"; let message = ""; try { await transitionWorkOrder(A.ctx.backoffice, { workOrderId: wo1.id, to: "billed" }); } catch (err) { code = err instanceof ServiceError ? err.code : "error"; message = err instanceof Error ? err.message : ""; } ok(code === "invalid" && message === "use_billing_overview", `(1) direkter Übergang → invalid use_billing_overview (erhalten ${code} ${message})`); ok((await prisma.workOrder.findUniqueOrThrow({ where: { id: wo1.id } })).status === "released_for_billing", "(1) Status unverändert"); section("Modul billing deaktiviert"); await prisma.tenantModule.upsert({ where: { tenantId_moduleKey: { tenantId: A.tenantId, moduleKey: "billing" } }, update: { enabled: false }, create: { tenantId: A.tenantId, moduleKey: "billing", enabled: false }, }); const wo2 = await releasedOrder(A); const res = await transitionWorkOrder(A.ctx.backoffice, { workOrderId: wo2.id, to: "billed" }); ok(res.status === "billed", "(2) ohne Abrechnungsmodul ist der direkte Übergang erlaubt"); });