---
suivi: 1297
date: 2026-08-12
sujet: diag_reinterpretation_depot_cie
chantier: depot-factures
type: diagnostic
statut: poussé
hash: e258fcd6
fichiers:
  - tools/diag/verif_reinterpretation_depot_1297.php
  - docs/suivi/SUIVI_1297_diag_reinterpretation_depot_cie.md
---

## PROMPT ENVOYÉ

PHASE 1 DIAG — NE PAS CODER. Tracer la pré-coche CIE à la réouverture d’un dépôt validé / payé (FA202605418 SIT 04, marché 109), inventaire des champs réinterprétés, mesure d’exposition (script lecture seule), faisabilité lecture seule post-NV1 sauf GS_ADMIN_ERP.

## SYNTHÈSE

### Fiches lues
- `SUIVI_1277_cie_chargement_dues.md` (LEÇON : loading + `modifiable` serveur)
- `SUIVI_1275_diag_droits_modification_depot.md` (canEditDepot, pré-coche dues, piège AdminERP)
- `SUIVI_1268_affectation_cie.md` (1 due → pré-coche ; 2+ → aucune)
- `SUIVI_1296` / chaîne #1292 (unités HT/TTC) — pas de correctif ici

### OBJET 1 — Chaîne de la pré-coche

| Fichier:ligne | Déclencheur | Condition | Effet |
|---|---|---|---|
| `routes/web.php` ~342 | GET `depot-factures/{uuid}/cie-retenue-dues` | Auth + vue dépôt | Route HTTP 200 visible dans le bandeau |
| `DepotFactureController::cieRetenueDues` ~4784 | Contrôleur | `marche_id` + `fournisseur_id` | JSON `dues[]`, `modifiable` = `canEditDepot($depot)` |
| `CieService::repartitionsDuePourFournisseurMarche` ~1003 | Service lecture | SoftDeletes ops+reps ; reste > 0 | Liste des dettes CIE **ouvertes aujourd’hui** (pas l’état validé du dépôt) |
| `DepotFactureSaisieForm.vue` ~4985 | `watch([marche_id, fournisseur_id, uuid], { immediate: true })` | Toujours à l’ouverture | Appelle `refreshCieDues()` |
| `…:refreshCieDues` ~4097 | axios GET cie-retenue-dues | Après gardes uuid/marché/fournisseur | Remplit `cieLignes`, bandeau `ok · HTTP 200 · N ligne(s)` |
| `…:4140-4143` | Branche `#1268` | `dues.length === 1` **ET** `modifiable === true` **ET** `!cieUserUnchecked` **ET** pas de `cie_lignes` / `preleve` sauvé | `checked=true`, `montant_ht=reste_du_ht` |
| `…:4170-4176` | Suite succès | dues > 0 + `modifiable` + `!cieUserUnchecked` | `showCIE=true` + `syncMontantCieTtcDepuisLignes()` → `form.montant_cie` TTC |
| `…:6450-6460` | `captureDraftBaseline` (nextTick onMounted) **avant** fin HTTP | Baseline sans CIE | Puis `montant_cie` / `cie_lignes` changent → `isDraftDirty=true` → bouton « Enregistrer (modifications non sauvegardées) » |
| `canEditDepot` ~4009 + `Show.vue:406` | `readonly = !can_edit` | Post-compta / payé : **true seulement si GS_ADMIN_ERP** (`FactureAdminErpEditOverride`) | Sans Admin : `modifiable=false` → pas de pré-coche. **Avec Admin (Robin) : pré-coche active même sur dépôt payé.** |

**Cause racine** : à l’ouverture, le front ne restitue pas l’état validé ; il **repropose les dettes CIE ouvertes** et, s’il n’y en a qu’une et que `canEditDepot` est vrai, la **pré-coche #1268** injecte un CIE inexistant dans le formulaire (et le dirty).

**Conditionné au statut ?** Indirectement via `canEditDepot` → `modifiable`. Pas de garde « déjà franchi NV1 / déjà validé → ne pas pré-cocher ». `depotRetenuesModifiables` (fige `paye`/`valide`/…) **n’est pas** utilisé pour la pré-coche CIE (#1277 : foi exclusive à `modifiable`).

### OBJET 2 — Inventaire champs réinterprétés (≤ 15, arrêt)

| Champ | Valeur enregistrée (cible métier) | Affichage ouverture (cas signalé) | Source affichage | Divergence |
|---|---|---|---|---|
| Case CIE `showCIE` | non (pas de CIE) | cochée | `refreshCieDues` | **oui** |
| Lignes opérations CIE | aucun prélèvement | 1 op. « nettoyage… » cochée | `dues[]` + pré-coche #1268 | **oui** |
| Montant CIE ligne HT | 0 | 252,00 | `reste_du_ht` | **oui** |
| `form.montant_cie` | 0 / absent (TTC) | ≈ 302,40 TTC | `syncMontantCieTtcDepuisLignes` | **oui** |
| `form.cie_lignes` | [] / absent | `[{repartition_id, 252}]` | sync | **oui** |
| RG % | saisie (ex. 5) | 5 | hydrate `ocr_raw.saisie` | non* |
| RG montant reconstitué | 1 411,23 € HT (historique) | 1 709,83 € | `montantRgTtc` / base avec CIE | **oui** |
| CP % | saisie | saisie | hydrate | non* |
| CP montant reconstitué | valeur historique | gonflé | même reconstitution | **oui** |
| OPC % / montant | 0 / — | 0 / masqué | hydrate | non |
| Finitions | saisie | saisie | hydrate | non* |
| Pénalités | `penalites_imputees` | idem | hydrate | non* |
| Cagnotte CP `deduire_cagnotte_cp` | saisie | saisie | hydrate | non* |
| Lignes HT/TVA / totaux saisis | `lignes_tva` | idem | hydrate (#849) | non* |
| Dirty / Enregistrer | propre | actif | baseline vs `montant_cie` post-HTTP | **oui** |

\* hors changement manuel marché (`applyRetenuesPrefillDepuisMarche` seulement via `onMarcheIdUserUpdate`) et hors watch #1224 (actif seulement si `depotRetenuesModifiables`, faux pour `paye`/`valide`/`comptabilisee`).

**Clause d’arrêt** : 15 lignes listées (dont 8 divergences confirmées). Pas d’analyse supplémentaire.

### OBJET 3 — Script

`tools/diag/verif_reinterpretation_depot_1297.php` — lecture seule.

**Exécution agent (local, 12/08/2026)** — sortie brute :

```
PHP_SAPI=cli
PHP_VERSION=8.3.1
VERSION()=11.4.5-MariaDB
driver=mysql db=erp_immo
depot_factures: id, poste_budgetaire_type_id, programme_budget_id, created_at, updated_at
TABLE ABSENTE: cie_operations — RESULTAT 0 NE VALIDE RIEN
```

La base locale `erp_immo` est un stub (5 colonnes `depot_factures`, pas de CIE). **Les compteurs d’exposition / parasites / FA202605418 sont INCONNUS jusqu’à rejeu OVH.** Un résultat 0 local ne valide rien.

À exécuter en prod :

```bash
php -d display_errors=1 tools/diag/verif_reinterpretation_depot_1297.php
```

### OBJET 4 — Faisabilité lecture seule

| Point | Constat |
|---|---|
| Modifiabilité actuelle | `canEditDepot` (#1276) + prop Inertia `can_edit` → `Show.vue` `:readonly="!can_edit"`. Front `depotRetenuesModifiables` fige déjà retenues UI pour `valide`/`paye`/`comptabilisee` **mais CIE contourne** via `modifiable`. |
| Branchement recommandé | 1) **Ne plus appeler / ne plus pré-cocher** les dues CIE si dépôt a franchi NV1 (sauf brouillon). 2) Verrou UI retenues+montant post-NV1 sauf Admin. 3) **Refus serveur** sur PATCH des champs retenues/montants. |
| Champs à verrouiller post-NV1 | RG/CP/OPC (cases+%), finitions, CIE (case+lignes+montants), pénalités liées retenues, bloc reconstitution / montants facture (lignes TVA, totaux), rattachement marché/fournisseur si impact comptable. |
| Rester modifiables (hors Admin) | Notes / libellé, documents joints, commentaires workflow — à confirmer Robin ; dates à arbitrer. |
| Contrôle serveur | `DepotFactureController::update` (+ chemins `valider*`, `assertCieRetenueServeur`, sync prélèvements). Un `readonly` UI seul est insuffisant. |
| Piège groupes | `hasAnyM365Group` / `hasM365Group` → true si `isAdminERP()`. Tester avec **`m365GroupNames()` brut**. `GS_PDG_ENVOL` référencé (`HandleInertiaRequests`) mais souvent absent base — vérifier `groupes_m365` + count users. Script §BONUS. |
| Périmètre chiffré | À remplir depuis sortie prod : `population_exposee_count` (retenues) vs même + montants (`depots_NV1_plus_count`). Local : inconnu. |

### CONCLUSION (5 lignes)
1. Cause racine : `refreshCieDues` + pré-coche #1268 quand `modifiable` (Admin ERP sur payé) et exactement 1 dette CIE ouverte.
2. Population exposée : dépôts NV1+ sans prélèvement CIE sur un couple marché/fournisseur à dette ouverte — **count prod à mesurer** (script).
3. Écritures parasites déjà survenues : **inconnu** localement (0 ligne local = stub DB) ; section 5 du script en prod.
4. Même famille que #1262 abandonné : Enregistrer réflexe réécrirait CIE + RG/CP sur facture Sage.
5. PHASE 2 recommandée : stopper proposition/pré-coche dues post-NV1 + lecture seule retenues+montant (sauf Admin via `m365GroupNames`) + refus serveur `update`.

## DÉPLOIEMENT-TEST

```bash
git pull origin main
php -d display_errors=1 tools/diag/verif_reinterpretation_depot_1297.php
```

Coller la sortie prod dans le ticket / PHASE 2. Aucun `journal:sync` (pas d’entrée journal — diagnostic).

## LEÇON

« Modifiable » Admin ERP + règle « 1 due → pré-cocher » transforme une **dette ouverte du marché** en **saisie fantôme** sur une facture déjà arbitrée. Restituer l’état validé et ne proposer les dues qu’en brouillon / neuf. Ne jamais tester GS_ADMIN_ERP via `hasAnyM365Group`.
