Files
timemaster/backend/migrations/versions/0031_overtime_cap_expiry.py
T
patrick 23ba7f1762 feat: Überstunden-Kappung + Jahresverfall pro Firma konfigurierbar
Backend:
- Company: overtime_cap_hours, overtime_expiry_enabled/month/day,
  overtime_max_carryover_hours
- OvertimeBalance: last_expiry_applied_at
- Migration 0031: neue Spalten in companies + overtime_balances
- _recalculate_overtime_balance: Kappung direkt nach Berechnung
- apply_overtime_expiry_if_needed(): lazy Verfall beim Balance-Abruf
- GET /absences/overtime-balance: prüft + wendet Verfall automatisch an
- POST /absences/overtime-balance/apply-expiry: manueller Trigger (Admin)

Frontend:
- CompanySettingsPage: neuer Block 'Überstunden-Konto'
  - Toggle Kappungsgrenze + Stunden-Input
  - Toggle Jahresverfall + Stichtag (Tag/Monat) + max. Übertrag
  - 'Verfall anwenden'-Button für Admins

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

34 lines
1.3 KiB
Python

"""overtime cap and expiry config
Revision ID: 0031
Revises: 0030
Create Date: 2026-05-25
"""
from alembic import op
import sqlalchemy as sa
revision = '0031'
down_revision = '0030'
branch_labels = None
depends_on = None
def upgrade():
# Companies: Kappung + Verfall
op.add_column('companies', sa.Column('overtime_cap_hours', sa.Integer(), nullable=True))
op.add_column('companies', sa.Column('overtime_expiry_enabled', sa.Boolean(), nullable=False, server_default='false'))
op.add_column('companies', sa.Column('overtime_expiry_month', sa.Integer(), nullable=False, server_default='3'))
op.add_column('companies', sa.Column('overtime_expiry_day', sa.Integer(), nullable=False, server_default='31'))
op.add_column('companies', sa.Column('overtime_max_carryover_hours', sa.Integer(), nullable=True))
# OvertimeBalance: Verfall-Zeitstempel
op.add_column('overtime_balances', sa.Column('last_expiry_applied_at', sa.DateTime(timezone=True), nullable=True))
def downgrade():
op.drop_column('companies', 'overtime_cap_hours')
op.drop_column('companies', 'overtime_expiry_enabled')
op.drop_column('companies', 'overtime_expiry_month')
op.drop_column('companies', 'overtime_expiry_day')
op.drop_column('companies', 'overtime_max_carryover_hours')
op.drop_column('overtime_balances', 'last_expiry_applied_at')