Files
timemaster/backend/migrations/versions/0028_overtime_fza_config.py
T
patrick 345002944e feat: Freizeitausgleich-Lücken geschlossen (Gap 1-3) + konfigurierbare Schwellwerte
Gap-1: Überziehschutz für Überstundenkonto
  - Company.overtime_overdraft_allowed (default: true) – blockiert FZA wenn deaktiviert
  - Company.overtime_warning_threshold_hours (default: 0) – Warnung wenn Konto unter Schwelle fällt
  - warnings[] jetzt in approve_absence Response (AbsenceApproveOut)
  - Migration 0028_overtime_fza_config.py

Gap-2: total_hours wird bei Zeiteintrag-Genehmigung neu berechnet
  - time_service.approve_entry() ruft _recalculate_overtime_balance() auf
  - last_calculated Timestamp wird gesetzt

Gap-3: Stornierung genehmigter FZA-Anträge bucht taken_hours zurück
  - _refund_overtime() Helfer hinzugefügt
  - cancel_absence() erlaubt jetzt HR/Admin auch genehmigte Abwesenheiten zu stornieren
  - DELETE /absences/{id} gibt jetzt AbsenceOut zurück (statt 204)
  - Mitarbeiter können genehmigte FZA-Anträge nicht selbst stornieren (409)

Frontend:
  - CompanySettingsPage: neuer Abschnitt 'Freizeitausgleich' mit Toggle + Schwellwert-Eingabe

Tests: backend/tests/test_fza.py mit 6 Tests (alle 3 Gaps)

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

48 lines
1.3 KiB
Python

"""Freizeitausgleich-Konfiguration: Überstunden-Überziehen und Warnschwelle
Revision ID: 0028
Revises: 0027
Create Date: 2026-05-25
Neue Felder in companies:
overtime_overdraft_allowed BOOLEAN DEFAULT TRUE
- Steuert ob das Überstundenkonto ins Minus gezogen werden darf.
- Default TRUE: bestehende Firmen behalten bisheriges Verhalten (kein Block).
overtime_warning_threshold_hours INTEGER DEFAULT 0
- Warnung wenn Konto nach Abzug unter diesen Wert fällt.
- Default 0: keine Warnung (bestehende Firmen unverändert).
"""
from alembic import op
import sqlalchemy as sa
revision = "0028"
down_revision = "0027"
branch_labels = None
depends_on = None
def upgrade() -> None:
op.add_column(
"companies",
sa.Column(
"overtime_overdraft_allowed",
sa.Boolean(),
nullable=False,
server_default=sa.text("true"),
),
)
op.add_column(
"companies",
sa.Column(
"overtime_warning_threshold_hours",
sa.Integer(),
nullable=False,
server_default=sa.text("0"),
),
)
def downgrade() -> None:
op.drop_column("companies", "overtime_warning_threshold_hours")
op.drop_column("companies", "overtime_overdraft_allowed")