Files
Salon/docs/execplans/booking-integrity.md
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

122 lines
8.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 members 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
- [x] (2026-02-28 13:05Z) Created ExecPlan for booking integrity (availability, schedules, overlap prevention).
- [x] (2026-02-28 13:25Z) Added staff availability model, admin registration, and manual migration.
- [x] (2026-02-28 13:30Z) Introduced booking validation service for duration, schedule, and overlap checks.
- [x] (2026-02-28 13:32Z) Updated booking create serializer to require staff and enforce validation rules.
- [x] (2026-02-28 13:45Z) Added backend tests covering overlap prevention, availability windows, and duration validation.
- [x] (2026-02-28 13:50Z) Updated `docs/risks.md` to reflect closed booking-integrity gaps.
## Surprises & Discoveries
- Observation: Django is not installed in the environment, so `makemigrations` could not run.
Evidence: `ImportError: Couldn't import Django` when running `python3 backend/manage.py makemigrations salons`.
## Decision Log
- Decision: Require `staff` on 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_time` matches the service duration in minutes.
Rationale: Prevents inconsistent bookings and ensures predictable slot lengths.
Date/Author: 2026-02-28, Codex
- Decision: Add the `StaffAvailability` migration manually instead of using `makemigrations`.
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:
- `staff` is required and belongs to the same salon as the service.
- `start_time < end_time` and duration matches `service.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 `pending` or `confirmed` that overlaps the requested window; `cancelled` and `completed` bookings 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_time` precedes `start_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 `pending` or `confirmed` status; allow overlaps with `cancelled` or `completed` bookings.
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`).
1. Add staff availability model and migration.
- Edit `backend/apps/salons/models.py` and `backend/apps/salons/admin.py`.
- Run:
python3 backend/manage.py makemigrations salons
2. Add booking validation service and update serializer.
- Create `backend/apps/bookings/services.py` and update `backend/apps/bookings/serializers.py`.
3. Add tests.
- Create `backend/apps/bookings/tests/test_booking_integrity.py`.
4. 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 pytest` passes, 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.py` must define a new `StaffAvailability` model with fields: `staff` (FK), `day_of_week` (0-6), `start_time`, `end_time`, `is_active`.
- `backend/apps/bookings/services.py` must define `validate_booking_request(service, staff, start_time, end_time)`.
- `backend/apps/bookings/serializers.py` must call the validation service and require `staff` on 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.