L17 Pakete: Smoke-Prüfungen, Audit-Labels, Betriebsdoku und Lane-Bericht

- smoke-auth: Admin-Karte, Teamleiterin ohne Chat-Platz, Monteur mit Platz,
  demo2 als Basis (Hinweis statt Profi-Seiten, API 403)
- Audit-Labels lotse_chat_seat / tenant_plan
- DEPLOY.md §7.5 (Pakete/Plätze setzen, Mehrverbrauch ablesen), API.md
- docs/craftvia/lanes/pakete.md

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-21 10:21:23 +02:00
co-authored by Claude Opus 5
parent 06d320908f
commit aca571b2e7
5 changed files with 168 additions and 9 deletions
+26 -8
View File
@@ -76,6 +76,9 @@ function plans(x: Awaited<ReturnType<typeof ids>>): Plan[] {
{ path: "/settings/audit" },
{ path: "/settings/email" },
{ path: "/settings/lotse", mustContain: "Lotse-Chat für Monteure" },
// L17 Pakete: Paket nur lesend, Plätze + Verbrauch
{ path: "/settings/lotse", mustContain: ["Paket &amp; Lotse-Chat", "Profi", "3 von 3 Plätzen vergeben", "Max Monteur", "Platz entziehen", "Chats"] },
{ path: "/settings", mustContain: "Freigeschaltete Module" },
{ path: "/settings/lotse/protocol" },
{ path: "/settings/order-types", mustContain: "Montage" },
{ path: "/settings/checklists", mustContain: "Montage Heizung/Sanitär" },
@@ -154,6 +157,10 @@ function plans(x: Awaited<ReturnType<typeof ids>>): Plan[] {
// L13 Planung: team lead read-only, own team only
{ path: "/planning", mustContain: ["Plantafel", "Team Nord", "Nur Lesezugriff"], mustNotContain: ["Team Süd"] },
{ path: "/planning/live", mustContain: "keine GPS-Ortung", mustNotContain: ["Team Süd"] },
// L17 Pakete: Teamleiterin ohne Chat-Platz → kein Navigationseintrag, freundlicher Hinweis
{ path: "/m", mustNotContain: ['href="/m/lotse"'] },
{ path: "/m/lotse", mustContain: "frag im Büro nach", mustNotContain: ['id="lotse-chat-input"'] },
...(x.d14 ? [{ path: m(x.d14), mustContain: x.d14.number, mustNotContain: [`href="/m/lotse?order=${x.d14.id}"`] }] : []),
],
},
{
@@ -189,6 +196,7 @@ function plans(x: Awaited<ReturnType<typeof ids>>): Plan[] {
{ path: "/m/lotse", mustContain: ["Lotse-Chat", "Neuer Chat", "Sprechen"] },
{ path: `/m/lotse?order=${x.d07.id}`, mustContain: [x.d07.number, "Lotse-Chat"] },
{ path: m(x.d07), mustContain: "Lotse fragen" },
{ path: "/m", mustContain: ['href="/m/lotse"', 'href="/m/emergency"'] }, // L17: Platz vergeben, Profi
...(x.d08 ? [{ path: `/m/lotse?order=${x.d08.id}`, expect: [404] }] : []),
// L14 Abrechnungsübersicht: Meilensteine mobil, Backoffice-Übersicht ohne Recht
{ path: m(x.d07), mustContain: ["Meilensteine", "Smoke-Meilenstein", "Erreicht melden"] },
@@ -224,15 +232,25 @@ function plans(x: Awaited<ReturnType<typeof ids>>): Plan[] {
{ path: `/customers/${x.customer.id}`, expect: [404] },
{ path: `/sites/${x.site.id}`, expect: [404] },
{ path: `/reports/${x.approved.id}`, expect: [404] },
...(x.emergency ? [{ path: `/work-orders/emergency-review/${x.emergency.id}`, expect: [404] }] : []),
...(x.imp ? [{ path: `/imports/${x.imp.id}`, expect: [404] }] : []),
// L17: demo2 is Basis → module layouts redirect before the (foreign) id is looked up
...(x.emergency ? [{ path: `/work-orders/emergency-review/${x.emergency.id}`, expect: [307, 404] }] : []),
...(x.imp ? [{ path: `/imports/${x.imp.id}`, expect: [307, 404] }] : []),
...(x.photo ? [{ path: `/files/${x.photo.documentId}`, expect: [404] }] : []),
{ path: "/planning", mustNotContain: ["Team Nord", x.d07.number] },
{ path: "/planning/live", mustNotContain: ["Team Nord", "Max Monteur"] },
{ path: `/api/v1/planning/recommendations?workOrderId=${x.d07.id}`, expect: [404] },
// L14 Abrechnungsübersicht: keine Einträge von demo
{ path: "/billing", mustContain: "Abrechnungsübersicht", mustNotContain: [x.d18.number, "Elbblick"] },
...(x.billing ? [{ path: `/billing/${x.billing.id}`, expect: [404] }, { path: `/billing/print?ids=${x.billing.id}`, mustNotContain: [x.d18.number] }] : []),
// L17 Pakete: demo2 = Basis → Planung, Abrechnung, Import, Notdienst, Lotse gesperrt (ruhiger Hinweis)
{ path: "/planning", expect: [307], redirectTo: "/dashboard" },
{ path: "/planning/live", expect: [307], redirectTo: "/dashboard" },
{ path: `/api/v1/planning/recommendations?workOrderId=${x.d07.id}`, expect: [403, 404] },
{ path: "/api/v1/planning/board", expect: [403] },
{ path: "/billing", expect: [307], redirectTo: "/dashboard" },
{ path: "/imports", expect: [307], redirectTo: "/dashboard" },
{ path: "/work-orders/emergency-review", expect: [307], redirectTo: "/dashboard" },
{ path: "/api/v1/billing", expect: [403] },
{ path: "/dashboard?module=profi", mustContain: ["Im Paket Profi enthalten", "Offene Aufträge"], mustNotContain: ['href="/planning"', 'href="/billing"', 'href="/imports"', 'href="/work-orders/emergency-review"'] },
{ path: "/settings/lotse", mustContain: ["Paket &amp; Lotse-Chat", "Basis", "im Paket Profi enthalten"] },
{ path: "/work-orders", mustContain: "DGUV" },
{ path: "/customers" },
{ path: "/reports" },
...(x.billing ? [{ path: `/billing/${x.billing.id}`, expect: [307, 404] }] : []),
{ path: wo(x.d07, "?tab=billing"), expect: [404] },
],
},