---
suivi: 1528
date: 2026-09-14
sujet: Diagnostic — simplifier les actes d’acquisition
chantier: foncier / actes / parcelles
type: diagnostic
statut: poussé
hash: a7affb64
fichiers:
  - docs/suivi/SUIVI_1528_diag_actes_simplification.md
---

# SUIVI #1528 — PHASE 1 diagnostic : simplifier les actes d’acquisition

## PROMPT ENVOYÉ

Constat prod : parcelle AB 0571 (Boisseron, réserve foncière) affiche
« 0 propriétaire » alors que deux actes HECTARE la concernent. Acte #1
sans parcelle. Décisions métier : un acte = date + notaire + prix +
société + ≥1 parcelle ; bascule détention groupe ; plus récent fait
foi ; supprimer surface acquise partielle ; colonne liste distincte
« détenue par le groupe ». Diagnostic seul. Pas de reprise auto. Pas
de chaîne de propriété.

## BASE GIT

HEAD local = `origin/main` = `bbf687ac` (chore hash fiche #1529).
Aucun rebase. Aucun fichier applicatif modifié. `.gitignore` et
`docs/architecture/` hors lot.

## FICHES LUES

- **#1092 LEÇON** — acte rattaché aux parcelles (pivot `acte_parcelle`) ;
  R5 clôture les détentions courantes ; R7 miroir `proprietaires`
  societe_groupe (abrogée ensuite). Impact : la liste lit encore R5
  (pivot), plus R7.
- **#1127** — surface_acquise_m2 ajoutée **après** création (fiche
  acte, pas le create). Vide = totalité. Impact : le create n’est pas
  en deux temps pour les parcelles ; la surface oui.
- **#1246 LEÇON** — `parcelles.societe_detentrice_id` remplace R7 ;
  l’acte pose la société ; ne pas confondre avec `proprietaires`.
  Impact : c’est exactement l’aveuglement de la liste.
- **#1446** — fusion état / type : `reserve_fonciere` est un
  **etat_foncier** (hors axe), pas un type à part. Impact : « réserve
  foncière » à l’écran = colonne `etat_foncier`, en concurrence avec
  le forçage `acquise` de l’acte.
- **#1462 / #1463** — fiche parcelle : société détentrice lue sur la
  colonne ; liste non traitée.
- **#1510 LEÇON** — rattacher à un acte existant = `attach` seul, **sans**
  `ActeAcquisitionService::creer`. Impact : pas de clôture R5, pas de
  société, pas d’état `acquise`.
- **#1514 LEÇON** — visibilité parcelle = créateur ∪ dossier ∪ bypass ;
  `grantVisibiliteUnitaire` (#1116) n’alimente plus ce scope.

---

## 1. CE QUE FAIT AUJOURD’HUI `ActeAcquisitionService::creer`

Fichier `app/Services/Foncier/ActeAcquisitionService.php`.

Garde-fou entrée L35-39 : `parcelle_ids` vide → `ValidationException`
« Au moins une parcelle est requise. » Les IDs sont résolus **hors ACL**
(`queryWithoutReferentielAcl`, L41-47).

Ensuite, hors transaction L50-53 : `FoncierVisibiliteService::grantVisibiliteUnitaire`
sur chaque parcelle. C’est le partage **#1116**
(`foncier_referentiel_visibilites`). Depuis #1288 / #1514 la visibilité
parcelle est `FoncierParcelleVisibiliteScope` (créateur ∪ dossier ∪
bypass) — ce grant **ne change pas** le scope. Sans effet sur l’update
d’état plus bas.

Transaction L92-162 :

1. **Insert `actes_fonciers`** L107-117 : promesse, dossier, référence,
   `societe_acquereur_id`, notaire, prix, date, `verrouille = false`,
   créateur. Pas de parcelle dans cette table.
2. **Pivot `acte_parcelle`** L119 : `$acte->parcelles()->attach($parcelleIds)`
   — **sans** `surface_acquise_m2` (NULL = totalité, #1127).
3. **Promesse** L121-126 : si `promesse_id`,
   `PromesseFonciereService::verrouillerApresActe` — verrouille la
   **promesse** (`promesses.verrouille = true`, statut acte), **pas**
   l’acte (`app/Services/Foncier/PromesseFonciereService.php` L120-126).
4. **Détentions courantes** L128-132 : `UPDATE parcelle_proprietaire
   SET date_fin_detention = date_acte WHERE parcelle_id IN (…) AND
   date_fin_detention IS NULL`. Les propriétaires externes passent en
   historique. **Aucune** ligne groupe n’est créée (R7 abrogée #1246).
5. **Société détentrice** L136-151 : pour chaque parcelle (hors ACL),
   `societe_detentrice_id = societe_acquereur_id` via Eloquent
   `forceFill`+`save` (audit). L’acte **écrase** une saisie manuelle
   différente.
6. **État foncier** L153-155 : `Parcelle::query()->whereIn('id', $parcelleIds)->update(['etat_foncier' => FoncierReferentiels::ETAT_ACQUISE])`. `ETAT_ACQUISE` = `'acquise'` (`FoncierReferentiels.php` L16 / L32). C’est un `UPDATE` de masse Query Builder : **pas** d’événement Eloquent, donc **pas** de ligne `entity_field_audits` pour cet écrit. Contrairement à la société (L147-149 `forceFill`+`save`). Un audit vide sur `etat_foncier` ne prouve pas que l’état n’a pas bougé.

### Cohérence avec AB 0571 « réserve foncière »

« Réserve foncière » **est** un `etat_foncier` depuis #1446
(`FoncierReferentiels::ETATS_FONCIERS` L36 :
`TYPE_FONCIER_RESERVE => 'Réserve foncière'`). Il est **hors axe**
(`ParcelleEtatAvancement::HORS_AXE` L27).

Le service **force** `'acquise'`, qui n’est **pas** « réserve foncière ».
Si AB 0571 affiche encore réserve foncière, le forçage n’a pas tenu
(ou n’a pas tourné). Causes possibles, par vraisemblance :

1. **Saisie manuelle après l’acte** — `etat_foncier` est en liste
   blanche inline (`ParcelleController::champsInlineAutorises` L77).
   Un chargé peut remettre « Réserve foncière » (classement patrimoine)
   après que l’acte a écrit `acquise`.
2. **Chemin rattacher sans `creer()`** — #1510
   `ParcelleCreationUnitaireService` L87-102 : `attach` seul. Ni R5,
   ni société, ni `acquise`.
3. **Update d’état sous ACL** — L153 utilise `Parcelle::query()` **avec**
   `FoncierParcelleVisibiliteScope`, alors que la société L136 passe
   hors ACL. Un POST avec des IDs hors visibilité de l’acteur poserait
   la société et **sauterait** l’état. L’UI de create ne propose que
   des parcelles visibles (`searchParcelles` L282 `Parcelle::query()`),
   donc rare en usage normal ; possible en payload crafté.
4. **Actes antérieurs au code actuel** — dates 1995 / 2023 saisies en
   2026 : si créés via `store` → `creer()`, l’état aurait dû passer à
   `acquise` au moment du POST.

SQL d’audit (ci-dessous) : `societe_detentrice_id` y figure si `creer()`
a tourné. `etat_foncier` n’y figure **que** si un inline / save Eloquent
l’a ensuite modifié — pas si le seul écrit est L153-155.

**Écart métier** : la décision « détenue par le groupe » n’équivaut pas
à `etat_foncier = acquise`. Forcer `acquise` **efface** le classement
réserve / opportunité / bouchon. PHASE 2 : poser la société (et
éventuellement ne plus toucher `etat_foncier`).

---

## 2. POURQUOI « 0 PROPRIÉTAIRE » S’AFFICHE

### Liste Prospection / Parcelles

`ParcelleController::index` redirige vers Prospection mode parcelle
(`ParcelleController.php` L83-88).

Requête : `ParcelleProspectionQuery::paginate` L90-96 :

- eager `proprietairesActuels` (pivot `parcelle_proprietaire` **où**
  `date_fin_detention IS NULL` — `Parcelle.php` L191-194) ;
- `withCount('proprietairesActuels as proprietaires_count')`.

**Aucune** lecture de `societe_detentrice_id`.

Sérialisation `ProspectionController::serializeParcelleLigne` L158-215 :
`nb_proprietaires` = ce count ; `proprietaires[]` = libellés du pivot.
Affichage `Parcelles/Index.vue` L510 et `ParcellePanel.vue` L534 / L583 :
`{{ row.etat_libelle }} · {{ row.nb_proprietaires }} propriétaire(s)`.

Donc après `creer()` qui **clôture** le pivot (L128-132), le count
tombe à 0. La société HECTARE est dans `parcelles.societe_detentrice_id`
(invisible ici). C’est le constat AB 0571, **par construction**, pas
un trou de données.

Recherche `q` (`ParcelleProspectionQuery` L244-258) : section, numéro,
commune, **ou** `orWhereHas('proprietairesActuels')`. Une parcelle
groupe n’est **pas** trouvable par « HECTARE ».

### Autres écrans — même aveuglement pivot

| Surface | Comportement |
|---|---|
| Fiche parcelle | **Pas aveugle** sur la société **si** `societe_detentrice_source === 'acte'` (`serializeSocieteDetentrice` L1174-1221, Show.vue L1192-1223, #1463). Le bloc « Propriétaire(s) actuel(s) » (Show.vue L2146-2222) est bien à 0 après R5 — cohérent mais trompeur à côté de la société. |
| Patrimoine | **Lit** `societe_detentrice_id` (`PatrimoineFoncierQuery.php` L36-38). AB 0571 devrait y figurer si la colonne est peuplée. |
| Mode Prospection propriétaire | Parcelles rattachées via `whereHas('proprietairesActuels')` (`ProspectionController.php` L376-378). Les parcelles groupe **disparaissent** de ce mode. |
| `parcellesSansProprietaire` | L711-716 `whereDoesntHave('proprietairesActuels')` — les parcelles groupe **entrent** dans « sans propriétaire ». |
| Dossier onglet FONCIER | `proprietairesActuels` (`DossierFoncierController.php` L1573, L1637-1638). |
| Valorisation | prix d’acte : d’abord `proprietairesActuels->first()->pivot.acte_foncier_id` (`ParcelleValorisationService.php` L219-228), **puis** repli sur `actesFonciers` L231-236. Le repli sauve le prix si le pivot est vide. |
| Export CSV parcelle | **aucun** trouvé. |

---

## 3. SQL (à coller en prod — pas d’accès MySQL ici)

### 3a — AB 0571 (constat)

```
SELECT p.id, p.section_cadastrale, p.numero, p.code_insee_commune,
       c.nom AS commune, p.surface_cadastrale_m2, p.etat_foncier,
       p.type_foncier, p.societe_detentrice_id, e.nom AS societe_nom,
       p.deleted_at
FROM parcelles p
LEFT JOIN communes c ON c.code_insee = p.code_insee_commune
LEFT JOIN entites e ON e.id = p.societe_detentrice_id
WHERE p.section_cadastrale = 'AB'
  AND (p.numero = '0571' OR p.numero = '571' OR p.numero LIKE '%0571%')
  AND (c.nom LIKE '%Boisseron%' OR p.code_insee_commune IS NOT NULL);
```

```
SELECT ap.acte_foncier_id, a.date_acte, a.prix_numeraire, a.reference_acte,
       a.societe_acquereur_id, ea.nom AS acquereur, a.verrouille,
       a.promesse_id, a.dossier_foncier_id, a.notaire_fournisseur_id,
       ap.surface_acquise_m2, p.surface_cadastrale_m2, p.deleted_at
FROM acte_parcelle ap
JOIN actes_fonciers a ON a.id = ap.acte_foncier_id
JOIN parcelles p ON p.id = ap.parcelle_id
LEFT JOIN entites ea ON ea.id = a.societe_acquereur_id
WHERE p.section_cadastrale = 'AB'
  AND (p.numero = '0571' OR p.numero = '571' OR p.numero LIKE '%0571%');
```

```
SELECT pp.id, pp.proprietaire_id, pr.nom, pr.raison_sociale,
       pp.quote_part, pp.date_debut_detention, pp.date_fin_detention,
       pp.acte_foncier_id
FROM parcelle_proprietaire pp
JOIN parcelles p ON p.id = pp.parcelle_id
LEFT JOIN proprietaires pr ON pr.id = pp.proprietaire_id
WHERE p.section_cadastrale = 'AB'
  AND (p.numero = '0571' OR p.numero = '571' OR p.numero LIKE '%0571%')
ORDER BY pp.date_fin_detention IS NULL DESC, pp.id;
```

```
SELECT efa.id, efa.champ, efa.ancienne_valeur, efa.nouvelle_valeur,
       efa.created_at, efa.user_id, efa.auditable_type, efa.auditable_id
FROM entity_field_audits efa
JOIN parcelles p ON p.id = efa.auditable_id
WHERE efa.auditable_type LIKE '%Parcelle%'
  AND p.section_cadastrale = 'AB'
  AND (p.numero = '0571' OR p.numero = '571' OR p.numero LIKE '%0571%')
  AND efa.champ IN ('etat_foncier', 'societe_detentrice_id')
ORDER BY efa.created_at;
```

(Colonnes réelles : `champ` / `ancienne_valeur` / `nouvelle_valeur` /
`auditable_id` / `auditable_type` — `EntityFieldAudit.php` L26-33. Un
`UPDATE` masse L153 n’écrit pas ici.)

### 3b — volumes société vs 0 propriétaire (liste)

```
SELECT
  COUNT(*) AS parcelles_actives,
  SUM(p.societe_detentrice_id IS NOT NULL) AS avec_societe,
  SUM(p.societe_detentrice_id IS NOT NULL AND NOT EXISTS (
        SELECT 1 FROM parcelle_proprietaire pp
        WHERE pp.parcelle_id = p.id AND pp.date_fin_detention IS NULL
      )) AS societe_et_zero_proprio_courant,
  SUM(p.societe_detentrice_id IS NOT NULL AND EXISTS (
        SELECT 1 FROM acte_parcelle ap WHERE ap.parcelle_id = p.id
      )) AS societe_avec_acte,
  SUM(p.societe_detentrice_id IS NOT NULL AND NOT EXISTS (
        SELECT 1 FROM acte_parcelle ap WHERE ap.parcelle_id = p.id
      )) AS societe_sans_acte
FROM parcelles p
WHERE p.deleted_at IS NULL
  AND p.statut_cadastral = 'active';
```

### 3c — actes : 0 / 1 / N parcelles (vivantes vs pivot brut)

```
SELECT
  COUNT(*) AS nb_actes,
  SUM(vivantes.nb = 0 OR vivantes.nb IS NULL) AS actes_zero_parcelle_vivante,
  SUM(vivantes.nb = 1) AS actes_une_parcelle,
  SUM(vivantes.nb > 1) AS actes_plusieurs_parcelles
FROM actes_fonciers a
LEFT JOIN (
  SELECT ap.acte_foncier_id, COUNT(*) AS nb
  FROM acte_parcelle ap
  INNER JOIN parcelles p ON p.id = ap.parcelle_id AND p.deleted_at IS NULL
  GROUP BY ap.acte_foncier_id
) vivantes ON vivantes.acte_foncier_id = a.id;
```

```
SELECT * FROM (
  SELECT a.id, a.date_acte, a.prix_numeraire, a.reference_acte,
         (SELECT COUNT(*) FROM acte_parcelle ap WHERE ap.acte_foncier_id = a.id) AS nb_pivot,
         (SELECT COUNT(*) FROM acte_parcelle ap
            JOIN parcelles p ON p.id = ap.parcelle_id AND p.deleted_at IS NULL
          WHERE ap.acte_foncier_id = a.id) AS nb_vivantes,
         (SELECT COUNT(*) FROM acte_parcelle ap
            JOIN parcelles p ON p.id = ap.parcelle_id AND p.deleted_at IS NOT NULL
          WHERE ap.acte_foncier_id = a.id) AS nb_soft_deleted
  FROM actes_fonciers a
) t
WHERE t.nb_vivantes = 0
ORDER BY t.id;
```

```
SELECT a.id, a.date_acte, a.prix_numeraire
FROM actes_fonciers a
WHERE NOT EXISTS (SELECT 1 FROM acte_parcelle ap WHERE ap.acte_foncier_id = a.id)
ORDER BY a.id;
```

Acte #1 (constat 31/07/2026, 100 000 €) :

```
SELECT a.id, a.date_acte, a.prix_numeraire, a.verrouille, a.promesse_id,
       a.dossier_foncier_id, a.notaire_fournisseur_id, a.reference_acte,
       (SELECT COUNT(*) FROM acte_parcelle ap WHERE ap.acte_foncier_id = a.id) AS nb_pivot,
       (SELECT COUNT(*) FROM acte_parcelle ap
          JOIN parcelles p ON p.id = ap.parcelle_id AND p.deleted_at IS NULL
        WHERE ap.acte_foncier_id = a.id) AS nb_vivantes,
       (SELECT COUNT(*) FROM acte_parcelle ap
          JOIN parcelles p ON p.id = ap.parcelle_id AND p.deleted_at IS NOT NULL
        WHERE ap.acte_foncier_id = a.id) AS nb_soft_deleted
FROM actes_fonciers a
WHERE a.id = 1
   OR (a.date_acte = '2026-07-31' AND a.prix_numeraire = 100000);
```

### 3d — parcelles avec plusieurs actes

```
SELECT p.id, p.section_cadastrale, p.numero, c.nom AS commune,
       COUNT(*) AS nb_actes,
       GROUP_CONCAT(ap.acte_foncier_id ORDER BY a.date_acte, a.id) AS acte_ids,
       GROUP_CONCAT(a.date_acte ORDER BY a.date_acte, a.id) AS dates
FROM acte_parcelle ap
JOIN parcelles p ON p.id = ap.parcelle_id
JOIN actes_fonciers a ON a.id = ap.acte_foncier_id
LEFT JOIN communes c ON c.code_insee = p.code_insee_commune
WHERE p.deleted_at IS NULL
GROUP BY p.id, p.section_cadastrale, p.numero, c.nom
HAVING COUNT(*) > 1
ORDER BY nb_actes DESC, p.id;
```

### 3e — surface_acquise_m2 renseignée et ≠ cadastrale (décision suppression)

```
SELECT
  COUNT(*) AS lignes_pivot,
  SUM(ap.surface_acquise_m2 IS NOT NULL) AS surface_non_null,
  SUM(ap.surface_acquise_m2 IS NOT NULL
      AND p.surface_cadastrale_m2 IS NOT NULL
      AND ROUND(ap.surface_acquise_m2, 2) <> ROUND(p.surface_cadastrale_m2, 2)
     ) AS surface_differente_cadastrale,
  SUM(ap.surface_acquise_m2 IS NOT NULL
      AND (p.surface_cadastrale_m2 IS NULL
           OR ROUND(ap.surface_acquise_m2, 2) = ROUND(p.surface_cadastrale_m2, 2))
     ) AS surface_egale_ou_sans_cadastre
FROM acte_parcelle ap
JOIN parcelles p ON p.id = ap.parcelle_id;
```

### 3f — champs d’écran (usage prod)

```
SELECT
  COUNT(*) AS nb_actes,
  SUM(promesse_id IS NOT NULL) AS avec_promesse,
  SUM(dossier_foncier_id IS NOT NULL) AS avec_dossier,
  SUM(notaire_fournisseur_id IS NOT NULL) AS avec_notaire,
  SUM(verrouille = 1) AS verrouilles,
  SUM(reference_acte IS NOT NULL AND TRIM(reference_acte) <> '') AS avec_reference
FROM actes_fonciers;
```

---

## 4. COÛT DE LA SUPPRESSION DE `surface_acquise_m2`

Colonne `acte_parcelle.surface_acquise_m2` — migration
`database/migrations/2026_07_31_150000_add_notaire_and_surface_acquise_to_actes.php` L25-27.
Nullable. Create d’acte **n’écrit pas** la valeur (`attach` nu L119).

**Écriture**

- Fiche acte `PATCH …/surfaces` (`ActeFoncierController::updateSurfaces` L214-247).
- Création unitaire : `appliquerSurfaceAcquise` /
  `attach(..., surface_acquise_m2)` (`ParcelleCreationUnitaireService.php`
  L73, L86, L100-102, L264-272). Écran `Parcelles/Create.vue` L563 / L644.

**Lecture**

- Fiche acte `ActesFonciers/Show.vue` L199-200 : « Acquise : … (totalité)
  si vide ».
- Indicateur dossier `DossierFoncierController::sommeSurfacesParcellesActe`
  L1926-1950 : si pivot NULL → **repli** arpentee puis cadastrale.
  Affiché `Dossiers/Show.vue` L1002.
- Relation `ActeFoncier::parcelles()` `withPivot('surface_acquise_m2')` L94.

**Pas de dépendance**

- Bilan financier, charges de portage, valorisation (prix d’acte, pas
  la surface partielle), Patrimoine.

Si 3e montre ~0 lignes différentes du cadastral : masquer / cesser d’écrire
est **sans perte métier**. Si des écarts existent : ce sont des acquisitions
partielles au sens actuel ; la décision métier (division cadastrale) dit
de ne **pas** les reprendre auto — les laisser en colonne jusqu’à un lot
de nettoyage, ou les ignorer à l’affichage. **Ne pas DROP** dans le lot
d’écran (réversibilité).

---

## 5. CONTRAINTE « AU MOINS UNE PARCELLE »

**Création via `/foncier/actes-fonciers`** : un seul POST.

- Front `Create.vue` L28-29, MultiSelect L228 : `parcelle_ids`.
- Back `ActeFoncierController::store` L135-137 : `required|array|min:1`.
- Service L35-39 : filet identique.

**Pas** de second temps « créer l’acte puis ajouter les parcelles » sur
cet écran. La surface partielle, elle, est un second temps (#1127) sur
la fiche.

**Rattachement ultérieur** : page « Nouvelle parcelle » `acte_mode=rattacher`
(`ParcelleCreationUnitaireService` L87-102) ajoute **une** parcelle à un
acte **déjà** créé. C’est ainsi qu’un acte peut **gagner** des parcelles
après coup — pas les perdre via l’UI.

**Pourquoi l’acte #1 peut afficher 0 parcelle**

Aucune route `update` / `destroy` / `detach` d’acte
(`routes/web.php` L1261-1293). On ne peut pas vider le pivot dans l’UI.

En revanche `Parcelle` est `SoftDeletes` (`Parcelle.php` L22). Le pivot
`restrictOnDelete` bloque un DELETE dur
(`2026_07_30_170300_create_acte_parcelle_table.php` L24-26) mais **pas**
le soft delete. `ActeFoncier::parcelles()` n’inclut pas `withTrashed()`
(L91-96) → une parcelle en corbeille **disparaît** du décompte
(`parcelles_count` L679-680, Index.vue L40).

Hypothèse à confirmer par SQL 3c : pivot encore là + `parcelles.deleted_at`
NON NULL, **ou** réellement 0 ligne `acte_parcelle` (saisie hors UI /
acte créé avant `min:1` — peu probable, #1092 du 30/07/2026, acte #1
daté 31/07/2026).

PHASE 2 : garder `min:1` au create ; afficher les parcelles soft-deleted
sur la fiche acte (constat) ; **ne pas** inventer un wizard à deux pas.

---

## 6. BASCULE AUTOMATIQUE — CONSÉQUENCES (pas de tranchage)

Aujourd’hui `creer()` : clôture les détentions courantes + pose la
société + (tente de) passer `acquise`. Pas d’inverse.

### Propriétaires externes déjà saisis

`creer()` les **clôture** (`date_fin_detention = date_acte`). Ils restent
en historique fiche (`proprietairesAnciens`). Ils ne sont pas effacés.
PHASE 2 alignée métier « le groupe a acheté » : **conserver cette
clôture** (déjà là) plutôt que d’effacer. Alternative : ne plus clôturer
— alors la liste montrerait encore les vendeurs **et** il faudrait
quand même un cran « groupe » via `societe_detentrice_id`.

### Retirer une parcelle / supprimer l’acte

**Aucun code.** Conséquences si on l’ajoute :

- Pivot : ligne disparue ; les autres parcelles de l’acte inchangées.
- `societe_detentrice_id` : **resterait** (aucun clear).
- `etat_foncier` : **resterait** `acquise` / réserve.
- Détentions clôturées : **ne se rouvriraient pas**.
- Deuxième acte sur la parcelle : resterait.

Donc « retirer » ne ramènerait **pas** tout seul à « non détenue ».
C’est cohérent avec « pas de chaîne de propriété » : le plus récent
acte restant ferait foi, ou la société resterait jusqu’à un geste
manuel. À trancher en PHASE 2 si on expose un bouton Retirer.

### Deux actes sur la même parcelle

Le pivot **empile**. Chaque `creer()` réécrit `societe_detentrice_id`
avec **cet** acquéreur et reclôture un pivot déjà vide. Le plus récent
**à l’écriture** gagne la société, pas un calcul à la lecture (sauf
fiche : `serializeSocieteDetentrice` trie les actes par `date_acte`
desc L1189-1196 pour le **lien** affiché, indépendamment de la colonne).

Si les deux actes HECTARE ont la même société, l’ordre est invisible.
Pas d’écrasement d’affichage liste (la liste ignore tout ça).

---

## 7. AFFICHAGE CIBLE (emplacement / comportement, pas le design)

**Où** : la 4ᵉ colonne « Informations » de la liste parcelle
(`Parcelles/Index.vue` / `ParcellePanel.vue`) qui concatène aujourd’hui
`etat_libelle · N propriétaire(s)`. Y coller une mention **distincte**
quand `societe_detentrice_id` est non NULL (libellé fixe « détenue par
le groupe »), **sans** y mettre le nom de société (Patrimoine / fiche
conservent la société). Si des `proprietairesActuels` restent, les
afficher à part (cas transitoire / rattacher sans `creer()`).

**Payload** : `serializeParcelleLigne` doit envoyer
`detenue_par_le_groupe` (bool) + éventuellement `nb_proprietaires`
inchangé pour l’externe. Eager `societe_detentrice_id` (colonne déjà
sur `parcelles`, pas de join obligatoire).

**Tri** : pas de tri actuel sur propriétaires. Un tri futur « groupe
d’abord » = `ORDER BY societe_detentrice_id IS NULL` — pas le libellé.

**Filtre** : ajout d’un cran « détenue par le groupe » =
`whereNotNull('societe_detentrice_id')`, disjoint des filtres état.
Ne pas réutiliser le filtre état « Acquise ».

**Recherche `q`** : aujourd’hui pivot externe seulement. Pour trouver
les parcelles du groupe : `orWhereNotNull('societe_detentrice_id')`
si la requête ressemble à un nom d’entité, **ou** un filtre dédié
plus clair qu’un LIKE sur `entites.nom`. Recommandation : **oui**,
pouvoir lister le stock groupe (filtre), sans mélanger HECTARE dans
la même liste que les vendeurs.

Mode propriétaire : hors périmètre d’un correctif liste, sauf à
exclure les parcelles groupe de `parcellesSansProprietaire`.

---

## 8. SIMPLIFICATIONS D’ÉCRAN

Écran create / show actuel :

| Champ | Prod (mesurer SQL 3f) | Verdict diagnostic |
|---|---|---|
| Date, société, prix, parcelles | cœur métier | garder, parcelles obligatoires |
| Notaire | optionnel, hérité promesse L99-105 | garder si 3f > 0, sinon masquer create (colonne conservée) |
| Référence | optionnel | garder |
| Promesse | optionnel ; verrouille la **promesse** | garder le lien ; pas un champ d’instruction parcelle |
| Dossier | nullable R2 ; show « Aucun (réserve) » Show.vue L108 | garder |
| Surface acquise | 2ᵉ temps fiche | **retirer de l’UI** si 3e ≈ 0 écart |
| Documents | #1117 | garder (hors modèle parcelle) |
| `actes_fonciers.verrouille` | posé `false` à la création L115 ; **aucun** `true` applicatif (grep : seulement la promesse) | **mort**. Affiché serialize L667 / search « (verrouillé) » L501. Masquer. Ne pas migrer DROP. |

Pas de verrouillage d’acte dans l’UI. Le verrou utile est celui de la
promesse une fois actée.

---

## PÉRIMÈTRE PHASE 2 (proposition)

Un lot écran + payload, **sans** migration DROP, **sans** reprise des
données, **sans** chaîne de détention.

1. Liste parcelle : mention distincte « détenue par le groupe » si
   `societe_detentrice_id` ; ne plus afficher « 0 propriétaire » comme
   seule info dans ce cas.
2. Filtre + recherche : cran groupe ; `q` ne suffit pas via le pivot.
3. Ne plus forcer `etat_foncier = acquise` à l’acte (laisse réserve /
   opportunité). L’effet unique = société détentrice + clôture pivot
   externe (déjà là dans `creer()`).
4. Masquer surface acquise (fiche acte + create unitaire) ; colonne
   conservée.
5. Masquer `verrouille` d’acte.
6. Fiche acte : parcelles soft-deleted visibles (constat acte #1).
7. `acte_mode=rattacher` : aujourd’hui **sans** R5/société — soit
   appeler le même effet que `creer()` sur cette parcelle, soit
   documenter que rattacher ne « détient » pas. À trancher, un seul
   comportement.

Hors PHASE 2 : DROP colonnes, bouton retirer/supprimer acte, quotes-parts,
backfill des 0 propriétaire, changer l’enum des états.

---

## DÉPLOIEMENT-TEST

```
git pull origin main
```

Pas de migrate, journal, npm. Exécuter les SQL §3. Contrôler AB 0571
(société, pivot clôturé, audit `etat_foncier`) et acte #1 (pivot vs
soft delete).

## LEÇON

R7 abrogée (#1246) a déplacé la détention groupe sur
`societe_detentrice_id`, mais la liste parcelle compte encore
`proprietairesActuels`. `creer()` vide ce compteur : « 0 propriétaire »
est le succès de R5, pas l’absence d’acte. Forcer `acquise` se heurte
à « réserve foncière » devenu un état (#1446). `grantVisibiliteUnitaire`
sur parcelle est un vestige #1116, inopérant pour #1514.
