Module product-catalog (mobile)
Ce fichier doit rester synchronisé avec le code du module. À mettre à jour à chaque changement structurel.
Rôle : référentiel des « produits » attachables à un voyage (hébergements, types de chambres, assurances, véhicules, lignes/arrêts). Le mobile en a besoin pendant le wizard de réservation pour proposer les choix et calculer les prix. Aligné sur le module backend Horizon product-catalog.
Code
- Store :
stores/catalog.ts(useCatalogStore)- Indexé par
travelId(cache par voyage :loadedTravels,loadingTravels) - Maps :
lines,stops,roomTypeCategories,accommodations,roomTypes,insurances,vehicles - L'option « Aucune assurance » est une
Insuranceréellevalue 0fournie par le backend danscatalog.insurances(plus de constante synthétique côté front depuis que la pension/assurance démarrent vierges — cf.business-rules.md). seasideCategories(TravelCategory[]) : destinations balnéaires (données de référence quasi-statiques). Préchargé une fois au cold start viauseCatalogStore(pinia).fetchSeasideCategories()appelé dansmain.tsjuste aprèsapp.use(pinia)(fire-and-forget) — donc une fois par (re)chargement de l'app, garanti même si aucun composant ne touche le store ; l'endpoint est lui-même LRU-caché 30 min. Erreur réseau logguée vialogError(_, 'catalog'), ne bloque pas le démarrage. Les boutons deSeasideInterestsFilterBarcorrespondent à ces catégories (noms et icônes hardcodés pour l'instant — icônes SVG inline<InlineSVG :src="/svg-icons/...">à la place des anciens drapeauxflag-icons, même pattern queInterestsFilterBar: recoloration à la sélection viacurrentColor) ; le filtre envoyé au backend est?seasideCategoryName=Baln {NOM}(cf.travel-catalog.md).
- Indexé par
- Components :
cards/AccommodationPreview.vue,travel-booking/TBStepAccommodation*.vue,travel-booking/TBStepDepartureLocation.vue - API :
publicApi.travels.getCatalog(travelId)→TravelCatalog(lines, roomTypeCategories, accommodations, insurances, vehicles),publicApi.travels.getSeasideCategories()→TravelCategory[] - Utils :
accommodation-optimizer.ts—parseDaysAccommodations(travel): algo greedy Set Cover pour grouper les jours d'un voyage par hôtel (NP-Hard, approximation suffisante < 30 jours / < 10 hôtels)meal-plans.ts— pensions (MealPlanenum)room-keys.ts— sérialise(roomTypeId, roomId, optionId)en clé stable pour les Maps du wizardage-tiers.ts— calcul duPassengerType(Adult/Junior/Child/Baby) selon l'âge et les seuils de l'Accommodationou duTravel
Entités principales
Accommodation(api_Accommodation) — hôtel/logement. PorteChildMin/Max,JuniorMin/Max,AdultMin(seuils d'âge),MealPlanpar défaut,internal(true = négocié Buchard, sinon externe → ignoré par l'optimizer).RoomType,RoomTypeCategory,Room,Option(RoomTypeOption)SettingInsurance(aliasCatalogInsurance) — assurance avecpriceStart/priceEnd(tranche de prix par personne) etstartDate/endDate(validité)Vehicle,SeatLine,Drive,Stop
Invariants & règles spécifiques
- Accommodation optimizer :
parseDaysAccommodations()ignore les hôtels externes (internal: false). Les jours sans hôtel ne sont dans aucun groupe. PourSeaside, court-circuit : un seul hôteltravel.accommodationcouvre 100% des jours. - Filtrage des assurances (
getInsurancesForPricePerPerson) : double critère- prix par personne dans
[priceStart, priceEnd] - date de l'occurrence (
selectedTO.start) dans[startDate, endDate]de l'assurance Tri descendant parvalue.
- prix par personne dans
requiresMealPlan:trueuniquement quand le voyage estSeasideET a uneaccommodation. Le vol-sec Seaside (sans hôtel) ne demande pas de pension.- Catalog chargé une fois par travelId : le store dédoublonne les appels concurrents via
loadingTravels.
Dépendances
- Dépend de :
travel-catalog(chargé à partir d'untravelId) - Consommé par :
booking(le wizard pioche tout le catalog ici),billing-payment(insurances pour le pricing)
Points d'attention
- Toujours utiliser
parseRoomKey()/ les helpers deroom-keys.tspour manipuler les clés composites — ne pas concaténer à la main. - Les
vehiclesdu catalog représentent les modèles de véhicule (capacité, plan de sièges) ; ne pas confondre avec l'Occurrence.vehiclesou leSeasideDate.Vehiclescôté Horizon qui sont des affectations datées. - Le plan de sièges du wizard (
TBSeatMap.vue) ne litcatalog.vehiclesque pour les voyages single-day et Seaside. Pour les voyages multi-day (hors Seaside), il lit désormaisbookingConstructor.vehicles— sourcé de l'affectation réelle de l'occurrence, pas du modèle générique du catalog, car la capacité/le plan de sièges peuvent différer par date. Pas viaselectedTO.vehicles(bug backend surGET /occurrences/:id, renvoie une liste de véhicules vide) : la donnée fiable esttravel.occurrences[].vehicles, chargée viaGET /travel/sluget retrouvée par id d'occurrence — cf.occurrence-capacity.md.catalog.getSeat/catalog.seatsont été supprimés (seulcatalog.vehiclessubsiste, pour ce fallback single-day/Seaside) — la résolution numéro-de-siège passe désormais parbookingConstructor.getSeatsForPassenger.
Contributors
No contributors
Changelog
No recent changes

