---
suivi: 1552
date: 2026-09-15
sujet: Accélérer le chargement d’une facture dans la boîte de dépôt
chantier: factures / depot / performance
type: feature
statut: poussé
hash: 36e19cd7
fichiers:
  - app/Http/Controllers/DepotFactureController.php
  - app/Services/MontantFactureSousTraitantService.php
  - routes/web.php
  - resources/js/Pages/DepotFactures/DepotFactureSaisieForm.vue
  - public/build/manifest.json
  - database/data/journal_mises_a_jour_post_2026_06_12.php
  - docs/suivi/SUIVI_1552_perf_chargement_depot.md
---

# SUIVI #1552 — PHASE 2 : accélérer le chargement d’une facture dans la boîte de dépôt

## PROMPT ENVOYÉ

Corriger les points 1 et 3 du diagnostic #1550 : ne charger que les
marchés du programme de la facture ; ne calculer `kpiAvancementMarche`
que pour le marché sélectionné ; endpoint de repli si OCR a
présélectionné un marché hors programme ; supprimer la double
agrégation HT+TTC et la double reprise. Évaluer les 4 009
fournisseurs (search existant ou signaler). Mesure SQL + taille
payload obligatoire. Pas de Redis, pas de découpage du formulaire,
pas d’allègement `ocr_raw`, pas de catalogues stables hors payload.

## FICHES LUES

- **#1550 LEÇON** — l’OCR n’est pas rejoué à l’affichage. La lenteur
  est `GET /depot-factures/{uuid}/data` → `depotSaisiePagePayload` :
  catalogue **tous** les marchés × KPI (2 agrég. + 2 reprises + 2 CIE).
  Volumes prod : 417 marchés, 4 009 fournisseurs. Point 2 (catalogues
  stables) et point 4 (`ocr_raw`) hors lot. CIE / avoirs déjà en GET
  dédiés : modèle du repli marchés.
- **#1190** — programmes déjà lazy (`/programmes/search`). Les marchés
  n’avaient pas suivi.
- **#1551** — zone commune Show.vue seulement ; pas de collision
  `DepotFactureSaisieForm` / `DepotFactureController` payload.

## SYNTHÈSE

### Marchés (point 1)

`depotSaisiePagePayload` ne charge plus `Marche::query()` global.
Il charge les marchés du **programme** du dépôt (colonne, saisie OCR,
suggestion, facture) plus les ids à conserver (marché déjà posé /
OCR). `kpiAvancementMarche` + `plafondHorsRetenues` uniquement pour
le marché **sélectionné**.

Repli : `GET /depot-factures/{uuid}/marches?programme_id=&kpi_marche_id=&include_marche_id=`
(même schéma que CIE / avoirs). Le formulaire fusionne dans
`marchesLocaux`. `marchesFiltres` reste filtré par programme **et**
conserve toujours le marché sélectionné s’il est d’un autre programme.

### Doubles agrégations (point 3)

`kpiAvancementMarche` : un seul `depotsPourAgregation`, une seule
reprise HT, TTC dérivé une fois. Les méthodes publiques
`totalHtDepotsMarche` / `totalTtcDepotsMarche` restent pour les
autres écrans.

### Fournisseurs — non basculés

`FournisseurController::search` existe (#1156) mais est **gating
commercialisation / lots / acquéreurs**, pas dépôt/factures. Le
Select saisie résout aussi par SIRET, hydrate l’OCR, ventile le
multi-fournisseur et mappe toute la liste (`DepotFactureSaisieForm`
~10 usages de `props.fournisseurs`). Basculer = retouche lourde du
composant. **Non fait dans ce lot.** Le levier principal reste les
marchés.

### Mesure

`GET /data` ajoute `_perf.query_count` (query log autour de
`findDepot` + payload). Taille : DevTools Size / Content-Length.

AVANT (code #1550 + volumes prod 417 marchés) : ~417 × 6 = **~2 502**
requêtes KPI (2 agrég. + 2 reprises + 2 CIE) + catalogues.
APRES : coller `_perf.query_count` et Size sur le même dépôt après
déploiement (commandes dans le livrable).

Aucun changement OCR ni données saisies. Aucune migration.

## DÉPLOIEMENT-TEST

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

Cas manuels prod :

1. Facture PROGRAMMES avec marché → marché dans la liste, sélectionné, avancement affiché
2. Facture PROGRAMMES sans marché → liste = marchés du programme
3. Changer de programme → liste mise à jour
4. OCR marché d’un autre programme → marché conservé dans la liste, repli GET
5. FRAIS GÉNÉRAUX → pas de marché, pas de régression
6. Facture historique → pas d’erreur
7. Enregistrer puis rouvrir → mêmes valeurs

## LEÇON

Le coût d’ouverture d’un dépôt n’est pas l’OCR : c’est le **catalogue
calculé pour tout l’ERP**. Un select filtré côté client n’excuse pas
de calculer le KPI de 417 marchés. Même schéma que les programmes
(#1190) : payload = contexte courant ; le reste en GET dédié. Ne pas
confondre `FournisseurController::search` (droits commercial) avec un
autocomplete dépôt. `query_count` sur `/data` est le seul moyen de
prouver l’avant/après en prod (pas de MySQL depuis l’agent).
