from datetime import timedelta from django.utils.translation import gettext_lazy as _ from rest_framework import serializers from apps.bookings.models import Booking, BookingStatus from apps.salons.models import StaffAvailability, StaffProfile def validate_booking_request(service, staff, start_time, end_time): if staff is None: raise serializers.ValidationError({"staff": _("Staff is required for booking")}) if isinstance(staff, StaffProfile) and staff.salon_id != service.salon_id: raise serializers.ValidationError({"staff": _("Selected staff does not belong to this salon")}) if start_time >= end_time: raise serializers.ValidationError({"end_time": _("End time must be after start time")}) expected_end = start_time + timedelta(minutes=service.duration_minutes) if expected_end != end_time: raise serializers.ValidationError({"end_time": _("End time must match service duration")}) availability_qs = StaffAvailability.objects.filter( staff=staff, day_of_week=start_time.weekday(), is_active=True, ) if availability_qs.exists(): within_window = availability_qs.filter( start_time__lte=start_time.time(), end_time__gte=end_time.time(), ).exists() if not within_window: raise serializers.ValidationError({"start_time": _("Booking is outside staff availability")}) overlap_exists = Booking.objects.filter( staff=staff, status__in=[BookingStatus.PENDING, BookingStatus.CONFIRMED], start_time__lt=end_time, end_time__gt=start_time, ).exists() if overlap_exists: raise serializers.ValidationError({"start_time": _("Booking overlaps an existing appointment")})