---
suivi: 1603
date: 2026-09-17
sujet: Rattachement périmètre si détention existante
chantier: foncier / dossiers
type: feature
statut: poussé
hash: 6ce86f7d
fichiers:
  - app/Http/Controllers/Foncier/DossierFoncierController.php
  - app/Services/Foncier/DossierFoncierPerimetreService.php
  - resources/js/Components/Foncier/DossierFoncierTab.vue
  - tests/Unit/DossierFoncier1603PerimetreSourceTest.php
  - database/data/journal_mises_a_jour_post_2026_06_12.php
  - public/build/
  - docs/suivi/SUIVI_1603_rattachement_perimetre_detention_existante.md
---

# SUIVI #1603 — Rattachement au périmètre si détention existante

## PROMPT ENVOYÉ

Deux corrections légères sur l’onglet FONCIER (DF-2026-0009, AI 0160
indivision HECTARE / THUIN). 1) Remettre au périmètre une parcelle
déjà détenue, sans refuser ni modifier la détention. 2) Avertir au
retrait si la parcelle figure sous plusieurs propriétaires du dossier.
Un seul bouton. Pas de migration. #1588 / #1569 / journal #1579
intacts.

## FICHES LUES

- **#1592 LEÇON** — le refus de retrait était serveur *et* UI ; lever
  les deux. Confirmation PrimeVue, pas `alert`. Impact : on *ajoute*
  une phrase à `messageConfirmationRetrait`, on ne recrée pas un
  confirm natif.
- **#1588 LEÇON** — sous_compromis bloque le rattachement à un
  *nouveau* dossier (`assertParcellesRattachablesALaCreation`). Impact :
  méthode intacte ; ne pas l’appeler depuis l’attach fiche.
- **#1569 LEÇON** — `deduire()` inchangé ; on appelle `recalculerIds`
  déjà dans `attacher` / `retirerParcelle`.
- **#1289** — périmètre = `dossier_foncier_parcelle`. Impact :
  `attacher()` suffit pour le cas déjà détenue.
- **#1602** — `manifest.json` commun. Impact : rebase Vite après
  push #1602, pas le même pull.

## OÙ LE REFUS ÉTAIT PRONONCÉ

`DossierFoncierController::attachParcellesProprietaire` appelait
`ParcelleCreationService::attachCourantsBatchForProprietaire(..., true)`
(`refuseSiDejaCourant`). Si une détention courante existait déjà pour
le couple parcelle × propriétaire, `ValidationException` :

« La parcelle AI 0160 est déjà détenue par ce propriétaire
(détention courante). Ajustez la quote-part… »

Le retrait du périmètre (#1592) ne clôture pas la détention, donc
remettre AI 0160 retombait toujours dans ce refus.

Le chemin fiche propriétaire (`ProprietaireController`, flag `false`)
n’est pas modifié : là, une quote-part peut encore s’actualiser.

## POURQUOI LE MESSAGE APPARAISSAIT DEUX FOIS

Le POST n’envoyait **qu’une** erreur (`parcelles.0.parcelle_id`).
Le dialogue `DossierFoncierTab.vue` l’affichait **deux fois** :

1. un `<p>` dédié à `errors['parcelles.0.parcelle_id']` ;
2. un `v-for` sur toutes les clés `parcelles*`.

L’indivision (deux blocs HECTARE / THUIN) n’a pas dupliqué le POST ;
la recherche parcelle est unique par `parcelles.id`. Le doublon était
d’affichage.

## COMPORTEMENT RETENU

- Déjà détenue par le propriétaire choisi : `attacher()` au pivot
  dossier, **aucun** `attachOrUpdatePivot` (ni quote-part, ni date,
  ni nouvelle ligne).
- Pas encore détenue : batch inchangé + `syncParcellesMiroirDepuisProprietaires`.
- Un bouton « Rattacher ». Info ambre avant validation, une fois par
  parcelle.
- Retrait partagé : phrase en plus sur la confirmation #1592.
  Comportement inchangé (retrait global).

## SYNTHÈSE

Petit diff. Droits inchangés (`authorize` + `abort_unless` view /
`useInDossier`). `m365GroupNames` brut côté policy existante, pas
un nouveau Gate.

## DÉPLOIEMENT-TEST

```
git pull origin main
php artisan view:clear
php artisan journal:sync
```

Pas de migrate. `route:clear` inutile.

## LEÇON

Un message Laravel unique devient double si le Vue a un `<p>` ciblé
*et* une boucle sur les mêmes clés. `refuseSiDejaCourant` est le bon
garde pour la *fiche propriétaire* ; sur le dossier, le verbe est
périmètre, pas détention.
