Added a staff availability model and migration, a booking validation service, and serializer enforcement.
8.0 KiB
Booking Integrity (Availability, Schedules, Overlap Prevention)
This ExecPlan is a living document. The sections Progress, Surprises & Discoveries, Decision Log, and Outcomes & Retrospective must be kept up to date as work proceeds.
The requirements for ExecPlans live in PLANS.md at the repository root. This document must be maintained in accordance with that file.
Purpose / Big Picture
After this change, bookings cannot be created in invalid time windows or in ways that double-book staff. A manager can rely on the system to prevent overlapping appointments and to enforce staff working hours. You can see it working by attempting to create a booking outside a staff member’s availability window or that overlaps an existing confirmed booking and receiving a clear validation error; creating a booking that fits availability and does not overlap should succeed.
Progress
- (2026-02-28 13:05Z) Created ExecPlan for booking integrity (availability, schedules, overlap prevention).
- (2026-02-28 13:25Z) Added staff availability model, admin registration, and manual migration.
- (2026-02-28 13:30Z) Introduced booking validation service for duration, schedule, and overlap checks.
- (2026-02-28 13:32Z) Updated booking create serializer to require staff and enforce validation rules.
- (2026-02-28 13:45Z) Added backend tests covering overlap prevention, availability windows, and duration validation.
- (2026-02-28 13:50Z) Updated
docs/risks.mdto reflect closed booking-integrity gaps.
Surprises & Discoveries
- Observation: Django is not installed in the environment, so
makemigrationscould not run. Evidence:ImportError: Couldn't import Djangowhen runningpython3 backend/manage.py makemigrations salons.
Decision Log
- Decision: Require
staffon booking creation to enforce schedule and overlap rules deterministically. Rationale: Without an assigned staff member, the system cannot guarantee schedule integrity. Date/Author: 2026-02-28, Codex - Decision: Treat staff availability as open-ended if no availability records exist for that staff member. Rationale: This avoids breaking existing workflows while enabling explicit schedule enforcement when configured. Date/Author: 2026-02-28, Codex
- Decision: Enforce that
end_time - start_timematches the service duration in minutes. Rationale: Prevents inconsistent bookings and ensures predictable slot lengths. Date/Author: 2026-02-28, Codex - Decision: Add the
StaffAvailabilitymigration manually instead of usingmakemigrations. Rationale: Django was unavailable in the environment; a manual migration keeps schema changes explicit and reviewable. Date/Author: 2026-02-28, Codex
Outcomes & Retrospective
Booking integrity is now enforced via staff availability checks, duration validation, and overlap prevention, with test coverage for each rule. This closes the highest-risk booking integrity gap in docs/risks.md, while timezone and business-hours enforcement remain future work.
Context and Orientation
Booking creation is implemented in backend/apps/bookings/serializers.py (BookingCreateSerializer) and routed via backend/apps/bookings/views.py in a DRF ModelViewSet. The booking model lives in backend/apps/bookings/models.py, while staff information is in backend/apps/salons/models.py as StaffProfile. There is no current scheduling model and no overlap validation. This plan introduces a staff availability model and a dedicated booking validation service to keep business logic out of views, in line with project standards.
Plan of Work
First, add a staff availability model in backend/apps/salons/models.py. Create a StaffAvailability model with a foreign key to StaffProfile, a day-of-week integer (0-6), and start/end times (as TimeField). Use an is_active boolean to allow disabling entries without deleting them. Register the model in backend/apps/salons/admin.py for basic management. Create and apply a migration in the salons app.
Next, add a booking validation service in backend/apps/bookings/services.py. The service should expose a function like validate_booking_request(service, staff, start_time, end_time) that raises serializers.ValidationError or a custom domain error translated into DRF validation errors. It should check:
staffis required and belongs to the same salon as the service.start_time < end_timeand duration matchesservice.duration_minutes.- Staff availability: if availability records exist for the staff and day-of-week, ensure the booking window is fully inside one availability window with
is_active=True. - Overlap: prevent any booking for the same staff with status in
pendingorconfirmedthat overlaps the requested window;cancelledandcompletedbookings should not block.
Then, update BookingCreateSerializer in backend/apps/bookings/serializers.py to call the validation service and to require staff. Keep create unchanged beyond relying on validated data.
Finally, add tests in backend/apps/bookings/tests/test_booking_integrity.py. Cover these cases:
- Reject bookings with no staff assigned.
- Reject bookings where
end_timeprecedesstart_time. - Reject bookings where duration does not match
service.duration_minutes. - Reject bookings outside staff availability when availability records exist.
- Allow bookings when no availability records exist.
- Reject overlapping bookings for the same staff with
pendingorconfirmedstatus; allow overlaps withcancelledorcompletedbookings.
Update docs/risks.md to mark booking integrity gaps as addressed once tests pass.
Concrete Steps
Run these commands from the repository root (/home/m7md/kshkool/Salon).
-
Add staff availability model and migration.
- Edit
backend/apps/salons/models.pyandbackend/apps/salons/admin.py. - Run: python3 backend/manage.py makemigrations salons
- Edit
-
Add booking validation service and update serializer.
- Create
backend/apps/bookings/services.pyand updatebackend/apps/bookings/serializers.py.
- Create
-
Add tests.
- Create
backend/apps/bookings/tests/test_booking_integrity.py.
- Create
-
Run tests.
- Backend: python3 -m pytest
Validation and Acceptance
- Attempting to create a booking without a staff member returns HTTP 400 with a clear validation error.
- Creating a booking outside availability returns HTTP 400 with a clear validation error.
- Creating a booking overlapping an existing pending/confirmed booking for the same staff returns HTTP 400.
- Creating a booking within an availability window and without overlap returns HTTP 201.
- Running
python3 -m pytestpasses, and the new booking-integrity tests fail before the changes and pass after.
Idempotence and Recovery
Model and serializer changes are additive and safe to reapply. If a migration needs to be re-run, it can be rolled back using standard Django migration rollback and re-applied. The validation service is pure and can be iterated without impacting data. If availability rules are too strict, disabling availability entries will effectively remove the constraint without deleting data.
Artifacts and Notes
Example overlap query used in validation:
Booking.objects.filter(
staff=staff,
status__in=[BookingStatus.PENDING, BookingStatus.CONFIRMED],
start_time__lt=end_time,
end_time__gt=start_time,
)
Interfaces and Dependencies
backend/apps/salons/models.pymust define a newStaffAvailabilitymodel with fields:staff(FK),day_of_week(0-6),start_time,end_time,is_active.backend/apps/bookings/services.pymust definevalidate_booking_request(service, staff, start_time, end_time).backend/apps/bookings/serializers.pymust call the validation service and requirestaffon create.
Plan Maintenance Note: Created on 2026-02-28 to implement booking integrity (availability, schedules, overlap prevention) as the next Phase 1 reliability step. Plan Maintenance Note (Update): Marked milestones complete and recorded the manual migration decision after implementing booking integrity and tests on 2026-02-28.