Tour (Tour)
En une phrase : le road-trip planifié — l'itinéraire surprise que les voyageurs vivront jour après jour, construit par l'équipe et vendu à travers une organisation partenaire.
Rôle métier
Le tour est le produit final du volet road-trips surprise : une séquence ordonnée d'étapes, chacune offrant des activités en alternatives priorisées. C'est l'objet que les planificateurs assemblent dans le back-office, que le partenaire distribue, et dont les étapes se dévoileront progressivement au voyageur le jour J (la mécanique de révélation — cœur du produit — reste à construire).
Chaque tour est rattaché à un partenaire de vente (une organisation, quel que soit son type) : c'est le canal par lequel ce road-trip est commercialisé. Ce lien est purement commercial — il ne confère aucune visibilité particulière au partenaire (voir « Visibilité » ci-dessous). Indépendamment de ce canal, un tour peut être rattaché à une région (une organisation de type region) : le territoire auquel l'itinéraire appartient. Ce lien est facultatif et purement informatif — il ne confère aucune visibilité. Le color est un attribut d'affichage (code couleur du tour dans les interfaces de planification). departure_city et departure_city_reveal_time portent le teaser de la veille du départ (voir « Règles métier »).
Cycle de vie
pending → active → suspended
pending— en cours de planification : visible de l'équipe uniquement.active— commercialisé / jouable : c'est le seul statut que les voyageurs et les organisations voient.suspended— retiré de la circulation sans être supprimé (saison terminée, problème avec un prestataire…).
Le passage d'un statut à l'autre est un acte super-admin explicite.
Visibilité — qui voit quoi
La règle est portée par une source de vérité unique (Tour::visibleTo()) :
| Casquette | Voit |
|---|---|
| Super-admin | Tous les tours |
| Organisation | Les tours active uniquement (y compris ceux dont elle n'est pas partenaire) |
| Voyageur | Les tours active uniquement |
Hors visibilité, un tour répond « n'existe pas » (404), jamais « interdit ».
Relations métier
| Relation | Sens métier |
|---|---|
| → Organisation partenaire | Le canal de vente ; on ne peut pas supprimer une organisation qui a des tours (pas de disparition silencieuse de catalogue) |
→ Région (region_organization_id) | Le territoire d'appartenance, facultatif ; seule une organisation de type region est acceptée, et supprimer la région détache ses tours (SET NULL) |
| ← Étapes | L'itinéraire ordonné ; les étapes n'existent que dans leur tour et disparaissent avec lui |
← Codes d'activation (tour_id) | Les voyages vendus sur cet itinéraire ; le tour est choisi par le voyageur à l'activation et le lien meurt avec le code, jamais l'inverse |
| ← Journal d'audit | Création, modifications et changements de statut tracés |
Règles métier
- Seule l'équipe écrit : création, modification, suppression et changement de statut sont réservés au super-admin ; le partenaire consulte.
- L'ordre du voyage est porté par les positions des étapes (1..N contiguës) — voir Étape ; les jours et heures sont indicatifs.
- La région d'un tour doit être une organisation de type
region— la règle est portée par la validation des requêtes (même posture que le type de prestataire des activités), pas par la base. - Le voyageur choisit son tour à l'activation de son code : le catalogue lui montre nom et description des tours
active(jamais l'itinéraire — c'est une surprise), il choisit le tour et sa date de départ d'un même geste. - La liste « à emporter » se lit avant de confirmer :
GET /api/tour/{id}/things-to-bringagrège les tagsthing_to_bringdédupliqués sur les activités de toutes les étapes et de tous les plans (tri par slug), en tableau nu deTagResource. La route passe par le gatevisibleTo(hors visibilité → 404) et l'agrégat est volontairement sans étapes ni noms d'activités — l'itinéraire reste une surprise. - La ville de départ se dévoile la veille :
departure_city(zone approximative, p. ex. « Fribourg ») etdeparture_city_reveal_timeportent le teaser envoyé la veille du départ (« demain à 9h, votre première étape sera près de Fribourg ») ; le jour J, c'est lereveal_timede l'étape 1 qui donne l'adresse exacte. La convention « la veille » est fixe (pas dedays_beforeici). Le tour étant un gabarit sans dates, l'heure est une heure du jour : l'instant réel se dérive de la date de départ du voyageur (used_atdu code d'activation). Les deux champs sont facultatifs et, commesteps.reveal_time, restent de pures données — la mécanique de notification est à construire (« Questions ouvertes » du README). Le teaser n'apparaît pas dans le résumé embarqué (TourSummaryResource) : l'itinéraire reste une surprise. - La suspension n'éjecte personne : un tour
suspendeddisparaît du catalogue (plus activable), mais les voyageurs en cours de voyage gardent l'accès complet à leur itinéraire — leur accès passe par leur code, pas par la visibilité catalogue (voir Routage d'étape).

