L12 Zeiterfassung: Tests und authentifizierter Smoke

test-zeiterfassung-service (78 Prüfungen) und test-zeiterfassung-sync (29 Prüfungen),
Rollen-Matrix um field:record_own_time und time:approve ergänzt, smoke-auth um
/m/time, /m/time/new, /m/approvals, Uhr-Leiste und /work-orders/time-approvals.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-15 09:29:46 +02:00
co-authored by Claude Opus 5
parent fe3eba6e44
commit 9f4eecf6e2
4 changed files with 409 additions and 1 deletions
+16
View File
@@ -26,6 +26,7 @@ import { createOrderType } from "../src/server/services/work-orders/settings";
import { listImports } from "../src/server/services/imports/queries";
import { createNote } from "../src/server/services/field/notes";
import { correctTimeEntry } from "../src/server/services/field/time-correction";
import { addManualTimeEntry, approveTimeEntry } from "../src/server/services/field/time-entries";
import { createDailyReport } from "../src/server/services/reports/create";
import { approveReport } from "../src/server/services/reports/approve";
import { listReports } from "../src/server/services/reports/queries";
@@ -98,6 +99,21 @@ runSuite("Sicherheit: Rollen-Matrix", [SLUG], async () => {
{ permission: "import:write", label: "Importe", run: (c) => listImports(c) },
{ permission: "field:execute", label: "Tätigkeitsnotiz erfassen", run: (c) => createNote(c, noteCreatePayload.parse({ workOrderId: shared.id, text: "Rollenprüfung" })) },
{ permission: "field:correct_time", label: "Arbeitszeit korrigieren", run: (c) => correctTimeEntry(c, { timeEntryId: entry.id, startedAt: session.startedAt, endedAt: session.endedAt, reason: "Rollenprüfung" }) },
// L12 Zeiterfassung
{
permission: "field:record_own_time",
label: "Eigene Zeit nachtragen",
run: (c) => addManualTimeEntry(c, { workOrderId: shared.id, type: "work", startedAt: new Date(Date.now() - 26 * 3600_000), durationMinutes: 30, reason: "Rollenprüfung" }),
},
{
permission: "time:approve",
label: "Zeitnachtrag freigeben",
run: async (c) => {
const s = await prisma.workSession.create({ data: { tenantId: A.tenantId, workOrderId: shared.id, userId: A.users.tech2.id, status: "ended", manual: true, startedAt: new Date(Date.now() - 7200_000), endedAt: new Date(Date.now() - 3600_000) } });
const e = await prisma.timeEntry.create({ data: { tenantId: A.tenantId, workSessionId: s.id, userId: A.users.tech2.id, startedAt: s.startedAt, endedAt: s.endedAt, source: "manual", approvalStatus: "pending", correctionReason: "Rollenprüfung" } });
return approveTimeEntry(c, e.id);
},
},
{ permission: "report:write", label: "Tagesbericht anlegen", run: async (c) => createDailyReport(c, { workOrderId: (await rawOrder(A, "planned")).id }) },
{ permission: "report:approve_team", label: "Bericht freigeben (Teamleiter oder Backoffice)", run: (c) => approveReport(c, { reportId: draftReport.id }, { dispatchPdf: async () => undefined }) },
{ permission: "emergency:create", label: "Notdienst-Kundensuche", run: (c) => searchCustomersForEmergency(c, "Hausverwaltung") },