aggiunti trasferte, export excel, miglioramenti generali

This commit is contained in:
2026-02-04 12:55:04 +01:00
parent 17453f5d13
commit 5f4ef6faee
30 changed files with 1558 additions and 325 deletions

View File

@@ -2,13 +2,13 @@
User Management Routes
Admin user CRUD and user self-service (profile, settings, password)
"""
from datetime import datetime
from datetime import datetime, date
from fastapi import APIRouter, Depends, HTTPException
from pydantic import BaseModel, EmailStr
from sqlalchemy.orm import Session
from database.connection import get_db
from database.models import User, UserRole, Office
from database.models import User, UserRole, Office, ParkingExclusion
from utils.auth_middleware import get_current_user, require_admin
from utils.helpers import (
generate_uuid, is_ldap_user, is_ldap_admin,
@@ -54,6 +54,20 @@ class ChangePasswordRequest(BaseModel):
new_password: str
class UserExclusionCreate(BaseModel):
start_date: date | None = None
end_date: date | None = None
notes: str | None = None
class UserExclusionResponse(BaseModel):
id: str
start_date: date | None
end_date: date | None
notes: str | None
is_excluded: bool = True
class UserResponse(BaseModel):
id: str
email: str
@@ -332,3 +346,105 @@ def change_password(data: ChangePasswordRequest, db: Session = Depends(get_db),
db.commit()
config.logger.info(f"User {current_user.email} changed password")
return {"message": "Password changed"}
# Exclusion Management (Self-Service)
# Exclusion Management (Self-Service)
@router.get("/me/exclusion", response_model=list[UserExclusionResponse])
def get_my_exclusions(db: Session = Depends(get_db), current_user=Depends(get_current_user)):
"""Get current user's parking exclusions"""
if not current_user.office_id:
return []
exclusions = db.query(ParkingExclusion).filter(
ParkingExclusion.user_id == current_user.id,
ParkingExclusion.office_id == current_user.office_id
).all()
return [
{
"id": e.id,
"start_date": e.start_date,
"end_date": e.end_date,
"notes": e.notes,
"is_excluded": True
}
for e in exclusions
]
@router.post("/me/exclusion")
def create_my_exclusion(data: UserExclusionCreate, db: Session = Depends(get_db), current_user=Depends(get_current_user)):
"""Create new parking exclusion for current user"""
if not current_user.office_id:
raise HTTPException(status_code=400, detail="User is not assigned to an office")
if data.start_date and data.end_date and data.end_date < data.start_date:
raise HTTPException(status_code=400, detail="End date must be after start date")
if data.end_date and not data.start_date:
raise HTTPException(status_code=400, detail="Start date is required if an end date is specified")
exclusion = ParkingExclusion(
id=generate_uuid(),
office_id=current_user.office_id,
user_id=current_user.id,
start_date=data.start_date,
end_date=data.end_date,
notes=data.notes or "Auto-esclusione utente",
created_at=datetime.utcnow()
)
db.add(exclusion)
db.commit()
return {"message": "Exclusion created", "id": exclusion.id}
@router.put("/me/exclusion/{exclusion_id}")
def update_my_exclusion(exclusion_id: str, data: UserExclusionCreate, db: Session = Depends(get_db), current_user=Depends(get_current_user)):
"""Update specific parking exclusion for current user"""
if not current_user.office_id:
raise HTTPException(status_code=400, detail="User is not assigned to an office")
exclusion = db.query(ParkingExclusion).filter(
ParkingExclusion.id == exclusion_id,
ParkingExclusion.user_id == current_user.id,
ParkingExclusion.office_id == current_user.office_id
).first()
if not exclusion:
raise HTTPException(status_code=404, detail="Exclusion not found")
if data.start_date and data.end_date and data.end_date < data.start_date:
raise HTTPException(status_code=400, detail="End date must be after start date")
if data.end_date and not data.start_date:
raise HTTPException(status_code=400, detail="Start date is required if an end date is specified")
exclusion.start_date = data.start_date
exclusion.end_date = data.end_date
if data.notes is not None:
exclusion.notes = data.notes
exclusion.updated_at = datetime.utcnow()
db.commit()
return {"message": "Exclusion updated", "id": exclusion.id}
@router.delete("/me/exclusion/{exclusion_id}")
def delete_my_exclusion(exclusion_id: str, db: Session = Depends(get_db), current_user=Depends(get_current_user)):
"""Remove specific parking exclusion for current user"""
if not current_user.office_id:
raise HTTPException(status_code=400, detail="User is not assigned to an office")
exclusion = db.query(ParkingExclusion).filter(
ParkingExclusion.id == exclusion_id,
ParkingExclusion.user_id == current_user.id,
ParkingExclusion.office_id == current_user.office_id
).first()
if not exclusion:
raise HTTPException(status_code=404, detail="Exclusion not found")
db.delete(exclusion)
db.commit()
return {"message": "Exclusion removed"}