# Fiche client : onglet « Synthèse » (mini suivi commercial)

Nouvel onglet en lecture seule dans la fiche client, placé juste avant « Devis », affiché uniquement pour un client existant. Chargé en AJAX à la première ouverture de l'onglet (pas d'impact sur le temps d'ouverture de la fiche).

## Fichiers modifiés

- `app/Http/Controllers/client_controller.php` : nouvelle méthode `synthese()` (imports `Carbon`, `action`, `facture` ajoutés).
- `routes/web/client.php` : `GET client/synthese` → `client_controller::synthese()`, nommée `client.synthese` (paramètres `client_id`, `annee` optionnel).
- `resources/views/client/form.blade.php` : lien d'onglet `#nav-synthese-tab`, panneau `#synthese_client`, JS `charger_synthese()` (graphique Chart.js 2.7.3, déjà chargé par `public/inc/haut.inc.php`).

Style : les en-têtes des parties et des cartes KPI (`#synthese_client .card-header` ; le titre des KPI, auparavant un petit texte gris dans le corps de la carte, est devenu un `card-header`) reprennent celui de la pesée bascule (`pesee_bascule/form.blade.php`) : fond vert `#8cc63f`, écriture blanche en gras, padding resserré. Règle CSS dans un `<style>` local à l'onglet.

## Indicateurs

Décision : le CA est basé sur **toutes les factures**, validées en comptabilité ou non, avoirs déduits (`facture_avoir` = 1 → montant négatif). Jusqu'au 2026-10-19, seules les factures validées (`facture_validee` = 1) étaient comptées ; le filtre a été retiré pour être aligné sur les statistiques standard et la feuille KPI finance. Les factures échues et les badges d'alerte suivent la même règle. Les acomptes sont comptés à leur émission puis neutralisés par la ligne de déduction négative de la facture finale.

| Carte | Calcul |
|---|---|
| CA HT | `SUM(facture_total_ht)` signé, du 01/01 à aujourd'hui (année en cours) ou année complète (année passée), comparé à la même période N-1 avec % d'évolution |
| Volume | `facture_nb_beton` (m³) et `facture_nb_granulat` (t) des factures hors avoirs, N vs N-1. Le granulat n'est affiché que s'il est non nul |
| Encours / crédit autorisé | Encours total de l'onglet Général (`#encours_total` = factures + BL non facturés), à défaut `client_credit_encours`. Jauge sur `client_credit_autorise` : vert, orange au-delà de `client_credit_alarme`, rouge à 100 % |
| Factures échues non réglées | Factures (validées ou non) hors avoirs, `facture_reste_reglement` > 0 et `facture_echeance` < aujourd'hui (montant TTC, nombre) |
| Devis (12 derniers mois) | Taux = gagnés (`devis_etat` 1) / tranchés (1 gagné, 2 perdu, 4 abandonné) ; nombre en cours (0) |
| Dernière livraison | `MAX(bl_date_livraison)` hors BL annulés, avec nombre de jours |
| Actions commerciales | Dernière action (date ≤ aujourd'hui) et prochaine action planifiée (`t_action`) |

Graphique : CA HT mensuel, barres groupées année sélectionnée / année précédente.

Donut « Répartition du CA HT » (à droite du graphique mensuel), sur la même période que la carte CA : somme signée (avoirs en négatif) de `ligne_facture_prix_total_ht` des factures, groupée par `ligne_facture_type` : F Béton, G Granulat, D Adjuvant, J Ajout, S Service, Z Transport. Les sous-totaux (B, H), commentaires (C) et lignes vides (E) sont exclus. Les catégories à 0 ne sont pas affichées. L'infobulle donne le montant et le pourcentage. Clé `repartition` (`[{libelle, montant}]`) dans la réponse de `synthese()`.

Deux graphiques côte à côte sous le CA mensuel et le donut : **Top 5 chantiers par CA HT** et **Top 5 chantiers par volume** (barres horizontales Chart.js `horizontalBar`, libellés tronqués à 28 caractères sur l'axe et complets dans l'infobulle). Même période et mêmes lignes que le donut, groupées par `t_ligne_facture.chantier_id` (jointure sur `t_chantier`) : CA = somme signée des montants HT, volume = quantité des lignes béton (F) en m³, ou, si le client n'a aucune ligne béton sur la période, quantité des lignes granulat (G) en tonnes (`unite_volume_chantier`). Les lignes sans chantier (déductions d'acompte, lignes manuelles) sont exclues des tops. Clés `top_chantiers_ca`, `top_chantiers_volume` (`[{libelle, valeur}]`). Libellé = code chantier (espaces de complément réduits) + nom. Les colonnes de `t_facture` sont qualifiées dans la requête de base (`t_facture.client_id`…) car `t_chantier` a aussi un `client_id`.

Courbe **Prix moyen HT** (pleine largeur, sous les tops), par mois de l'année sélectionnée :
- **Béton N** (trait plein) et **Béton N-1** (pointillés) = HT signé des lignes F (avoirs en négatif) / quantité des lignes F hors avoirs, en €/m³. Si le client n'a aucune ligne béton sur N et N-1, la courbe passe en granulat (lignes G, €/t) ; clés `prix_produit`, `prix_unite`.
- **Tout compris N** (orange) = HT signé de toutes les lignes tarifées (béton, transport, services, ajouts…) / même volume.
- Un mois sans volume renvoie `null` et laisse un trou (`spanGaps: false`). Clés `prix_moyen_n`, `prix_moyen_n1`, `prix_tout_compris_n`.
- Un avoir baisse le montant du mois sans retirer de volume : une remise ou une correction de prix fait donc baisser le prix moyen, comme attendu.
- Contrôle client 2394, 2026 : béton entre 96,08 et 120,25 €/m³ (le pic d'avril à 133,81 €/m³, obtenu quand les avoirs retiraient du volume, a disparu), tout compris entre 139,84 et 209,88 €/m³.

Courbe **Volume mensuel sur 3 ans** (à droite du prix moyen) : une courbe par année (N-2 gris clair, N-1 gris, N vert et plus épaisse) superposée de janvier à décembre pour voir la saisonnalité, avec le total annuel dans la légende pour la tendance. Volume = quantité des lignes F hors avoirs (m³), ou G (t) pour un client sans béton, même règle que le prix moyen. Les mois futurs de l'année en cours sont à `null` (la courbe s'arrête au mois en cours). Clé `volume_mensuel` (`[{annee, volumes[12]}]`). La requête mensuelle du prix moyen couvre désormais N-2 à N et sert aux deux graphiques (le choix béton / granulat se fait sur ces 3 ans).

**Règle des volumes** : un volume n'est jamais négatif. Un avoir corrige un montant, il ne retire pas de volume livré : tous les volumes (carte, tops, prix moyen, volume sur 3 ans) ne comptent que les factures hors avoirs (`$volume = CASE WHEN facture_avoir = 1 THEN 0 ELSE 1 END`), alors que les montants restent signés (`$signe`). Avec cette règle, la carte (en-tête `facture_nb_beton`) et les graphiques (lignes F) donnent le même volume : 1 845,65 m³ pour le client 2394 en 2026, 615,8 m³ pour le 6237. Auparavant, les avoirs faisaient diverger les deux sources (7 avoirs du client 2394 portent 148 m³ en en-tête pour 37,6 m³ de lignes béton). Hors avoirs, seules 2 factures de toute la base ont un `facture_nb_beton` différent de leurs lignes béton.

Décision : les colonnes `t_facture.facture_montant_beton/granulat/service/transport/autre` existent mais ne sont pas alimentées (toujours 0), d'où le calcul sur les lignes. Contrôle sur le client 2394 en 2026 : Béton 190 202,79 + Transport 65 717,25 + Service 59 654,19 + Ajout 2 389,00 + Adjuvant 2 045,70 = 320 008,93 €, égal au CA de la carte. Les lignes de déduction d'acompte (type S, négatives) diminuent la part Service. Un sélecteur d'année (années ayant des factures + année en cours) recharge l'onglet.

## Détail des cartes KPI en DataTable (comme KPI finance)

Un clic sur les cartes **CA HT facturé**, **Volume facturé**, **Factures échues non réglées** ou **Devis (12 derniers mois)** ouvre une modale avec le détail en DataTable, chargé à l'ouverture, ainsi que le nombre de lignes et le total. Même fonctionnement que `kpi/finance.blade.php`.

- Route `client.synthese_detail` (`GET /client/synthese_detail`, paramètres `client_id`, `annee`, `indicateur` = `ca` | `volume` | `echu` | `devis`) → `client_controller::synthese_detail()`.
- Colonnes :
  - ca : N°, date, type (facture/avoir), chantier, montant HT signé ;
  - volume : N°, date, chantier, béton (m³), granulat (t), montant HT. Factures hors avoirs ayant un volume, lu sur l'en-tête (`facture_nb_beton` / `facture_nb_granulat`) comme la carte ;
  - echu : N°, date, échéance, jours de retard (tri par défaut), chantier, montant TTC, reste à régler TTC ;
  - devis : N°, date, état, chantier, quantité prévue, montant HT (même calcul que la fiche devis).
- Le N° de facture ouvre la facture dans un nouvel onglet (`facture_laravel.formulaire`). Le N° de devis n'est pas un lien : l'écran devis ne s'ouvre pas sur un devis donné par URL.
- Le total du détail est égal à la carte, car la période et les requêtes de base sont partagées avec `synthese()` : `periode_synthese()` (nouvelle) et `factures_echues_query()` (extraite de `factures_echues()`). Vérifié sur les clients 2394, 6237 et 4856 pour 2026 : CA, volume béton, échu (montant et nombre) et nombre de devis identiques.
- La modale `#modal_detail_synthese` est déplacée dans le `body` au chargement de la fiche (l'ancienne copie est supprimée d'abord) : `#affiche_client` a un `transform` CSS (`style.css`) qui rendrait sa position relative au cadre de la fiche. Même piège que les fenêtres de la fiche facture (§6octies d'`Architecture.md`).
- Pas de détail pour les cartes Encours, Dernière livraison et Actions commerciales : l'encours inclut les BL non facturés (calcul de l'onglet Général), et les livraisons et actions ont déjà leurs onglets.

## Test

Appel direct de `synthese()` sur le client 2394 : CA 2026 = 320 008,93 €, 1 697,65 m³, répartition mensuelle cohérente, année 2025 vide (pas de factures). Rendu dans le navigateur non testé.
