Module — Dashboards & Reports
Synchronisé avec le code. Mettre à jour à chaque changement structurel.
Rôle
- Dashboards : vues live UI pour les utilisateurs back-office (Direction, mgmt) — KPIs occupation, CA, statuts.
- Reports : exports Excel / PDF à destination de la comptabilité et de la direction.
Emplacement
- Pages :
src/Web/Pages/Dashboards/,src/Web/Pages/Reports/ - Services :
DashboardService.cs,ReportService.cs - DTOs :
Application/Dtos/Dashboard/ - Frontend : ApexCharts pour les visualisations dans Razor
Entités principales
Aucune entité dédiée — agrégation cross-module sur :
Booking(volumes, CA)Occurrence(taux d'occupation)Invoice/Payment(CA réel, encaissé)Customer(segmentation)
Règles métier spécifiques
- Dashboards = données fraîches (queries directes EF + cache éventuel via
OutputCache). - Reports = exports formels (Excel via
EPPlus, PDF via Liquid+iText). Souvent paramétrés par période, type de voyage, business axis. Travel.BusinessAxisest l'un des champs de segmentation analytique CA dans les reports.- Calcul d'occupation dans les dashboards : utiliser
TravelOccupancyAndBookingStateService.CalculateOccupancyAndSetBookingStateavecincludeAllOccurrences: truequand on veut inclure les occurrences passées (statistiques historiques).
Points d'attention / pièges
- Performance : les reports peuvent agréger sur de gros volumes — préférer
IQueryable.Sum/Countcôté SQL plutôt que.ToList().Sum()en mémoire. - Filtre soft-delete : par défaut les soft-deleted sont exclus. Pour des audit reports, utiliser
IgnoreQueryFilters(). - Locale fr-CH : formats de dates et nombres dans les exports → utiliser explicitement la culture pour éviter les surprises sur des serveurs en autre locale.
- Données indicatives :
OccurrenceCostetBreakEvenPointsont indicatifs (cf.occurrence-capacity.md). Ne pas les utiliser dans des reports comptables stricts. - Taux de remplissage (
DashboardService.GetOccurrencesOccupancyData) : la carte affiche le max du taux véhicule et du taux hébergement. Toute capacité peut valoir 0 (une course d'un jour n'a pas d'hébergement) → toujours garder la division derrière un testCapacity > 0. Sans ce garde-fou,0.0/0donneNaN, et comme toute comparaison avecNaNest fausse, leNaNremportait le max et s'affichait enNaN%(corrigé juil. 2026). - Report « Taux de remplissage et capacité » (
ReportService.GetManagement) : distinguer deux colonnes passagers. « Passagers total » = occupation totale du départ (Occurrence.NumberOfPassengers, oudriveOcc.Occupancypour les lignes OneDay) — non filtrée par la plage de dates de réservation du moteur de recherche. « Passagers » = sous-ensemble réservé dans la fenêtre[BookingStartDate, BookingEndDate], compté sur les mêmes statuts que l'occupation (ValidatingBookingStatus.BookingHasImpactOnOccurrenceOccupancy= Draft/Confirmed/Billed + PendingWebOrMobile avec transaction ou en holdCreatedAt >= PendingHoldCutoff()), passagers non annulés. Les colonnes monétaires (Total confirmé/facturé/Total) sont elles aussi filtrées par date mais sur Confirmed/Billed uniquement. ⚠ L'export Excel (Export) aligne les cellules par position (pas par référence de header comme le rendu UI) : ajouter une colonne impose donc d'insérer la cellule au bon rang dans la listeCellsde chaque branche.- Colonne « CA prestations (3010/3011) » (ajoutée juil. 2026) : à côté des colonnes nettes existantes. Les colonnes
Total confirmé/Total facturé/Totalrestent le net facturé (Booking.FinalAmount, donc après rabais, commissions, bons, assurances) — ce qui faussait la comparaison avec la compta BC et le panier moyen (un bon de 3'000 sur un voyage à 3'000 → net 0 alors qu'il y a bien 1 pax et 3'000 de prestation). La nouvelle colonne = les prestations voyage/hébergement telles que BC les impute sur 3010/3011 (transport, hébergement, pension, excursions, supplément vol, supplément(s) booking, supplément global, net de la Réduction Early Booking qui est aussi postée sur 3010/3011) ; hors rabais/commissions (3902/3901/3908/3911), bons Croisitour (2062), bons cadeaux (2061), assurances (3021), points fidélité (3916/3917). Réconcilie par construction avec le solde BC des comptes 3010/3011 — pas de recalcul depuis les prix configurés.- ⚠
InvoiceItem.Accountest[NotMapped](recalculé uniquement au sync NAV, jamais persisté) : filtrer par compte sur des items relus en base renvoie donc 0. SeulsDescription,Price,FullPricesont persistés. Le helperReportService.GetPrestationAmount(booking)identifie donc les lignes hors 3010/3011 par préfixe deDescription(NonPrestationDescriptionPrefixes: « Rabais », « Utilisation Bon Croisitour », « Assurance », « Bon cadeau », « Points fidélité ») et somme leFullPricede tout le reste. Si une nouvelle catégorie de ligne hors 3010/3011 est ajoutée dansBookingService.CreateOrUpdateInvoice, penser à l'ajouter à cette liste. - Source par résa : facture Balance si elle existe (
Enabled), sinon Confirmation ;FullPrice= montant plein (indépendant du split acompte/solde). Somme les résasConfirmed+Billedde la fenêtre de dates (analogue de la colonneTotal). - ⚠ Comme les colonnes nettes existantes, une résa dont les passagers chargent sur plusieurs drives est attribuée à chaque drive touché (même sémantique que
confirmedAmount/billedAmount). Nécessite l'IncludedesInvoices.InvoiceItemsdans la requêteloadFactor.
- ⚠
- OneDay multi-lignes : le rapport produit une row par ligne (drive), et
driveOcc.Occupancyne compte que les passagers dont leLoadingStopest sur un arrêt de la ligne (le moteurCalculateDriveOccupancyignore lesLoadingStopId == null). Les passagers non rattachés à une ligne (stop null, ou stop hors des lignes actives) apparaissent donc dans une row de réconciliation « {Voyage} - Sans ligne assignée » ajoutée en fin de bloc OneDay. Son « Passagers total » est déduit par soustraction (Occurrence.NumberOfPassengers − Σ driveOcc.Occupancy, donc non filtré par date) et son « Passagers » compte les passagers sans ligne dans la fenêtre de dates. Le moteur d'occupation partagé n'est pas modifié (impact capacités/dispo ailleurs) — la correction est purement dans le rapport. Les colonnes monétaires de cette row restent vides (le CA d'une réservation est déjà compté sur sa ligne).
- Colonne « CA prestations (3010/3011) » (ajoutée juil. 2026) : à côté des colonnes nettes existantes. Les colonnes
Conventions locales
- Ajouter un nouveau report = créer une page
Pages/Reports/<Name>.cshtml(.cs)+ une méthodeReportService.GenerateXxx(filters)qui retourne unStream(Excel) ou unbyte[](PDF). - Les DTOs Dashboard sont dans
Dtos/Dashboard/(folder dédié).
Dépendances
- ← Toutes les sources de données métier (Booking, Occurrence, Invoice, Payment, Customer…).
- → consommé par : Direction (Dashboards), Comptabilité (Reports).
Contributors
No contributors
Changelog
No recent changes

