129 lines
3.8 KiB
Python
129 lines
3.8 KiB
Python
|
|
# -*- 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))
|