---
suivi: 1062
date: 2026-07-29
sujet: Diagnostic grille prix lotissement (HECTARE) vs VEFA (ENVOL)
chantier: commercialisation_grille
type: diagnostic
statut: poussé
hash: b388faf6
fichiers:
  - tools/diag/diag_grille_1062.php
  - docs/suivi/SUIVI_1062_diag_grille_prix_lotissement.md
---

## PROMPT ENVOYÉ

SUIVI #1062 — PHASE 1 diagnostic uniquement. Grille commercialisation conçue pour la VEFA
affichée telle quelle sur HECTARE (lotissement / terrains). Établir modèle de données,
rendu, modules enseigne, comparer 3 approches, recommander. Aucun fix / migration / .vue.
KPI hors sujet. SDP et CES saisis manuellement (CES = surface m² dans le modèle Robin).

## SYNTHÈSE

### A — Modèle de données

#### A1. Table porteuse
Pas la table `lots` (socle TMA / prestations, quasi vide). Les lots de grille sont dans
`lots_commerciaux` — modèle `App\Models\LotCommercial`, relation
`Programme::lotsCommerciaux()`.

Colonnes d’après migrations cumulées (vérifier en prod via le script A1) :
`id, programme_id, numero_lot, type_logement, etage, surface_habitable, surface_terrasse,
exposition, nb_stationnement, plan_fichier_path, prix_grille_ttc, regime_tva,
prix_vente_ttc, difference, statut, tma_montant_ttc, remises_ttc, agence_nom,
commission_ttc, commentaire, date_acte, date_reservation, mode_vente, deleted_at,
created_at, updated_at`.
Enfants : `lot_emplacements` (stationnement n°), `lot_annexes` (surfaces annexes),
`lot_commercial_historique`, `offres_commerciales`.

#### A2. Colonnes UI VEFA ↔ source
| Colonne UI | Source |
|---|---|
| N° Lot | `lots_commerciaux.numero_lot` |
| Type | `type_logement` |
| Étage | `etage` |
| Exposition | `exposition` |
| Surf. hab. | `surface_habitable` |
| Terrasse | `surface_terrasse` |
| Annexes | relation `annexes` (`lot_annexes`) |
| Stationnement | `emplacements` / fallback `nb_stationnement` |
| Grille TTC | `prix_grille_ttc` |
| Prix effectif TTC | accessor `prix_effectif_ttc` (promo active ou grille) |
| Prix vente TTC | `prix_vente_ttc` (figé à la réservation) |
| Différence | `difference` (et/ou calcul UI) |
| Statut | `statut` + accessor `statut_label` |
| Mode de vente | `mode_vente` + `MODE_VENTE` |
| Plan | `plan_fichier_path` |
| Actions | UI seule |

Colonnes **en dur** dans `LotsGrillePanel.vue` (~L1565–1820) — pas de config déclarative.

#### A3. Champs cibles HECTARE
| Besoin | Existe ? |
|---|---|
| Surface terrain (≠ surf. hab.) | **NON** — seul `surface_habitable` / `surface_terrasse` |
| SDP | **NON** (aucune colonne `sdp` / `surface_de_plancher`) |
| CES (surface m²) | **NON** |
| Prix grille / vente hors mention TTC | **NON** — uniquement `prix_*_ttc` + `regime_tva` |
| Migration nécessaire | **OUI** pour surface terrain + SDP + CES (+ décision HT/TTC) |

#### A4. Statuts
Enum métier code : `en_stock` \| `en_vente` \| `reserve` \| `acte` \| `annule`
(constantes `LotCommercial::*`). Libellés UI : En stock / En vente / Réservé / Acté / Annulé.
Le modèle Robin « **2 - Réservé** » n’existe **pas** en base : même jeu de codes, présentation
différente éventuelle (numérotation à trancher). Pipeline commercial figé dans le modèle.

#### A5. Volumes
Exécuter en prod : `php tools/diag/diag_grille_1062.php` (section A5).
Attendu métier : EQUILIBRE (id 13, HEC34-001) = 0 ou peu de lots ; parc ENVOL dominant.
Filtre enseigne via `programmes.enseigne_id` → `enseignes.code` (pas préfixe `code_envol`).

### B — Rendu

#### B1. Chemins
- Page : `resources/js/Pages/Programmes/Commercialisation.vue` (onglet GRILLE)
- Grille + saisie : `resources/js/Components/Commercialisation/LotsGrillePanel.vue`
- Back liste : `CommercialisationController::index` (charge tous les lots + relations)
- CRUD grille : `LotCommercialController` + trait `ManagesCommercialLotPayload`
  (whitelist L27–38 : pas de SDP/CES)

#### B2. Config colonnes existante ?
**Non** sur cet écran. Colonnes PrimeVue `Column` hardcodées. Pas de préférences colonnes.
Modules enseigne = booléen tout-ou-rien (pas un jeu de colonnes). Nomenclature / bilan :
autre logique métier, pas réutilisable telle quelle pour une grille DataTable.

#### B3. Formulaire saisie
Même composant `LotsGrillePanel.vue` (dialog création / édition inline + modal).
Champs alignés whitelist back. SDP/CES absents → saisie impossible sans migration + UI.

#### B4. Consommateurs impactés (risque)
| Surface | Usage |
|---|---|
| Bilan financier (`BilanFinancierService`) | Recettes via `prix_grille_ttc` / `prix_vente_ttc` + TVA |
| Dashboard programme | Compteurs lots par statut |
| Réservations / acquéreurs | FK `lot_commercial_id`, prix TTC |
| Appels de fonds VEFA | FK lot (module déjà off HECTARE) |
| TMA | FK lot nullable |
| Offres promo | `prix_promo_ttc` lié lot |
| Import Pegao | Extraction VEFA (surfaces hab/terrasse, prix TTC) |
| `Commercial/Index.vue`, synthèse stock | Agrégats TTC |
| Historique lots | Journal champs grille |
| Sage / Intacct | Indirect via bilan / commercialisation — ne pas casser les montants TTC ENVOL |

### C — Modules enseigne
- Stockage : JSON `enseignes.modules_actifs`
- Helper : `Enseigne::aModule($key)` / `Programme::enseigneAModule`
- #1061 **déjà sur main** (`compte_prorata`, `cie`, `nf_habitat`)
- Module `commercialisation` = on/off de la **fonctionnalité**, pas un schéma de colonnes
- Verdict C2 : **inadapté** seul pour « jeu de colonnes différent » — utile comme **garde**
  (ex. activer un mode lotissement) mais ne décrit pas les colonnes

### D — Approches

| | (1) Colonnes conditionnelles | (2) Colonnes déclaratives | (3) Composant dédié |
|---|---|---|---|
| Effort | Moyen | Élevé | Moyen-élevé |
| Risque ENVOL | Moyen (même template) | Moyen si bien isolé | **Faible** (fichier séparé) |
| Extensibilité | Faible (if enseigne) | Haute | Moyenne (N vues) |
| Saisie | Même form branché | Form généré / branché | Form dédié |

**Question de fond :** ce n’est **pas** qu’une histoire de colonnes. ENVOL = VEFA (logement,
étage, exposition, TTC, Pegao, AF, TMA). HECTARE = lotissement (terrain, SDP, CES saisis,
prix éventuellement HT). Même table `lots_commerciaux` possible **si** champs lotissement
nullable + affichage/saisie branchés par enseigne (ou type programme) — mais traiter ça comme
un simple hide/show VEFA laisserait une dette permanente (formulaires, imports, bilan TVA).

#### D1. Recommandation
1. **Court terme (lots de dev)** : option **(3) légère** ou **(1) bien bornée** —
   composant / branche `enseigne.code === 'HECTARE'` (ou module dédié
   `grille_lotissement` booléen) pour affichage + saisie, **sans toucher** au template VEFA
   par défaut → protège ENVOL.
2. **Données** : migration nullable `surface_terrain`, `sdp`, `ces` (decimal m²) sur
   `lots_commerciaux` ; prix : **trancher HT vs TTC** avant de créer des colonnes.
3. **Ne pas** abuser du seul mécanisme modules pour lister les colonnes ; un module
   `grille_lotissement` peut servir de flag d’activation, pas de schéma.
4. KPI / totaux : hors périmètre (confirmé Robin) — ne pas les refondre dans le 1er lot UI.
5. Découpage proposé :
   - Lot A : migration champs + validation store/update
   - Lot B : UI grille + formulaire HECTARE (composant dédié ou branche isolée)
   - Lot C : exports / Pegao / bilan — **seulement** si HECTARE doit entrer dans les recettes
     (sinon laisser bilan inchangé tant que 0 lots)

#### D2. Questions à trancher (Robin)
1. Prix HECTARE : **HT** ou **TTC** (ou les deux) ? Impact bilan / TVA.
2. Statut : réutiliser `en_stock|en_vente|reserve|acte` avec libellé « 2 - Réservé », ou
   autre nomenclature ?
3. Flag d’activation : `enseigne.code === 'HECTARE'` en dur, ou nouveau module admin
   `grille_lotissement` ?
4. Un lot HECTARE doit-il apparaître dans le **bilan recettes** dès le 1er lot métier ?
5. Type de logement / mode de vente : utiles en lotissement ou à masquer ?

#### D3. Risques ENVOL
- Modifier `LotsGrillePanel.vue` / whitelist / accessors TTC sans garde-fou → régression
  10 programmes VEFA, réservations, offres, Pegao, appels de fonds, bilan.
- Renommer ou « généraliser » `prix_*_ttc` → casse Sage/bilan.
- Réutiliser `surface_habitable` pour la surface terrain → sémantique fausse + exports VEFA.
- Soft-delete / unique `(programme_id, numero_lot)` : OK à conserver.

## DÉPLOIEMENT-TEST

```bash
git pull origin main
php tools/diag/diag_grille_1062.php
```

Coller les sections A1 / A3 / A4 / A5 / C du script dans le ticket.
Pas de migrate, pas de journal:sync, pas de rebuild, pas de route:clear.

## LEÇON
Une grille « unique » héritée d’un métier (VEFA) appliquée à un autre (lotissement) sans
champs ni colonnes dédiés produit un écran vide de sens : le mécanisme modules enseigne
désactive des blocs fonctionnels, mais ne décrit pas un schéma de colonnes — sans diagnostic
du modèle, on traiterait un écart de métier comme un problème d’affichage.
