---
suivi: 1453
date: 2026-09-04
sujet: Dépôt facture — commande backfill valideur = déposant
chantier: depot_factures
type: feature
statut: poussé
hash: 2bae45ec
fichiers:
  - app/Console/Commands/BackfillDepotFactureValidateurCommand.php
  - app/Support/FactureHistoriquePresenter.php
  - tests/Unit/BackfillDepotFactureValidateurCommandTest.php
  - tests/Unit/BackfillDepotFactureValidateurCommandDbTest.php
  - docs/suivi/SUIVI_1453_backfill_validateur_depot.md
---

# SUIVI #1453 — Backfill valideur déposant

## PROMPT ENVOYÉ

Le #1450 est déployé mais la commande artisan de rattrapage des 21 dépôts
sans valideur n’existait pas. Livrer `depot-factures:backfill-validateur`,
dry-run par défaut, JSON_SET d’une seule clé, idempotente, journal
`facture_historique`, CLI OVH sans Graph. Ne pas exécuter le rattrapage.

## FICHES LUES

- `SUIVI_1450` — valideur dans `ocr_raw.saisie.validateur_id` ; déposant = `user_id` ;
  azure_id sinon `users.id` ; ne pas défaire enregistrement permissif / envoi durci / filtres.
- `SUIVI_1435` LEÇON — ne jamais réécrire un JSON métier avec un objet entier à la place
  d’une clé. Ici : `JSON_SET` sur `$.saisie.validateur_id` uniquement.

Base : `origin/main` `7fe5e3b9` (chore #1450), ancêtre `f33abb92` (#1450 feat).

## CONVENTION BACKFILL RELEVÉE

`php artisan list | grep -i backfill` :

- `{domaine}:backfill-{sujet}` : `lots:backfill-exposition`, `taches:backfill-*`, `budgets:backfill-ancrage-historique`
- `{domaine}:{sujet}:backfill` : `meta:campaign-names:backfill`, `meta:leads:backfill`
- `{domaine}:backfill` : `rg:backfill`
- Dry-run par défaut + `--apply` : `meta:campaign-names:backfill`, `lots:backfill-exposition`, `taches:backfill-validation-nv1`

Retenu : `depot-factures:backfill-validateur` + `{--apply}` (comme meta/lots/taches).

## SYNTAXE

php artisan depot-factures:backfill-validateur
php artisan depot-factures:backfill-validateur --apply

## JOURNALISATION CLI

`DepotFacture::logHistorique(..., system: true)` (trait `Historisable`) :
`user_id` = null, `impersonator_id` = null, action `backfill_validateur_deposant`
(libellé presenter distinct de `modifie`). Pas d’auth en CLI → pas de plantage.

## REQUÊTE TÉMOIN (Robin, avant puis après --apply)

SELECT
  id, uuid, statut,
  JSON_UNQUOTE(JSON_EXTRACT(ocr_raw, '$.saisie.validateur_id')) AS validateur_id,
  JSON_UNQUOTE(JSON_EXTRACT(ocr_raw, '$.saisie.entite_id')) AS entite_id,
  JSON_UNQUOTE(JSON_EXTRACT(ocr_raw, '$.saisie.marche_id')) AS marche_id,
  JSON_UNQUOTE(JSON_EXTRACT(ocr_raw, '$.saisie.montant_ht')) AS montant_ht,
  JSON_UNQUOTE(JSON_EXTRACT(ocr_raw, '$.saisie.destination')) AS destination,
  JSON_UNQUOTE(JSON_EXTRACT(ocr_raw, '$.saisie.programme_id')) AS programme_id,
  JSON_UNQUOTE(JSON_EXTRACT(ocr_raw, '$.saisie.fournisseur_id')) AS fournisseur_id,
  JSON_UNQUOTE(JSON_EXTRACT(ocr_raw, '$.saisie.mode_reglement')) AS mode_reglement,
  JSON_UNQUOTE(JSON_EXTRACT(ocr_raw, '$.saisie.numero_facture')) AS numero_facture,
  JSON_KEYS(JSON_EXTRACT(ocr_raw, '$.saisie')) AS cles_saisie
FROM depot_factures
WHERE id = :id AND deleted_at IS NULL;

Seul `validateur_id` (et `cles_saisie` si la clé est ajoutée) doit changer.

## SYNTHÈSE

Commande livrée, non exécutée en prod. Périmètre : cinq statuts de boîte,
uniquement sans `validateur_id`. Une requête SELECT boîte + un UPDATE JOIN
JSON_SET. Aucun .vue, aucune migration, `DepotFactureController` non modifié.

## DÉPLOIEMENT-TEST

git pull origin main
php artisan optimize:clear
Puis Robin : dry-run, puis --apply.

## LEÇON

Annoncer une commande dans une synthèse ne la crée pas. Le rattrapage JSON
doit partir d’une commande `--apply` explicite, JSON_SET d’une clé, historique
`system: true` (CLI sans user).
