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>
This commit is contained in:
@@ -210,6 +210,15 @@ async def get_overtime_balance(
|
||||
)
|
||||
if bal is None:
|
||||
return OvertimeBalanceOut(total_hours=0, taken_hours=0, available_hours=0)
|
||||
|
||||
# Verfall anwenden wenn nötig
|
||||
from app.services.report_service import apply_overtime_expiry_if_needed
|
||||
from app.models.company import Company as CompanyModel
|
||||
company = await db.get(CompanyModel, current_user.company_id)
|
||||
changed = await apply_overtime_expiry_if_needed(bal, company, db)
|
||||
if changed:
|
||||
await db.commit()
|
||||
|
||||
return OvertimeBalanceOut(
|
||||
total_hours=float(bal.total_hours),
|
||||
taken_hours=float(bal.taken_hours),
|
||||
@@ -217,6 +226,29 @@ async def get_overtime_balance(
|
||||
)
|
||||
|
||||
|
||||
@router.post("/absences/overtime-balance/apply-expiry")
|
||||
async def apply_overtime_expiry_all(
|
||||
current_user: User = require_role(UserRole.COMPANY_ADMIN, UserRole.SUPER_ADMIN),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
"""Überstunden-Verfall manuell für alle Mitarbeiter der Firma anwenden."""
|
||||
from sqlalchemy import select as sa_select
|
||||
from app.models.company import Company as CompanyModel
|
||||
from app.services.report_service import apply_overtime_expiry_if_needed
|
||||
|
||||
company = await db.get(CompanyModel, current_user.company_id)
|
||||
balances = list(await db.scalars(
|
||||
sa_select(OvertimeBalance).where(OvertimeBalance.company_id == current_user.company_id)
|
||||
))
|
||||
applied_count = 0
|
||||
for bal in balances:
|
||||
changed = await apply_overtime_expiry_if_needed(bal, company, db)
|
||||
if changed:
|
||||
applied_count += 1
|
||||
await db.commit()
|
||||
return {"applied_to": applied_count, "total": len(balances)}
|
||||
|
||||
|
||||
@router.get("/absences/", response_model=AbsenceListResponse)
|
||||
async def list_absences(
|
||||
current_user: CurrentUser,
|
||||
|
||||
Reference in New Issue
Block a user