---
suivi: 1266
date: 2026-08-11
sujet: PHASE 2 modele CIE — structure cout/prelevements, soft-delete, masque pair-a-pair
chantier: cie / compta
type: feature
statut: poussé
hash: 8c8e5eaf
fichiers:
  - database/migrations/2026_08_11_140000_add_depot_facture_cout_id_to_cie_operations_table.php
  - database/migrations/2026_08_11_140100_create_cie_prelevements_table.php
  - database/migrations/2026_08_11_140200_add_cumul_retenu_ht_to_cie_repartitions_table.php
  - database/migrations/2026_08_11_140300_add_soft_deletes_to_cie_repartitions_table.php
  - app/Models/CiePrelevement.php
  - app/Models/CieOperation.php
  - app/Models/CieRepartition.php
  - app/Services/CieService.php
  - app/Http/Controllers/CieController.php
  - routes/web.php
  - resources/js/Pages/Cie/Index.vue
  - tools/diag/verif_modele_cie_1266.php
  - database/data/journal_mises_a_jour_post_2026_06_12.php
  - docs/suivi/SUIVI_1266_modele_cie.md
  - public/build/
---

# SUIVI #1266 — Modèle CIE PHASE 2

## PROMPT ENVOYÉ

PHASE 2 — schéma + backend uniquement. Aucune retenue appliquée. Ne pas
ressusciter #1262. Ne pas toucher numérateur / montant_cie / saisie facture /
écritures. Suite #1265 (7cfe23e2 / 6bb9e645), exécuté prod 11/08/2026 12:38.

## FICHES LUES

- `#1265` — deux sémantiques, R4 bloqué, pair-à-pair faux, nature déclarée
  structurelle, plan papier.
- `#1261` / `#1263` — montant_cie=0 partout ; ERP incomplet pas corrompu.
- `#990` — dont CIE via cie_repartitions.marche_id ; whereHas operation.
- `#1249`/`#1253` — pièges soft delete / index FK (ici : aucun dropIndex).

## RÈGLES R1–R7

R1 avanceur = toujours ENVOL · R2 un créancier ENVOL · R3 retenue éteint dette ·
R4 un coût → N retenues · R5 montant = répartition · R6 partiel OK · R7 HT partout.

## OBJET 1 — Quatre constats (lecture, avant / dans verif)

### (a) Opération 10 — critère déduit déjà faux
avanceur OCCITANIE SOLUTIONS (2226) ≠ fourn. dépôt 1339 OCCITANIE SECURITE (3989) ;
op_ht = depot_ht = 90 ; rep KM2A 100 %. #1265 classait RETENUE. Réalité présumée :
PRESTATION + erreur de saisie avanceur. **Ne pas corriger** — Lahouari tranche.
Preuve que la nature doit être **structurelle**.

### (b) Ops 12+13 = un seul coût 681,00 découpé
2 × 340,50 ; commentaire op 12 « A REPRENDRE ». Contournement cardinalité.
Liste contournements réels : **12, 13 seulement**. Ops 4–9 = vrais coûts 1 débiteur
(1 rep 100 % n’est pas toujours un contournement).

### (c) Trois fournisseurs « ENVOL »
À confirmer noms exacts via verif OVH (ids 1179, 1180, 3224 + like %ENVOL%).
Créancier juridique = **hors périmètre** (Robin / Sabrina / Rudy).

### (d) Reps sans marché
rep 23 SNP 252 + rep 28 NJIMA 39 = **291,00 €** structurellement irrécupérables
par retenue sur situation. Hors lot ; le modèle (marche_id nullable) n’empêche
pas un mode hors situation ultérieur.

## Schéma installé (ordre migrations)

1. `2026_08_11_140000` — `cie_operations.depot_facture_cout_id` nullable FK nullOnDelete
2. `2026_08_11_140100` — table `cie_prelevements` (softDeletes, statut retenu|encaisse|annule,
   depot restrictOnDelete)
3. `2026_08_11_140200` — `cie_repartitions.cumul_retenu_ht` DEFAULT 0 (cache ;
   vérité = prélevements ; écrit par `CieService::recalculerCumulRetenuHt`)
4. `2026_08_11_140300` — softDeletes `cie_repartitions` + UPDATE lié rattrapage fantômes

**Conservé** : `depot_facture_id` legacy, pas d’unique, pas de drop d’index existant.
**Aucune reprise** des 11 ops (pas de copie vers cout_id / prélevements).

Hard cascade FK op→rep : inchangé ; s’applique au forceDelete. Soft delete op →
boot `CieOperation` soft-delete ses répartitions.

## Requêtes soft-delete corrigées / inventaire

| Requête | Avant | Après |
|---------|-------|-------|
| `CieRepartition::query()` (global SoftDeletes) | comptait fantômes si op deleted | filtre `deleted_at` auto |
| `MarcheCouvertureKpiService` cie_a_venir | whereHas operation (ops) | + SoftDeletes reps |
| `CieService::operationsForProgramme` / soldes / etatRécup | via relation reps | exclut soft-deleted |
| `CieController::destroy` | soft-delete op seule | boot soft-delete reps |
| Migration rattrapage | — | aligne deleted_at reps sur ops |

## État de reclassement

Proposition (pas un fait) — détail script section 6. Reclassement manuel Robin
dans un lot écran ultérieur. Pas de data-fix.

## Pair-à-pair masqué

- Front : onglets Matrice / Règlements retirés de `Cie/Index.vue`
- Serveur : `calculerMatriceDettes` / `suggestionsReglements` → abort 403 ;
  routes `programmes.cie.matrice` / `reglements` → 403
- Algo legacy conservé en private
- **Soldes conservés** (défaut connu : RB créancier alors que payé) — signalé

## Rest à faire (lots suivants)

- Écran saisie (#1264) : 5e case CIE, plafond reste dû
- Application retenue + écriture `montant_cie` + numérateur (pas #1262 tel quel)
- Reclassement manuel 11 ops + refonte 12/13
- Créancier juridique
- Récupération hors situation (291 €)
- Remplacement onglet Soldes par état mono-créancier (API `etatRecuperationParProgramme` prête)

## DÉPLOIEMENT-TEST

```
git pull origin main
php artisan migrate --force
php artisan optimize:clear
php artisan route:clear
php artisan journal:sync
php -d display_errors=1 tools/diag/verif_modele_cie_1266.php
```

Écran Robin : Matrice/Règlements absents ; routes forgées 403 ; Opérations/Soldes/KPI
inchangés ; `grep "production.ERROR" storage/logs/laravel.log | tail -5`.

## LEÇON

Nature déduite = piège comptable (op 10). Séparer par structure (cout_id vs
prélevements). Soft-delete parent sans enfants = dettes fantômes. Masquer
l’actionnable (règlements) avant d’appliquer des retenues.
