Darstellung
07 – Urlaub / Abwesenheit (Leave)
Reifegrad: 🟢 produktiv · Schicht: leave_*-Tabellen, src/lib/leave/*, src/app/leave, src/app/settings/leave, src/app/api/leave/*
Zweck
Antrag, Genehmigung und Kontingentverwaltung von Abwesenheiten (Urlaub, Krankheit etc.) – inkl. rückwirkender und stundengenauer Anträge, mit automatischer Erzeugung von Kalender-Abwesenheiten.
Datenmodell (Migration 017 + 039)
leave_types: Abwesenheitsarten je Mandant (type_key,counts_against_quota,requires_manager_approval,requires_attachment).leave_policies: Regeln pro Typ/Jahr (entitlement_days,carry_over_limit_days,min_notice_days,allow_half_days,requires_document_from_day).leave_balances: Salden je User/Typ/Jahr (entitlement_days,carry_over_days,used_days,pending_days,remaining_days).leave_requests: Antrag (starts_on/ends_on,requested_days,status∈ {pending, approved, declined, cancelled},request_channel∈ {portal, whatsapp, api},is_retroactive,attachment_document_id,approved_appointment_id). Stundengenau überstarts_at/ends_at/requested_minutes(Migration 039).leave_approvals: Entscheidungsprotokoll (decision,decision_channel,decision_message_id).leave_request_events: Event-Log (event_type,payload).
Geschäftslogik (src/lib/leave/*)
leave-types-service.ts/leave-policy-service.ts– Stammdaten & Regeln.leave-balance-service.ts– Saldoführung:rollbackPendingLeaveDays,finalizeApprovedLeaveDays(pending → used bei Genehmigung).leave-apply-service.ts– erzeugt bei Genehmigung Abwesenheits-Artefakte: einenappointments-Eintrag (appointment_type='absence',status='confirmed',source_channel='leave_approval') und pusht ihn in verbundene Kalender (pushAppointmentToActiveProviders/enqueueOutboundAppointmentSync).leave-time-utils.ts– Fensterparsing (ParsedLeaveWindow, ganztägig vs. stundengenau), Label-Formatierung. Unit-getestet (leave-time-utils.test.ts).leave-form-validation.ts,leave-history-utils.ts,leave-list-patch.ts– jeweils mit Tests (npm run test:leave).routing.ts–notifyLeaveRecipients(an Manager/Antragsteller).leave-realtime.ts–LeaveChangedEventfür die Realtime-Bridge (leave:changed).
Workflow
Antrag (portal/whatsapp/api) → pending (Saldo: pending_days +=)
├─ approve → approved → Saldo finalisieren + appointments(absence) + Kalender-Push + Notify
├─ decline → declined → pending zurückrollen
└─ revoke → cancelled → Artefakte/Saldo zurückrollenAPI-Endpunkte
| Endpoint | Funktion |
|---|---|
GET/POST /api/leave/requests | Anträge listen / stellen |
POST /api/leave/requests/[id]/decision | genehmigen/ablehnen |
POST /api/leave/requests/[id]/revoke | zurückziehen/stornieren |
GET /api/leave/requests/[id]/events | Event-Verlauf eines Antrags |
GET/POST /api/leave/types | Abwesenheitsarten (mandantenweit) |
UI
/leave– Mitarbeiter-/Manager-Sicht (Anträge, Salden, Genehmigung)./settings/leave– Konfiguration der Typen/Policies.- Komponenten:
src/components/leave/*.
Besonderheiten
- Mehrkanalfähig: Anträge & Entscheidungen können über Portal oder WhatsApp laufen (
request_channel,decision_channel,decision_message_id) – verzahnt mit dem Agent (siehe 11-whatsapp-agent). - Rückwirkende Anträge (
is_retroactive) sind explizit unterstützt. - Genehmigte Abwesenheit erscheint automatisch in Plantafel/Kapazität (
user_absences+appointments), siehe 06-termine-kalender-plantafel.