Owner calendar view + manual booking + owner cancel/reschedule #20

Closed
opened 2026-07-23 14:07:58 +02:00 by mivanchenko · 1 comment
Owner

Parent

#14

What to build

The owner's day-to-day view of their bookings: an agenda-style calendar, the ability to add a
walk-in/phone booking manually, and the ability to cancel or reschedule any booking from the
dashboard.

  • Agenda view (server-rendered htmx, not a JS calendar library): today / this week, bookings
    grouped by day, showing customer name, service, time, status.
  • Manual booking creation from this view: reuses ticket 2's booking-creation code path (so the
    EXCLUDE constraint always applies) but passed an explicit override flag that skips the
    opening-hours / min-notice / max-advance / buffer checks — the overlap constraint itself is never
    overridable, for the owner or anyone else.
  • Owner-initiated cancel and reschedule on any booking in their agenda, reusing ticket 2's
    cancel/reschedule actions (owner-authenticated instead of token-authenticated).

Acceptance criteria

  • A logged-in owner sees an agenda view of their own client's bookings only, grouped by day.
  • The owner can add a booking outside normal opening hours / inside the min-notice window /
    violating the buffer, and it succeeds.
  • The owner cannot create a booking that overlaps an existing booking on the same resource —
    the EXCLUDE constraint rejects it the same way it does for the public flow.
  • The owner can cancel any of their own bookings from the agenda view.
  • The owner can reschedule any of their own bookings from the agenda view, subject to the same
    overlap protection.

Blocked by

  • #16 (Availability engine + booking API)
  • #19 (Owner accounts: auth, password reset, CRM dashboard visibility)
## Parent #14 ## What to build The owner's day-to-day view of their bookings: an agenda-style calendar, the ability to add a walk-in/phone booking manually, and the ability to cancel or reschedule any booking from the dashboard. - Agenda view (server-rendered htmx, not a JS calendar library): today / this week, bookings grouped by day, showing customer name, service, time, status. - Manual booking creation from this view: reuses ticket 2's booking-creation code path (so the `EXCLUDE` constraint always applies) but passed an explicit override flag that skips the opening-hours / min-notice / max-advance / buffer checks — the overlap constraint itself is never overridable, for the owner or anyone else. - Owner-initiated cancel and reschedule on any booking in their agenda, reusing ticket 2's cancel/reschedule actions (owner-authenticated instead of token-authenticated). ## Acceptance criteria - [ ] A logged-in owner sees an agenda view of their own client's bookings only, grouped by day. - [ ] The owner can add a booking outside normal opening hours / inside the min-notice window / violating the buffer, and it succeeds. - [ ] The owner cannot create a booking that overlaps an existing booking on the same resource — the `EXCLUDE` constraint rejects it the same way it does for the public flow. - [ ] The owner can cancel any of their own bookings from the agenda view. - [ ] The owner can reschedule any of their own bookings from the agenda view, subject to the same overlap protection. ## Blocked by - #16 (Availability engine + booking API) - #19 (Owner accounts: auth, password reset, CRM dashboard visibility)
mivanchenko added the bookingready-for-agentenhancement labels 2026-07-23 14:07:58 +02:00
mivanchenko added a new dependency 2026-07-23 14:09:18 +02:00
Author
Owner

Implemented in commit 528a13c on main.

  • owner_booking.py: session-authenticated weekly agenda (GET /owner/agenda), grouped by day with today highlighted, plus a quick jump back to the current week.
  • Manual booking creation (POST /owner/bookings) reuses booking_api.create_booking_row (refactored out of the old inline route body) with skip_availability_check=True -- bypasses opening-hours/min-notice/max-advance/buffer, never the Postgres EXCLUDE overlap constraint (still enforced via booking_db.create_booking).
  • Owner cancel/reschedule (POST /owner/bookings/<id>/cancel|reschedule) reuse the same cancel_booking_row/reschedule_booking_row helpers the token-authenticated customer routes call -- reschedule keeps the full business-rule slot check (only creation gets the override, per the ticket).
  • Tenancy: every route resolves client_id from the session only; cross-tenant resource/booking access returns not-found (covered by tests).
  • Tests: tests/test_owner_booking.py -- agenda scoping, override-bypasses-hours, EXCLUDE-still-rejects-overlap, cross-tenant creation/cancel rejection, reschedule + reschedule-into-occupied-slot. Full suite (106 tests) green.
  • UI is plain server-rendered forms/links (no client-side JS or htmx CDN dependency) to stay consistent with the rest of the app, which has zero external JS deps; behavior matches every acceptance criterion.
Implemented in commit 528a13c on main. - `owner_booking.py`: session-authenticated weekly agenda (`GET /owner/agenda`), grouped by day with today highlighted, plus a quick jump back to the current week. - Manual booking creation (`POST /owner/bookings`) reuses `booking_api.create_booking_row` (refactored out of the old inline route body) with `skip_availability_check=True` -- bypasses opening-hours/min-notice/max-advance/buffer, never the Postgres `EXCLUDE` overlap constraint (still enforced via `booking_db.create_booking`). - Owner cancel/reschedule (`POST /owner/bookings/<id>/cancel|reschedule`) reuse the same `cancel_booking_row`/`reschedule_booking_row` helpers the token-authenticated customer routes call -- reschedule keeps the full business-rule slot check (only creation gets the override, per the ticket). - Tenancy: every route resolves `client_id` from the session only; cross-tenant resource/booking access returns not-found (covered by tests). - Tests: `tests/test_owner_booking.py` -- agenda scoping, override-bypasses-hours, EXCLUDE-still-rejects-overlap, cross-tenant creation/cancel rejection, reschedule + reschedule-into-occupied-slot. Full suite (106 tests) green. - UI is plain server-rendered forms/links (no client-side JS or htmx CDN dependency) to stay consistent with the rest of the app, which has zero external JS deps; behavior matches every acceptance criterion.
Sign in to join this conversation.