---
suivi: 1569
date: 2026-09-16
sujet: Parcelle — statut entièrement déduit
chantier: foncier / parcelles
type: feature
statut: poussé
hash: e86c79da
fichiers:
  - app/Support/Foncier/FoncierReferentiels.php
  - app/Services/Foncier/ParcelleStatutService.php
  - app/Console/Commands/FoncierRecalculStatutsCommand.php
  - database/migrations/2026_09_16_140000_add_statut_to_parcelles.php
  - app/Models/Parcelle.php
  - app/Http/Controllers/Foncier/ParcelleController.php
  - app/Http/Controllers/Foncier/ProspectionController.php
  - app/Services/Foncier/ParcelleProspectionQuery.php
  - resources/js/Pages/Foncier/Parcelles/Show.vue
  - resources/js/Pages/Foncier/Prospection/Index.vue
  - tests/Unit/Parcelle1569SourceTest.php
  - app/Support/Foncier/Alertes/Types/PromesseParcelleCoherenceType.php
  - public/build/
  - docs/suivi/SUIVI_1569_statut_deduit_parcelle.md
---

# SUIVI #1569 — Statut déduit de la parcelle

## PROMPT ENVOYÉ

Remplacer `parcelles.etat_foncier` saisi (14 valeurs mélangeant
avancement et destination) par un `statut` entièrement déduit de
faits ERP. Exception : case « Sans issue ». Rebase sur main contenant
#1568. Ne pas supprimer `etat_foncier` / `type_foncier`. Ne pas
toucher destination (#1568) ni responsable (#1567).

## FICHES LUES

- **#1568 LEÇON** — destination = intention saisie ; `opportunite` n’est
  pas une destination. Impact : ne pas retoucher `destination` ; le
  filtre Type foncier disparaît (remplacé par Destination).
- **#1564 LEÇON** — `applyServerDefaults` sans flag écrasait l’état des
  filles. Impact : plus de saisie d’état à la division ; le statut des
  filles est déduit après création.
- **#1563** — patron `occupation_absente_at` / `_par_id`. Impact :
  `sans_issue_at` / `sans_issue_par_id` même schéma.
- **#1561** — `vendue_client` était un état saisi. Impact : plus de
  saisie ; `cedee` n’est pas produit (pas d’acte de cession).
- **#1533 LEÇON** — liste = `Prospection/Index.vue` ; filtres SQL.
  Impact : filtre Statut en SQL sur `parcelles.statut`.

## SOURCES RETENUES (phase préalable)

| Statut | Source | Citation | Produit ? |
|---|---|---|---|
| En négociation | `offres_foncieres` + pivot `offre_parcelle` (toute offre, y compris refusée) | `app/Models/OffreFonciere.php:191` ; `ParcelleStatutService.php:219` | oui |
| Explorée | `dossiers_fonciers.statut` ∈ {terminee, annulee} = clos ; {en_cours, en_veille} = vivant | `FoncierReferentiels.php:337-351` ; `ParcelleStatutService.php:230-256` | oui |
| Cédée | Aucun acte de vente / cession / rétrocession. `actes_fonciers` = acquisition uniquement (société acquéreuse, date, prix). `vendue_client` était un état saisi, pas un fait. | `database/migrations/2026_07_30_170200_create_actes_fonciers_table.php:18-37` | **NON** |
| Détenue | `parcelles.societe_detentrice_id` NOT NULL | `ParcelleStatutService.php:203` | oui |
| Sous compromis | `promesses.statut = signe` + pivot `promesse_parcelle` | `ParcelleStatutService.php:206-209` | oui |
| Remplacée | `parcelles.statut_cadastral = remplacee` | `ParcelleStatutService.php:202` | oui |
| Sans issue | `parcelles.sans_issue_at` (saisi) | `ParcelleStatutService.php:201` | oui |

`ParcelleEtatAvancement` : logique absorbée dans `ParcelleStatutService::deduire` (`:145`) ; classe supprimée. `ParcelleEtatTransitionService` subsiste comme mince wrapper promesse → `recalculerIds` (appels existants inchangés).

## POINTS DE RECALCUL BRANCHÉS

- Périmètre dossier attacher : `DossierFoncierPerimetreService.php:144`
- Périmètre dossier retirer : `DossierFoncierPerimetreService.php:206`
- Périmètre sync détentions (IDs retirés) : `DossierFoncierPerimetreService.php:117`
- Offre store : `OffreFonciereController.php:107`
- Offre update : `OffreFonciereController.php:149`
- Offre réponse / marquer envoyée / périmètre / statut inline / duplication
- Promesse créer : `PromesseFonciereService.php:61` via `ParcelleEtatTransitionService`
- Promesse mettre à jour (IDs détachés) : `PromesseFonciereService.php:84-101`
- Acte acquisition : `ActeAcquisitionService.php:128`
- Dossier champ statut : `DossierFoncierController.php:1251`
- Division / réunion : `ParcelleOperationCadastraleService.php:107` et `:238`
- Société détentrice inline : `ParcelleController.php` après save `societe_detentrice_id`
- Sans issue POST/DELETE : `ParcelleController.php:501` / `retirerSansIssue`
- Création unitaire / batch : `ParcelleCreationUnitaireService.php:124` ; `ParcelleCreationService.php:357`
- Commande : `php artisan foncier:recalcul-statuts`
- Alerte cohérence promesse : `PromesseParcelleCoherenceType.php` (lit `statut`, plus `ParcelleEtatAvancement`)

## ÉCRANS REPRIS

- Fiche `Show.vue` : sélecteur État foncier retiré ; statut lecture seule + raison cliquable ; case Sans issue avec confirm ; badge titre = statut ; division sans saisie d’état
- Liste `Prospection/Index.vue` : colonne/filtre/pastilles/aide « Statut » ; filtre Type foncier retiré
- Création unitaire `Create.vue` et batch `ProspectionSaisieDialog.vue` : plus de choix d’état
- `Form.vue` : plus de select État foncier
- Carte d’emprise dossier : couleurs par `statut` (`DossierFoncierController`)
- Corbeille, navigation fiche, scénario, acte Show : libellé via `statut`
- `ParcellePanel.vue` : pastilles Statut

## STATUTS NON PRODUITS

- **Cédée (`cedee`)** : pas de source (pas d’acte de cession / vente). La parcelle retombe sur le suivant dans l’ordre de priorité.

## MAPPING FILTRE STATUT

| Libellé affiché | Valeur postée | Colonne DB | Libellé back |
|---|---|---|---|
| Repérée | `reperee` | `parcelles.statut` | Statut |
| Opportunité | `opportunite` | `parcelles.statut` | Statut |
| En négociation | `en_negociation` | `parcelles.statut` | Statut |
| Sous compromis | `sous_compromis` | `parcelles.statut` | Statut |
| Détenue | `detenue` | `parcelles.statut` | Statut |
| Cédée | `cedee` | `parcelles.statut` | Statut |
| Remplacée | `remplacee` | `parcelles.statut` | Statut |
| Explorée | `exploree` | `parcelles.statut` | Statut |
| Sans issue | `sans_issue` | `parcelles.statut` | Statut |

Query string inchangée : `etats[]` (valeurs = codes STATUTS).

## SYNTHÈSE

Le foncier fait son travail (rattacher, offrir, signer, acquérir) : le
statut suit. `etat_foncier` et `type_foncier` restent en base, non lus
ni écrits.

## DÉPLOIEMENT-TEST

```
git pull origin main
php artisan migrate --force
php artisan optimize:clear
php artisan view:clear
php artisan journal:sync
php artisan foncier:recalcul-statuts
```

Relever dans le log migrate :
`[#1569] Recalcul statut — total=… reperee=… opportunite=… en_negociation=… sous_compromis=… detenue=… cedee=… remplacee=… exploree=… sans_issue=…`

Attendu prod (10 vivantes, 1 détenue, 3 actes, 7 dossiers) : au moins
1 `detenue` et 1 `remplacee`. Ne pas ajuster la règle si les chiffres
divergent.

## LEÇON

Ne pas inventer de colonne pour « Cédée » : une destination `cession`
est une intention (#1568), pas une sortie de patrimoine. Une offre
refusée reste un fait de négociation. `exploree` ne remplace `reperee`
que s’il n’existe plus aucun dossier vivant. Recalcul en lot
(`chargerFaits` par chunk 200) : N+1 interdit sur la liste et sur
`foncier:recalcul-statuts`. `saveQuietly` + `FieldAuditService` pour
l’audit statut (le trait ne part pas).
