Issue #3614505: The held overlay outlives the basket, so a day full of the visitor's own past booking looks bookable and refuses on submit

The overlay cookie is refreshed on any request that changes a booking. That is enough while the visitor drives every state change themselves. It stops being enough once a workflow does: an order confirmed in a workflow or a cron request leaves the visitor's browser holding an overlay for places they no longer hold, and the client cannot expire that overlay on its own, because a workflow takes the holds off the clock and the cookie then carries no deadline to expire by.

The result is the reported bug: a day whose only remaining place is the visitor's own finished booking is drawn as theirs rather than as full, invites a click, and the engine refuses the hold on submit.

The fix is one line plus its reasoning. Drawing a booking surface flags the request for a refresh, so the overlay is re-derived rather than trusted. Nothing new is needed to decide the answer: HeldCookie::value() already starts from BookingCart::current(), which withholds an order once it leaves pending, so for a basket that has moved on the projection is NULL and the response subscriber clears the cookie.

It also covers the "at a minimum, correct it on error" case for free: a refused hold re-renders the page, a re-render is a draw, so the overlay is corrected at exactly the moment the server has proved it wrong.

Coverage: a new kernel test, HeldOverlayRefreshTest, asserts both directions. A basket moved to completed loses its overlay on the next draw (empty value, expiry in the past), and an open basket keeps its overlay with the right quantity, so re-asking never costs a live basket the shading it needs. Both were run against the unfixed code first and fail there.

Verified locally: phpcs (Drupal, DrupalPractice, warnings on), phpstan with the drupal ruleset, cspell, and the yoyaku_calendar kernel suite.

Merge request reports

Loading
Loading