Skip to content

Module occurrence-capacity (mobile)

Ce fichier doit rester synchronisé avec le code du module. À mettre à jour à chaque changement structurel.

Rôle : fournir au mobile les dates de départ concrètes d'un voyage et leur capacité résiduelle (chambres, sièges véhicule). Aligné sur occurrence-capacity backend Horizon.

Code

  • Store : stores/occurrence.ts (cache des occurrences chargées + occupation véhicule)
  • Components :
    • travel-booking/TBStepDepartureDate.vue — sélection de la date
    • travel-booking/TBStepSeatSelection.vue + TBSeatMap.vue — plan véhicule
    • cards/UpcomingDeparturesCard.vue, TravelOccurrenceRow.vue — affichage
  • API : publicApi.occurrences.{getById,getUpcoming,getRoomTypeAvailability,getVehicleOccupancy}

Entités principales

  • OccurrenceSummary — type renvoyé aussi bien par getUpcoming (liste/cards) que par getById/fetchOccurrence (occurrence sélectionnée, peuple selectedTO) : il n'existe pas de type « Occurrence complète » distinct côté @spektrum/horizon-types. Porte drives, stops, vehicles (affectation datée, cf. « Points d'attention »), vehicleCapacity/vehicleOccupancy (agrégats), start, end, bookingState, etc. ⚠️ Le champ vehicles de selectedTO (issu de getById, donc GET /occurrences/:id) est peuplé vide côté backend (bug confirmé) — ne pas s'y fier, voir « Points d'attention ». ⚠️ vehicleCapacityReturn (mentionné en business rule pour Seaside aller/retour) n'existe pas dans @spektrum/horizon-types@1.9.0 ni en extension locale (types/extensions.ts) — à vérifier sur le wire / à augmenter localement avant de s'y fier en code (même pattern que isFlatRatePerPerson).
  • RoomTypeAvailability — disponibilité par type de chambre pour une occurrence
  • Seat (alias api_vehicle_Seat) — siège occupé/dispo dans le plan véhicule

Invariants & règles spécifiques

  • Édition d'un booking existant : getVehicleOccupancy(occurrenceId, currentBookingId) exclut les sièges du booking en cours d'édition de la carte d'occupation, sinon l'utilisateur ne pourrait pas resélectionner ses propres sièges.
  • Seaside — deux capacités séparées : VehicleCapacity (aller) et VehicleCapacityReturn (retour). Un client Seaside peut partir à la date X et revenir à Y/Z (séjour 2 ou 3 semaines).
  • bookingState : porté soit par l'occurrence sélectionnée, soit en fallback par le voyage lui-même (travel.bookingState). Gouverne si l'occurrence est réservable ou en liste d'attente.
  • Sélection d'une occurrence dans le wizard déclenche en parallèle :
    1. fetchOccurrence(id) pour peupler selectedTO
    2. fetchVehicleOccupancy(id) pour la map des sièges Et reset les rooms/passengers/seats précédents.
  • Source du plan de sièges = catalog vs occurrence, selon le type de voyage : bookingConstructor.vehicles (exposé par useBCVehicle, consommé par TBSeatMap.vue) vaut l'affectation véhicule réelle de l'occurrence sélectionnée pour les voyages multi-day hors Seaside, et retombe sur catalog.vehicles (modèle générique) pour single-day et Seaside — même bascule que stopOptions (isSeaside / isSingleDay / sinon). Raison : la capacité et le plan de sièges peuvent différer par date, et l'occupation (vehicleOccupancy, matché par seat.id) est déjà par-occurrence — un mismatch d'id catalog/occurrence pouvait faire passer des sièges occupés pour libres. Seaside garde le catalog car son affectation datée vit sur un champ distinct (SeasideDate.Vehicles), pas Occurrence.vehicles. Pas lu depuis selectedTO.vehicles (bug backend, GET /occurrences/:id renvoie une liste de véhicules vide) : useBCVehicle retrouve l'occurrence dans travel.value.occurrences (chargé via GET /travel/slug, fiable) par id, et lit .vehicles dessus — même contournement, pour la même raison, que singleDayDrives/lines un peu plus haut dans le même composable (bug backend équivalent sur les quotas/occupancy des drives).
  • TBSeatMap.vue doit re-synchroniser selectedDeckId à chaque changement de vehicles (watch(vehicleDeckSelection, ..., { immediate: true })), pas seulement au premier montage : pour les voyages multi-day, le véhicule/pont affiché dépend maintenant de l'occurrence sélectionnée, qui peut changer en cours de session (navigation par pastilles, wizard <KeepAlive> sur toute la session) sans remonter le composant.

Dépendances

  • Dépend de : travel-catalog (l'occurrence appartient à un Travel)
  • Consommé par : booking (wizard), travel-catalog (affichage UpcomingDepartures)

Points d'attention

  • getById peut renvoyer {} (objet vide) — code traite ça comme « pas trouvé » et reset le selectedTO. Conserver ce comportement.
  • Les sièges sont stockés par siège, pas par passager — le mapping passenger ↔ siège vit dans bookingConstructor via le composable useBCVehicle.
  • selectedTO.vehicles (getById) ne pas utiliser — vide côté backend. Toujours passer par travel.value.occurrences.find(occ => occ.id === selectedTO.value?.id)?.vehicles (voir occurrenceVehicles dans useBCVehicle). Si ce bug backend est corrigé un jour, ce contournement (et celui, identique, de singleDayDrives/lines) pourra être simplifié — mais vérifier d'abord que GET /occurrences/:id renvoie bien les véhicules avant de le faire.

Contributors

No contributors

Changelog

No recent changes