Skip to content

Vues BI (bi.*) — contrat de données avec un partenaire externe

Ce que c'est

La base Horizon expose un schéma bi de 27 vues en lecture, consommées par un partenaire externe (outil de reporting / BI côté Buchard). C'est un contrat de données : toute modification d'une colonne exposée est un breaking change pour ce partenaire, qui doit être prévenu avant la mise en prod.

Les vues ne sont pas gérées par EF Core : elles vivent uniquement en base (pas de migration, pas de fichier dans le repo). Elles n'apparaissent donc dans aucun diff — d'où la règle de notification du CLAUDE.md (section « Vues BI »).

Points structurants

  • Aucune vue n'utilise SELECT * : toutes listent explicitement leurs colonnes.
    • Conséquence 1 : ajouter un champ à une table ne casse rien, mais le partenaire ne le voit pas. Si le champ l'intéresse, il faut modifier la vue (ALTER VIEW) — décision à prendre avec lui.
    • Conséquence 2 : renommer ou supprimer une colonne listée casse la vue à l'exécution (Invalid column name), silencieusement jusqu'à la première requête du partenaire.
  • Filtrage volontaire de données sensibles : bi.BookingPassengers commente explicitement IBAN et MedicalCertificate dans sa définition. Ne jamais les réintroduire sans arbitrage.
  • Aucune vue ne filtre IsDeleted : les soft-deletes sont exposés tels quels, avec la colonne IsDeleted quand elle existe. Le filtrage est à la charge du partenaire.

Correspondance vue → table(s) dbo

Le nom de la vue correspond à la table sous-jacente sauf dans ces 3 cas :

VueTable(s) source
bi.DriveOccurrencedbo.OneDayTravelDriveOccurrences
bi.Stopsdbo.DriveStops jointe à dbo.Stops (colonnes des deux)
bi.CustomerSubscriptionsdbo.CustomerSubscriptions jointe à dbo.Subscriptions (pour Name)

Les 24 autres sont un simple SELECT <colonnes> FROM dbo.<MêmeNom> : Accommodations, BookingPassengers, Bookings, Customers, Drives, InvoiceItems, Invoices, Lines, OccurrenceCosts, OccurrenceCostVariousCosts, Occurrences, OccurrenceVehicles, Passengers, TravelCategories, TravelDayAccommodations, TravelDays, TravelDayVehicles, TravelLines, TravelOccurrences, TravelRanges, Travels, TravelTravelRange, Vehicles, VehicleTypes.

Tables dbo sous surveillance

Toute modification de colonne sur l'une de ces tables déclenche la notification :

Accommodations, BookingPassengers, Bookings, Customers, CustomerSubscriptions, DriveStops, Drives, InvoiceItems, Invoices, Lines, OccurrenceCosts, OccurrenceCostVariousCosts, Occurrences, OccurrenceVehicles, OneDayTravelDriveOccurrences, Passengers, Stops, Subscriptions, TravelCategories, TravelDayAccommodations, TravelDays, TravelDayVehicles, TravelLines, TravelOccurrences, TravelRanges, Travels, TravelTravelRange, Vehicles, VehicleTypes.

Pièges connus

  • bi.Travels expose Capacity, CapacityMax, CapacityTotal, CapacityVehicle, CapacityAccommodation et LoadingLineId — champs dépréciés côté Horizon (cf. règles immuables 4 et 5 du CLAUDE.md). On ne les utilise plus, mais on ne peut pas les supprimer sans casser le partenaire.
  • bi.Customers expose les 5 colonnes ClubMembership* / DoNotRenewMembership : les anomalies de données Club (dates epoch 1970, doubles facturations) sont donc visibles côté partenaire.
  • bi.Occurrences expose [End] et Start — mots réservés, toujours entre crochets dans la vue.
  • Les colonnes listées plus bas sont un instantané au 31.08.2026. Pour l'état réel, interroger la base plutôt que de faire confiance à ce fichier.

Vérifier l'état réel des vues

bash
# Colonnes exposées par vue
sqlcmd -S localhost,1433 -U sa -P 'Password12!' -d Horizon -C -y 0 -Y 0 -i requete.sql
# requete.sql :
#   SET QUOTED_IDENTIFIER ON;
#   SELECT v.name + ' | ' + STUFF((SELECT ', ' + c.name FROM sys.columns c
#     WHERE c.object_id = v.object_id ORDER BY c.column_id FOR XML PATH(''), TYPE).value('.','nvarchar(max)'),1,2,'')
#   FROM sys.views v JOIN sys.schemas s ON s.schema_id = v.schema_id WHERE s.name = 'bi' ORDER BY v.name;

# Définition SQL complète d'une vue
#   SELECT definition FROM sys.sql_modules WHERE object_id = OBJECT_ID('bi.Bookings');

Colonnes exposées (instantané 31.08.2026)

VueColonnes exposées
AccommodationsAdultMax, AdultMin, AllInclusive, AllInclusivePrice, Breakfast, BreakfastPrice, ChildMax, ChildMin, ContactId, CreatedAt, Currency, DeletedAt, Description, ExternalId, ExtraChargeAdult, ExtraChargeAdultType, ExtraChargeChild, ExtraChargeChildType, ExtraChargeJunior, ExtraChargeJuniorType, FullBoard, FullBoardPrice, GlobeId, HalfBoard, HalfBoardPrice, Id, Internal, IsDeleted, JuniorMax, JuniorMin, MealPlan, Name, ProgramBoard, ProgramBoardPrice, Ranking, SearchData, SupplierId, TouristTax, TourOperatorId, Type, UpdatedAt
BookingPassengersBookingId, CancellationDate, CancellationFees, CancellationInsuranceId, Cancelled, LoadingStopId, LoadingTimetableStopId, MealPlan, PassengerId, Price, TripType, UnloadingStopId, UnloadingTimetableStopId
BookingsAmount, BookingDate, CancellationAction, CancellationDate, ConfirmationDate, CreatedAt, CustomerId, CustomerIncludeInBooking, DeletedAt, FinalAmount, GlobeId, Id, IsDeleted, Legacy, Number, NumberOfPassengers, Origin, SellerId, Status, TravelOccurrenceId, UpdatedAt
CustomersAddress, BadPayer, Birthdate, City, Civility, Company, CreatedAt, Discount, DiscountType, EMail, Enabled, FirstName, FullName, Gender, GlobeId, Id, IsGroup, Name, NavNo, Newsletter, NoEMail, NoMobile, Phone, State, TravelBan, Type, UpdatedAt, Zip, ClubMembershipType, ClubMembershipCode, ClubMembershipStart, ClubMembershipEnd, DoNotRenewMembership
CustomerSubscriptionsCustomerId, SubscriptionId, Name (← Subscriptions.Name), Enabled
DriveOccurrenceId, DriveId, OccurrenceId, Quota, IsDeleted
DrivesCreatedAt, DeletedAt, Distance, Id, IsDeleted, IsOneShot, LineId, Name, RoundTrip, UpdatedAt
InvoiceItemsDescription, Id, InvoiceId, Price
InvoicesBookingId, BusinessAxis, Category, CreatedAt, CustomerId, Date, DueDate, Enabled, GiftId, Id, NavNo, Number, Total, Type, UpdatedAt, UserId, VatGroup
LinesCreatedAt, DeletedAt, Id, IsDeleted, Name, UpdatedAt
OccurrenceCostsId, FlightIncluded, Flight, FlightCurrency, FlightCostPerCustomer, CruiseIncluded, Cruise, CruiseCurrency, CruiseCostPerCustomer, TourOperatorMin, TourOperatorMax, TourOperatorCurrency, VatType
OccurrenceCostVariousCostsId, OccurrenceCostId, Name, Amount, Currency, PerCustomer
OccurrencesBilled, BreakEvenPoint, CreatedAt, DeletedAt, End, ExpectedPassengers, GlobeId, Id, IsDeleted, LoadingTableBackId, LoadingTableId, MinutesForADayOfWork, NavNo, OccurrenceCostId, SellingPrice, SellingPriceChild, SellingPriceJunior, SettingGeneralId, Start, Status, UpdatedAt
OccurrenceVehiclesId, OccurrenceId, VehicleId
PassengersBirthdate, CustomerId, Firstname, Id, Name
StopsId (DriveStops.Id), DriveId, Place, Locality, Lat, Long (← Stops), Order, State, CreatedAt, DeletedAt, IsDeleted, UpdatedAt, OccurrenceId, Before, Transfer, StopId
TravelCategoriesCreatedAt, DeletedAt, Id, IsDeleted, Name, UpdatedAt
TravelDayAccommodationsId, TravelDayId, AccommodationId, Main
TravelDaysId, TravelId, TourOperator, Name, Description, Distance
TravelDayVehiclesDisplayOnWebsite, Distance, EmptyReturn, FlightOrFerry, Id, JourneyEnd, JourneyStart, TourOperator, TravelDayId, VehicleId
TravelLinesLineId, TravelId, IsUnloading
TravelOccurrencesCreatedAt, DeletedAt, Id, IsDeleted, IsPriority, OccurrenceId, TravelId, UpdatedAt
TravelRangesCreatedAt, DeletedAt, Id, IsDeleted, Name, UpdatedAt
TravelsAccommodationId, BusinessAxis, Capacity, CapacityAccommodation, CapacityMax, CapacityTotal, CapacityVehicle, CategoryId, CountryId, CreatedAt, DeletedAt, DistanceLoading, DistanceUnloading, Duration, EarlyBooking, EarlyBookingDate, EarlyBookingValue, FlightOnly, GlobeId, Id, IsDeleted, Legacy, LoadingLineId, MainTravelRangeId, Name, NoVehiclePlan, OccurrenceRelatedTravel, Progress, Slug, StageProgressValueId, Status, TravelParentId, Type, UnloadingLineId, UpdatedAt, VehicleId
TravelTravelRangeTravelRangesId, TravelsId
VehiclesCapacity, CostByKm, CreatedAt, DeletedAt, DepreciationChargesPerDay, GlobeId, Id, Internal, IsDeleted, Name, NoCapacity, NumberOfDecker, NumberOfVehicle, TypeId, UpdatedAt, Vip
VehicleTypesId, Name

Contributors

No contributors

Changelog

No recent changes