The product owner scoped the booking model down to resources, services and
service options; everything else goes. Deleted, with their tables, tests, panel
pages and API routes:
src/Policy 27 files policy engine, simulation, templates
src/Package 13 files packages and the credit ledger
src/Course 14 files treatment protocols and courses
src/Cancellation + src/Waitlist 19 files penalties, no-shows, waitlist
src/Report + src/Shared/Event events outbox and the two reports
The surviving code had hooks into all of them, so this is not only deletion:
- AppointmentPlanBuilder loses the timing and resource policy passes, and the
requirement-from-policy builder that had no other caller (449 → 379 lines)
- PricingEngine loses policy discounts and package coverage; PriceQuote loses
its package fields and quote() its patient argument, which existed only to
find a usable package
- BookingService no longer consumes credit, unlinks course sessions or emits
events; HoldService and ResourceBlockController stop emitting too
- ServiceSelectionValidator keeps groups and relations, drops the policy layer
- the appointment loses its course_session link
Cancelling an appointment still works and still records who and why — it moves
through PATCH /api/v1/appointment/{uuid}/status. What it no longer does is
compute a penalty, so the panel dialog is a plain confirm now. That is the
visible cost of this change and it is intended, not an oversight.
The drop migration uses DROP TABLE IF EXISTS with foreign-key checks off: a
half-applied earlier run left some tables already gone, and a migration that
only works from a pristine schema is a trap on any environment that was
interrupted. messenger_messages is deliberately left alone — it is Symfony's,
not ours.
Suite green at 1258 tests, slot-mode-frozen green, phpstan back to its 14-error
baseline after removing two now-unused members it caught, tsc clean, and
app:seed-scenarios still builds all three environments.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>