Files
aza/AzA march 2026/workforce_planner/api/routes_absences.py

129 lines
3.8 KiB
Python
Raw Normal View History

2026-03-25 22:03:39 +01:00
# -*- coding: utf-8 -*-
"""API-Routen für Abwesenheiten, Kontingente und Genehmigungen."""
import datetime
from typing import Optional
from fastapi import APIRouter, Depends, HTTPException, Query
from sqlalchemy.orm import Session
from ..database import get_db
from ..core.schemas import (
AbsenceCreate, AbsenceUpdate, AbsenceRead,
BalanceRead, BalanceAdjust, ApprovalDecision,
)
from ..core.enums import EmployeeRole
from ..core.models import Employee
from ..absences.service import AbsenceService
from ..absences.rules import RuleViolation
from .auth import get_current_user, require_role
router = APIRouter(prefix="/absences", tags=["Abwesenheiten"])
@router.get("/", response_model=list[AbsenceRead])
def list_absences(
year: Optional[int] = None,
employee_id: Optional[str] = None,
start: Optional[datetime.date] = None,
end: Optional[datetime.date] = None,
db: Session = Depends(get_db),
_user: Employee = Depends(get_current_user),
):
svc = AbsenceService(db)
if employee_id:
return svc.get_absences_for_employee(employee_id, year)
if start and end:
return svc.get_absences_for_period(start, end)
return svc.get_all_absences(year)
@router.post("/", response_model=AbsenceRead, status_code=201)
def create_absence(
data: AbsenceCreate,
db: Session = Depends(get_db),
user: Employee = Depends(get_current_user),
):
svc = AbsenceService(db)
try:
return svc.create_absence(data)
except RuleViolation as e:
raise HTTPException(422, detail={"rule": e.rule, "message": e.message})
except ValueError as e:
raise HTTPException(400, str(e))
@router.patch("/{absence_id}", response_model=AbsenceRead)
def update_absence(
absence_id: str,
data: AbsenceUpdate,
db: Session = Depends(get_db),
_user: Employee = Depends(get_current_user),
):
svc = AbsenceService(db)
try:
result = svc.update_absence(absence_id, data)
except RuleViolation as e:
raise HTTPException(422, detail={"rule": e.rule, "message": e.message})
if not result:
raise HTTPException(404, "Abwesenheit nicht gefunden")
return result
@router.delete("/{absence_id}", status_code=204)
def delete_absence(
absence_id: str,
db: Session = Depends(get_db),
_user: Employee = Depends(get_current_user),
):
svc = AbsenceService(db)
if not svc.delete_absence(absence_id):
raise HTTPException(404, "Abwesenheit nicht gefunden")
@router.post("/approve", response_model=AbsenceRead)
def approve_absence(
decision: ApprovalDecision,
db: Session = Depends(get_db),
_user: Employee = Depends(require_role(EmployeeRole.ADMIN, EmployeeRole.MANAGER)),
):
svc = AbsenceService(db)
try:
return svc.approve(decision)
except ValueError as e:
raise HTTPException(400, str(e))
# ── Kontingent / Balance ────────────────────────────────────
balance_router = APIRouter(prefix="/balance", tags=["Ferientage-Kontingent"])
@balance_router.get("/{employee_id}/{year}", response_model=BalanceRead)
def get_balance(
employee_id: str,
year: int,
db: Session = Depends(get_db),
_user: Employee = Depends(get_current_user),
):
svc = AbsenceService(db)
try:
return svc.get_balance(employee_id, year)
except ValueError as e:
raise HTTPException(404, str(e))
@balance_router.patch("/{employee_id}/{year}", response_model=BalanceRead)
def adjust_balance(
employee_id: str,
year: int,
data: BalanceAdjust,
db: Session = Depends(get_db),
_user: Employee = Depends(require_role(EmployeeRole.ADMIN, EmployeeRole.MANAGER)),
):
svc = AbsenceService(db)
try:
return svc.adjust_balance(employee_id, year, data)
except ValueError as e:
raise HTTPException(404, str(e))