Commit Graph
6 Commits
Author SHA1 Message Date
patrickandClaude Opus 4.8 eb8dace0fd feat(overtime): Auszahlungs-Anträge durch Mitarbeiter (opt-in pro Firma)
Mitarbeiter beantragt Überstunden-Auszahlung, HR genehmigt/lehnt ab.
Firmen-Opt-in payout_request_enabled (Default aus - nur HR-Direktbuchung).
Saldo-Abzug erst bei Genehmigung; Reject/Cancel bucht nichts.

- Migration 0042: hours_payouts.status/decided_by/decided_at/rejection_reason
  + companies.payout_request_enabled (nur Spalten, RLS unveraendert)
- Router: POST /hr/payouts/request|{id}/approve|reject|cancel; list status-Filter;
  HR-Direktbuchung bleibt (status approved)
- Frontend: PayoutRequestCard (Selbstbedienung in AbsencesPage), HR-Page
  Status-Spalte + Genehmigen/Ablehnen, CompanySettings-Toggle
- 4 pytest-Cases

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-08 22:43:26 +02:00
patrickandClaude Opus 4.8 eab41ede69 feat: agent-12 – Zwei-Stufen-Genehmigung für Abwesenheiten
Optionale zweistufige Freigabe (Feature-Parität mit Urlaubsverwaltung,
Second-Stage-Authority), ohne SSO:

- Firmen-Opt-in companies.two_stage_approval_enabled + two_stage_min_days
  (nur Anträge ab X Arbeitstagen brauchen Stufe 2; 0 = alle).
- Ablauf PENDING → FIRST_APPROVED → APPROVED: erste Stufe durch Manager-Rollen,
  finale Stufe nur HR/Admin und zwingend eine ANDERE Person als Stufe 1.
- Urlaubs-/FZA-Abzug, CalDAV-Sync und Vertreter-Mail erst bei finaler Genehmigung.
  Ablehnen in beiden Stufen möglich; Eigentümer darf FIRST_APPROVED noch stornieren.
- pending_days, Kalender und Reminder-Digest berücksichtigen FIRST_APPROVED.
- Neuer Status-Wert + absences.first_approved_by; System-Kommentar bei Stufe 1.

Frontend: CompanySettingsPage (Toggle + Schwellwert), AbsencesPage
("Endgültig genehmigen"/Ablehnen für HR/Admin ≠ Erstgenehmiger, Status-Badge).

Migration 0038. 190/190 Tests grün. Deployed 137 + 164.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 13:17:32 +02:00
patrickandClaude Opus 4.8 e8bed43570 feat: agent-11 PR2 – Urlaubsanspruch (Verfall scharf, Pro-rata, Teilzeit)
Korrektheit der Urlaubskonten (Feature-Parität mit Urlaubsverwaltung):

- Verfall scharfgeschaltet: neuer effektiv verfügbarer Saldo (available_days)
  schließt verfallenen, noch nicht verbrauchten Resturlaub aus; Konto-Warnung
  beim Antrag nutzt jetzt available statt remaining. (Verfallsdatum bleibt in
  company.settings, UI bereits vorhanden.)
- Anteilige Berechnung (Zwölftel) im Ein-/Austrittsjahr anhand neuer Felder
  users.entry_date / exit_date; opt-in pro Firma (vacation_prorate_first_year).
- Teilzeit: Anspruch optional aus Arbeitstagen/Woche des WorkSchedule abgeleitet
  (vacation_from_schedule), Basis vacation_default_days.
- _get_or_create_balance berechnet den Grundanspruch jetzt frisch
  (_compute_entitlement); _carryover_expired/effective_available als Service-API,
  Router delegiert.

Frontend: CompanySettingsPage (Jahresurlaub + Pro-rata- und Teilzeit-Toggles),
UsersPage (Ein-/Austrittsdatum im Edit-Modal), AbsencesPage ("Verfügbar" + Hinweis
bei verfallenem Resturlaub).

Migration 0036. 183/183 Tests grün. Deployed auf 137 + 164.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 12:03:42 +02:00
patrickandClaude Opus 4.8 6fa66b8c13 feat: agent-11 PR1 – Vertretung, Storno-Re-Genehmigung, Kommentare
Abwesenheits-Modul abgerundet (Feature-Parität mit Urlaubsverwaltung):

- Vertretung: Overlap-Warnung beim Anlegen, E-Mail an Vertretung bei
  Genehmigung, GET /absences/?as_substitute=true, neuer schlanker
  GET /users/colleagues (alle Rollen, RLS-gefenced) für die Auswahl;
  Vertreter-Dropdown + Anzeige in der Liste.
- Stornierung mit Re-Genehmigung: neuer Status CANCELLATION_REQUESTED,
  POST /absences/{id}/request-cancellation; Manager genehmigt/lehnt über
  bestehende approve/reject ab (Urlaub + FZA-Rückbuchung via _apply_cancellation).
- Kommentare: Model AbsenceComment (company_id-RLS), GET/POST comments,
  System-Kommentare bei Statuswechsel, AbsenceCommentsModal.
- Fix: CalDAV fire-and-forget nutzte die Request-Session weiter (in Tests
  geteilt -> "another operation in progress"); jetzt sync_*_bg mit eigener
  Session + RLS-Bypass.

Migration 0035. 178/178 Tests grün. Deployed auf 137 + 164.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 11:47:47 +02:00
patrickandClaude Sonnet 4.6 4cce09521e feat: FZA Einzelstunden + Security-Fixes (K-1–K-5, H-2–H-4, M-1/M-3/M-6)
FZA Einzelstunden:
- Absence.fza_hours (Numeric 5,2) — FZA in Stunden statt Tagen
- Migration 0032: fza_hours Spalte in absences
- AbsenceCreate/AbsenceOut Schema um fza_hours erweitert
- absence_service: _deduct/_refund_overtime nutzt fza_hours direkt wenn gesetzt
- Frontend: Tage/Stunden-Toggle im FZA-Antrag-Modal

Security K-1: Privilege Escalation via PATCH /users/{id}.role
- user_service: Whitelist für Rollenänderungen, SUPER_ADMIN nur durch SUPER_ADMIN
- Letzter COMPANY_ADMIN gegen Selbst-Demotion gesichert

Security K-2: Kiosk-IP-Whitelist hinter nginx
- kiosk_security: _get_client_ip() liest X-Real-IP statt request.client.host

Security K-3: Kiosk-PIN Brute-Force-Schutz
- kiosk_auth_service: Redis-Lockout nach 5 Fehlversuchen (15 min)

Security K-4: TOTP-Setup-Hijacking
- auth router: /totp/setup abgelehnt wenn TOTP bereits aktiv

Security K-5: Separater Fernet-Key
- config: SECRET_KEY_DATA Feld (optional, Fallback auf SECRET_KEY)
- crypto: get_fernet_key() mit Warning bei fehlendem SECRET_KEY_DATA

Security H-2: Vacation Balance nur HR/Admin
- absences router: PATCH /balance nur noch HR/COMPANY_ADMIN/SUPER_ADMIN + AuditLog

Security H-3: Rate-Limits auf /auth/refresh + /auth/logout
- auth router: 30/min auf refresh, 60/min auf logout

Security H-4: Login-Failure-Logging + Lockout
- auth_service: Redis-Counter, Lockout nach 10 Versuchen (15 min)
- AuditLog für login_success und login_failed

Security M-1: Nginx Security-Header
- nginx.conf: X-Frame-Options, X-Content-Type-Options, CSP, Referrer-Policy, X-XSS-Protection, Permissions-Policy

Security M-3: AuditLog bei Rollenänderungen
- user_service: action=role_changed mit old/new role

Security M-6: create_all nur in Development
- main.py: Base.metadata.create_all nur wenn not settings.is_production

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-26 11:13:42 +02:00
sysopsandClaude Sonnet 4.6 45218cc744 Initial commit – TimeMaster Zeiterfassung & HR-Tool
Stand: agent-06 (Audit-Log), agent-05 (Krankmeldung), agent-07 Phase 1 (Personalnummer),
Busylight-Pull-Integration, TOTP/2FA, Abwesenheiten, Zeiterfassung, Kiosk-Grundgerüst.
Migrations 0001–0023 deployed auf 192.168.1.137 + .164.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 20:03:27 +02:00