---
suivi: 1177
date: 2026-08-04
sujet: Résumé programme — carte recette + alertes commerciales
chantier: commercialisation
type: feature
statut: poussé
hash: b7c10f7f
fichiers:
  - resources/js/Pages/Programmes/Dashboard.vue (~29 Ko, 677 lignes)
  - app/Http/Controllers/ProgrammeDashboardController.php
  - app/Support/Commercial/ProgrammeResumeCommercialBuilder.php
  - resources/js/Components/Programmes/AcquereursGrillePanel.vue
  - tests/Unit/ProgrammeResumeCommercial1177Test.php
  - database/data/journal_mises_a_jour_post_2026_06_12.php
  - public/build/ (Dashboard-zkaJM_aU.js · Tma-kroEw6D0.js)
  - docs/suivi/SUIVI_1177_resume_commercial_recette_alertes.md
---

## PROMPT ENVOYÉ

SUIVI #1177 — sur le RÉSUMÉ programme (pas LotsGrillePanel / AcquereursGrillePanel) :
max 2 cartes (Recette + Alertes), cliquables avec filtre pré-appliqué, TTC/HT
étiquetés, anti-silence #1043, réutiliser RemisesAccordeesCalculator +
AcquereursProchaineEcheance. Affichage seul.

## SYNTHÈSE

### Fiches lues
- `SUIVI_1172` / `SUIVI_1176` — chaîne échéances, alertes, filtres En retard /
  Avec alerte. Approche : **réutiliser** `AcquereursProchaineEcheance`, deep-link
  `?filtre=` vers la grille Acquéreurs.
- `SUIVI_1168` — pivot `reservation_lots.prix_vente_ttc` + RemisesAccordeesCalculator.

### Fichier modifié (chemin + taille)
`resources/js/Pages/Programmes/Dashboard.vue` — **~29 162 octets**, **677 lignes**
(avant ~21,7 Ko / 511 lignes). Monté par `GET /programmes/{id}` →
`ProgrammeDashboardController::show` (Inertia `Programmes/Dashboard`).

### Cartes
1. **Commercial · recette** (si `enseigneAModule('commercialisation')` +
   `commercialisation.lecture`) : CA réservé/acté TTC · CA potentiel TTC ·
   Remises TTC · AF à émettre TTC (si `programmes.appels_de_fonds.lecture`).
2. **Alertes du programme** : uniquement lignes count > 0 ; carte absente si vide.
   Indisponibilité de calcul → bandeau « indisponible », jamais 0 inventé.

### Requêtes ajoutées (par indicateur)
| KPI | Requête |
|-----|---------|
| CA réservé+acté | 1× `SUM(reservation_lots.prix_vente_ttc)` JOIN résa/lots |
| CA potentiel | 1× `SUM(lots_commerciaux.prix_grille_ttc)` hors annulé |
| Remises | 1× lots reserve/acte + eager reservations / pivot → `RemisesAccordeesCalculator::total` |
| AF à émettre | 1× `appels_fonds` (a_emettre) COUNT+SUM + 1× `appels_de_fonds` (brouillon) COUNT+SUM |
| Alertes | 1× reservations en_cours/acte + eager contact/notaire ; urgence en mémoire |

Total ajouté ≈ **6–8 requêtes** (eager inclus), **pas de N+1** ligne à ligne.
Temps : champ `ms` dans le payload ; MariaDB locale indisponible → mesurer en prod
via `commercial_recette.ms` / `commercial_alertes.ms` (attendu < quelques centaines ms
sur 61 réservations / 107 lots).

### Services réutilisés (aucune formule dupliquée)
- `RemisesAccordeesCalculator::total` (pas de 3ᵉ implémentation)
- `AcquereursProchaineEcheance::forReservation` + `alertesStatutSru`
- AF : somme **legacy + Intacct** (tables non fusionnées) — dit dans ce livrable

### Indisponibilité vs zéro réel
- `disponible: false` → bandeau rose « Calcul/Alertes indisponible » ; montants `null`
- `disponible: true` + `0,00 €` → vrai zéro (ex. 0 lot acté, 0 AF) formaté en euros

### Deep-links filtres (#1176 + #1177)
`/tmas?filtre=retard|alerte|sans_notaire|sru_incoherent|date_acte#grille`

## DÉPLOIEMENT-TEST

1. `git pull origin main` ; `optimize:clear` ; `view:clear` ; `journal:sync`
2. LES TRITONS : vérifier 4 KPIs TTC, alertes LACROUX/CARLIER, clics filtres
3. `diag_remises_kpi_1168.php` → 107 304,48 € ; `commercial:coherence-reservation-lots` → 0
4. Programme HECTARE lotissement : carte OK ; AF masqué sans permission
5. Smoke : carte absente si 0 alerte ; simuler panne → « indisponible »

## LEÇON

Le résumé ne montrait que la **dépense** (HT) — le promoteur a besoin de la **recette**
(TTC) à côté, étiquetée, sans convertir. Un indicateur non cliquable est de la
décoration. Zéro crédible après catch = #1043.
