Files
Salon/backend/apps/bookings/services.py
T
mohd 411180e312 Created and activated the booking integrity ExecPlan, then implemented staff availability, overlap prevention, and duration validation with backend tests.
Added a staff availability model and migration, a booking validation service, and serializer enforcement.
2026-02-28 12:05:57 +03:00

46 lines
1.7 KiB
Python

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")})