chore: move reservations backend to proper DI

Folds the 626-line services/reservationService.ts into the DI-native
ReservationsService — byte-identical SQL, statuses, bodies, error strings
and broadcasts; the legacy file is deleted.

- reservations.mcp.ts: the 5 legacy tools (create/update/delete_reservation,
  reorder_reservations, link_hotel_accommodation) + the trip-reservations
  resource move to the decorator registry (identical names, schemas,
  annotations, error strings, broadcasts); the canWrite/canRead registration
  gates become declarative access markers. Legacy registrar and resource
  entries removed.
- reservations.bridge.ts: 9 legacy-named exports + 3 type re-exports for the
  outside-container consumers (tripService, airtrail import/sync, the
  still-legacy transit + transports registrars, transitItineraryService's
  type-only import).
- notifyBookingChange folds to the legacy (tripId, actorId) signature; the
  controller passes user.id and the plugin-host factory drops its last
  plain-function reservation import for a private method over the injected
  service (constructor unchanged).
- TripsService and BookingImportService inject ReservationsService instead of
  importing legacy functions.
- Tests: reservations.service.test.ts rewritten as a real-SQL suite
  (RESV-SVC-001..030, RES-TRAV-001..005 moved verbatim,
  RESV-BRIDGE-001..009 pinning the bridge); both e2e suites converted to the
  DI-native pattern; path mocks repointed to the bridge or constructor stubs;
  tools-reservations kept and extended with the moved resource cases.

Quirks preserved on purpose (parity first — see the follow-up fix commit):
the raw-accommodation_id metadata-sync gate, the un-transactioned
multi-statement writes, the truthy updatePositions dayId check, the
empty-string COALESCE keeps, and the TEXT accommodation_id normalization.
This commit is contained in:
jubnl
2026-07-27 19:47:01 +02:00
parent c27fc99220
commit 203d67c45f
34 changed files with 1807 additions and 1175 deletions
@@ -245,6 +245,7 @@ const reservationsStub = {
list(tid: string) { return [{ id: 1, trip_id: Number(tid), title: 'Flight' }]; },
syncBudgetOnCreate() {},
syncBudgetOnUpdate() {},
notifyBookingChange() {},
} as unknown as ReservationsService;
vi.mock('../../../src/services/journeyService', () => ({
// Consumed by the real assignments.service.ts module (loaded un-mocked as a