"""Booking validation service.""" from datetime import datetime from sqlalchemy import and_ from sqlalchemy.orm import Session from app.models.booking import Booking from app.models.settings import Settings def validate_booking_rules( db: Session, space_id: int, user_id: int, start_datetime: datetime, end_datetime: datetime, exclude_booking_id: int | None = None, ) -> list[str]: """ Validate booking against global settings rules. Args: db: Database session space_id: ID of the space to book user_id: ID of the user making the booking start_datetime: Booking start time end_datetime: Booking end time exclude_booking_id: Optional booking ID to exclude from overlap check (used when re-validating an existing booking) Returns: List of validation error messages (empty list = validation OK) """ errors = [] # Fetch settings (create default if not exists) settings = db.query(Settings).filter(Settings.id == 1).first() if not settings: settings = Settings( id=1, min_duration_minutes=30, max_duration_minutes=480, working_hours_start=8, working_hours_end=20, max_bookings_per_day_per_user=3, min_hours_before_cancel=2, ) db.add(settings) db.commit() db.refresh(settings) # a) Validate duration in range duration_minutes = (end_datetime - start_datetime).total_seconds() / 60 if ( duration_minutes < settings.min_duration_minutes or duration_minutes > settings.max_duration_minutes ): errors.append( f"Durata rezervării trebuie să fie între {settings.min_duration_minutes} " f"și {settings.max_duration_minutes} minute" ) # b) Validate working hours if ( start_datetime.hour < settings.working_hours_start or end_datetime.hour > settings.working_hours_end ): errors.append( f"Rezervările sunt permise doar între {settings.working_hours_start}:00 " f"și {settings.working_hours_end}:00" ) # c) Check for overlapping bookings query = db.query(Booking).filter( Booking.space_id == space_id, Booking.status.in_(["approved", "pending"]), and_( Booking.start_datetime < end_datetime, Booking.end_datetime > start_datetime, ), ) # Exclude current booking if re-validating if exclude_booking_id is not None: query = query.filter(Booking.id != exclude_booking_id) overlapping_bookings = query.first() if overlapping_bookings: errors.append("Spațiul este deja rezervat în acest interval") # d) Check max bookings per day per user booking_date = start_datetime.date() start_of_day = datetime.combine(booking_date, datetime.min.time()) end_of_day = datetime.combine(booking_date, datetime.max.time()) user_bookings_count = ( db.query(Booking) .filter( Booking.user_id == user_id, Booking.status.in_(["approved", "pending"]), Booking.start_datetime >= start_of_day, Booking.start_datetime <= end_of_day, ) .count() ) if user_bookings_count >= settings.max_bookings_per_day_per_user: errors.append( f"Ai atins limita de {settings.max_bookings_per_day_per_user} rezervări pe zi" ) return errors