---
suivi: 1489
date: 2026-09-08
sujet: Cocher déjà réglée en NV1/NV2 clôture le workflow
chantier: factures
type: fix
statut: poussé
hash: 39fc6bea
fichiers:
  - app/Services/FactureDejaRegleeClotureWorkflowService.php
  - app/Console/Commands/ClotureDejaRegleeWorkflowCommand.php
  - app/Http/Controllers/DepotFactureController.php
  - app/Models/WorkflowValidation.php
  - app/Models/Task.php
  - app/Services/AlerteService.php
  - app/Services/TaskSyncService.php
  - app/Support/FactureHistoriquePresenter.php
  - database/migrations/2026_09_08_184900_add_sans_objet_to_workflow_validations_statut_enum.php
  - database/data/journal_mises_a_jour_post_2026_06_12.php
  - tests/Unit/FactureDejaRegleeClotureWorkflow1489Test.php
  - tests/Unit/FactureDejaRegleeClotureWorkflow1489SourceTest.php
---

# SUIVI #1489 — déjà réglée en cours de NV : clôturer sans valider

## PROMPT ENVOYÉ

Cocher « déjà réglée » sur une facture déjà en NV1/NV2 coincait la fiche
(#1488) : frise skip NV, bouton Valider masqué, WV encore `en_attente`.
Clôturer les WV nv1/nv2 en attente, passer facture + dépôt à
`a_comptabiliser`, journaliser, notifier le valideur (cloche + Teams).
Reprise des 5 dépôts mesurés. Pas de confirmation bloquante.

## BASE GIT

HEAD attendu `0b0fa1bf` (fiche #1488). origin/main à jour, pas de rebase.

## FICHES LUES

- **#1488** (LEÇON) — `deja_reglee` est un *type* de frise qui saute NV1/NV2 ;
  `showHeaderValidationActions` exige `currentStepKey` nv1/nv2. Impact : ne
  pas retoucher la frise `saisie_historique`/`deja_valide` ; débloquer en
  changeant `factures.statut` → `a_comptabiliser` (bouton Comptabiliser).
- **#1486** (LEÇON) — enseigne = `programmes.enseigne_id`. Reliquat 1634/1315
  (`deja_reglee=0`) hors reprise. Ne pas modifier
  `FactureWorkflowRealignementService`.
- **#1485** (LEÇON) — badge ≠ filtre. Ne pas toucher `FactureGlobale*` /
  `Global.vue`.

## SYNTHÈSE

### Statut de clôture retenu : `sans_objet` (valeur ENUM **nouvelle**)

Valeurs existantes de `workflow_validations.statut` (migration
`2026_04_22_100200` + usages) : `en_attente`, `valide`, `rejete`, `relance`.
`relance` n’est jamais écrit dans l’appli.

Aucune ne signifie « clôturé sans validation, sans objet » :
- `valide` — personne n’a validé (interdit par le prompt) ;
- `rejete` — lu comme un rejet (frise `rejetee`) ;
- `relance` — relance, pas une clôture ;
- `en_attente` — ne ferme rien.

Migration MySQL : ajout de `sans_objet`. La ligne WV est conservée.

### Notification

Destinataire : `workflow_validations.validateur_id` en priorité ; fallback
NV1 = `ocr_raw.saisie.validateur_id` ; fallback NV2 =
`ValidateurNv2Resolver` (users table, pas Graph). Divergence WV/ocr : log
warning, on notifie le WV.

Cloche : `alertes.scenario` = `facture_deja_reglee_cloture_dest_{id}`
(≪ 64). Teams : `TeamsNotificationService::notifierUtilisateur` depuis le
contexte web (pas artisan). Reprise : `notify: false`.

### Commande

Signature littérale : `factures:cloture-deja-reglee-workflow`
(`--dry-run` par défaut, `--force` pour écrire, dépôts
835,836,837,840,1735). Namespace `factures` (déjà existant).

### (d) Décocher

Ne réouvre pas les WV. Les `sans_objet` restent ; le statut reste
`a_comptabiliser`. Relancer un circuit exigerait un nouvel envoi.

## DÉPLOIEMENT-TEST

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

Puis `php artisan factures:cloture-deja-reglee-workflow` (dry-run) puis
`--force`. Recoupement SQL : voir synthèse.

## LEÇON

Cocher `deja_reglee` *après* ouverture d’un WV ne doit pas seulement poser
un drapeau/frise : il faut clôturer le circuit (`sans_objet`, pas `valide`)
et aligner `factures.statut` / `depot_factures.statut` sur l’enum réel
(`a_comptabiliser`). `relance` dans l’enum WV n’est pas un fourre-tout.
`alertes.scenario` VARCHAR(64) : scénario court + `_dest_{id}`. Commande
artisan : le token avant le premier `:` doit être un namespace existant
(`factures:`, pas `depot:`).
