Ad-hoc resource blocking
- "The laser is being serviced this afternoon" is a specific range, not a change
to the resource's working pattern. It stays separate from calendar exceptions
and the modal says which is which — merging them means either an afternoon's
closure lives in the calendar forever, or a change to working hours vanishes
with one click
- Blocking a range that already holds an appointment is refused with 409 rather
than silently taking capacity back; the appointment is still there and someone
has to decide about it first
- Deleting an occupancy that belongs to an appointment is refused too, otherwise
a patient's booking would quietly lose its resource with no record
409 on hold now recovers
Saying "someone just took it" is not enough — the operator would have to search
again by hand. The page drops the stale selection and refetches, so alternatives
are on screen immediately.
Flake, second half
The earlier fix only covered createUser's retry path. Any test that trips a
unique constraint closes the EntityManager, and the next test inherits the same
closed instance from the container. setUp now resets the registry when it finds
a closed manager, so a test's starting state no longer depends on how the
previous one failed.
Three consecutive full runs green: 1340 tests.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The engine from tasks 06 and 07 could find slots and hold them, but nothing in
the panel could actually book one.
- Search, hold, confirm stay three separate steps because they are three
separate states: between seeing a slot and taking it the seat is still open,
and between taking and confirming there is a deadline
- HoldCountdown reads the server's expires_at rather than starting its own
timer at render: browser clock skew and network latency both cost seconds,
and those seconds are exactly where a hold is lost. It turns urgent under a
minute and tells the parent the moment it lapses
- Per-role resource swap offers only the resources the engine returned for that
same slot. Listing every resource in the branch would let an operator pick
one that was never free and collect a 409
- An empty result is not an error: the reason code renders as a sentence
saying what to change
- Confirm requires a doctor and stays disabled until one is chosen — the
endpoint rejects it anyway, and finding that out after the hold clock has
been running is the wrong time
Reached from the appointments page as a separate action rather than folded into
the existing form: its search comes from the intersection of resource
calendars, not from one doctor's slots, and merging the two would confuse both.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>