feat: aggiunti: loggica random, tema scuro, correzioni mail, miglioramenti generali, cache;

This commit is contained in:
StefanoSalemi
2026-04-17 18:27:37 +02:00
parent a7ef46640d
commit 104ad53a9a
26 changed files with 861 additions and 216 deletions

View File

@@ -29,6 +29,7 @@ class ValidOfficeCreate(BaseModel):
booking_window_enabled: bool = True
booking_window_end_hour: int = 18
booking_window_end_minute: int = 0
assignment_mode: str = "fairness"
class ClosingDayCreate(BaseModel):
@@ -61,6 +62,7 @@ class OfficeSettingsUpdate(BaseModel):
booking_window_enabled: bool | None = None
booking_window_end_hour: int | None = None
booking_window_end_minute: int | None = None
assignment_mode: str | None = None
# Helper check
@@ -127,6 +129,7 @@ def create_office(data: ValidOfficeCreate, db: Session = Depends(get_db), user=D
booking_window_enabled=data.booking_window_enabled,
booking_window_end_hour=data.booking_window_end_hour,
booking_window_end_minute=data.booking_window_end_minute,
assignment_mode=data.assignment_mode,
created_at=datetime.utcnow()
)
db.add(office)
@@ -157,7 +160,8 @@ def get_office_details(office_id: str, db: Session = Depends(get_db), user=Depen
"user_count": user_count,
"booking_window_enabled": office.booking_window_enabled,
"booking_window_end_hour": office.booking_window_end_hour,
"booking_window_end_minute": office.booking_window_end_minute
"booking_window_end_minute": office.booking_window_end_minute,
"assignment_mode": getattr(office, 'assignment_mode', 'fairness')
}
@@ -194,6 +198,9 @@ def update_office_settings(office_id: str, data: OfficeSettingsUpdate, db: Sessi
raise HTTPException(status_code=400, detail="Minute must be 0-59")
office.booking_window_end_minute = data.booking_window_end_minute
if data.assignment_mode is not None:
office.assignment_mode = data.assignment_mode
office.updated_at = datetime.utcnow()
db.commit()
@@ -208,7 +215,8 @@ def update_office_settings(office_id: str, data: OfficeSettingsUpdate, db: Sessi
"spot_prefix": office.spot_prefix,
"booking_window_enabled": office.booking_window_enabled,
"booking_window_end_hour": office.booking_window_end_hour,
"booking_window_end_minute": office.booking_window_end_minute
"booking_window_end_minute": office.booking_window_end_minute,
"assignment_mode": getattr(office, 'assignment_mode', 'fairness')
}
@router.delete("/{office_id}")
@@ -277,6 +285,29 @@ def add_office_closing_day(office_id: str, data: ClosingDayCreate, db: Session =
)
db.add(closing_day)
db.commit()
# Clear presence and parking assignments for this new closed period
end_date = data.end_date or data.date
users = db.query(User).filter(User.office_id == office_id).all()
user_ids = [u.id for u in users]
if user_ids:
# Delete Parking Assignments
db.query(DailyParkingAssignment).filter(
DailyParkingAssignment.user_id.in_(user_ids),
DailyParkingAssignment.date >= data.date,
DailyParkingAssignment.date <= end_date
).delete(synchronize_session=False)
# Delete Presence
db.query(UserPresence).filter(
UserPresence.user_id.in_(user_ids),
UserPresence.date >= data.date,
UserPresence.date <= end_date
).delete(synchronize_session=False)
db.commit()
return {"id": closing_day.id, "message": "Closing day added"}

View File

@@ -30,6 +30,7 @@ from services.parking import (
run_batch_allocation, clear_assignments_for_office_date
)
from services.notifications import notify_parking_assigned, notify_parking_released, notify_parking_reassigned
from utils.helpers import generate_uuid
from app import config
router = APIRouter(prefix="/api/parking", tags=["parking"])
@@ -271,6 +272,9 @@ def manual_assign(data: ManualAssignRequest, db: Session = Depends(get_db), curr
db.add(new_assignment)
db.commit()
# Send Notification
notify_parking_assigned(user, assign_date, spot_def.name)
return {"message": "Spot assigned", "spot_id": data.spot_id, "spot_display_name": spot_def.name}

View File

@@ -268,9 +268,20 @@ def get_team_presences(start_date: date, end_date: date, office_id: str = None,
office_lookup = {o.id: o.name for o in offices}
# Build response
from services.parking import get_user_parking_ratio
result = []
for user in users:
user_presences = [p for p in presences if p.user_id == user.id]
office_mode = "fairness"
if user.office_id:
office = next((o for o in offices if o.id == user.office_id), None)
if office:
office_mode = office.assignment_mode or "fairness"
user_ratio = None
if office_mode == "fairness" and user.office_id:
user_ratio = get_user_parking_ratio(user.id, user.office_id, db)
result.append({
"id": user.id,
@@ -279,7 +290,8 @@ def get_team_presences(start_date: date, end_date: date, office_id: str = None,
"office_name": office_lookup.get(user.office_id),
"presences": [{"date": p.date, "status": p.status} for p in user_presences],
"parking_dates": parking_lookup.get(user.id, []),
"parking_info": parking_info_lookup.get(user.id, [])
"parking_info": parking_info_lookup.get(user.id, []),
"ratio": user_ratio
})
return result