Skip to content

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 über starts_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.tserzeugt bei Genehmigung Abwesenheits-Artefakte: einen appointments-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.tsnotifyLeaveRecipients (an Manager/Antragsteller).
  • leave-realtime.tsLeaveChangedEvent fü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ückrollen

API-Endpunkte

EndpointFunktion
GET/POST /api/leave/requestsAnträge listen / stellen
POST /api/leave/requests/[id]/decisiongenehmigen/ablehnen
POST /api/leave/requests/[id]/revokezurückziehen/stornieren
GET /api/leave/requests/[id]/eventsEvent-Verlauf eines Antrags
GET/POST /api/leave/typesAbwesenheitsarten (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.

Verwandte Notes

Work7 · Software für Handwerksbetriebe