---
suivi: 1762
date: 2026-09-30
sujet: Marquer payées les factures historiques d'Eric PORTALES
chantier: factures
type: commande
statut: poussé
hash:
fichiers:
  - app/Services/FacturePaiementManuelHistoriqueService.php
  - app/Console/Commands/FacturesHistoriqueMarquerPayeesCommand.php
  - app/Support/FactureHistoriqueMasseCible.php
  - tests/Unit/FactureHistoriqueMassePayees1762Test.php
  - docs/suivi/SUIVI_1762_historique_eric_marquer_payees.md
---

# SUIVI #1762 — Factures historiques d'Eric, marquage payé en masse

## PROMPT ENVOYÉ

Marquer payées les factures de type Historique déposées par eric.portales@hectare.fr qui ne sont pas encore payées. Commande en deux temps (dry-run par défaut, puis --apply). Aucune écriture Sage. Date de paiement = date de règlement saisie, sinon vide. Saisie incomplète listée à part, non modifiée.

## FICHES LUES

- #1604 LEÇON : le payé manuel est le drapeau `paiement_manuel_*`, pas `etat_paiement_sage` (la synchro Sage mélangerait l'affichage).
- #1754 : la date « déjà réglée » de la frise est `date_reglement`, puis `intacct_when_paid`. `date_paiement` n'est pas la source de la frise.
- #1693 : constat de non-paiement Sage, pas le mécanisme de marquage.
- #1524 : une saisie historique n'est pas envoyée en comptabilisation.
- #1611 : `saisie_historique` n'est pas un type de document ; l'historique ne devient pas une facture Sage.

## CONSTAT

Type stocké sur le dépôt : `depot_factures.type_source = historique` (`DepotFacture::TYPE_SOURCE_HISTORIQUE`, `app/Models/DepotFacture.php:101`). À l'enregistrement, si `type_source` change, `saisie_historique` passe à vrai et `deja_reglee` aussi pour historique ou déjà réglée (`DepotFacture.php:226-240`).

Circuit : la boîte affiche le dépôt avant qu'une facture existe. « Valider (historique) » crée la facture en `statut = payee`, source `erp_upload` (`DepotFactureController.php:2933-2951`), recopie `date_reglement`, puis `finaliserStatutHistoriquePaye` (`3053-3066`) qui met le dépôt en `paye` et `date_paiement = date_reglement ?? date_paiement ?? now()`. Cette commande ne reprend pas ce `now()`. Le même écran collecte RG / CP et recalcule le marché (`3022-3037`). Ce lot ne le fait pas : Payé HT se lit via `FactureStatutService::estPayee` (`FactureStatutService.php:105`), sans écrire la ligne marché. Pas de facture Sage.

Payée dans l'ERP : facture `statut = payee` (`Facture.php:27`), dépôt `statut = paye`. `etat_paiement_sage = paye` veut dire payée par Sage. Le marquage manuel (#1604) pose `paiement_manuel_at`, `paiement_manuel_date`, `paiement_manuel_par_user_id`. Mécanisme réutilisé : `FacturePaiementManuelHistoriqueService::marquer` (fiche, date obligatoire, aucun appel Sage). La masse passe par `marquerMasse` : même écriture, date seulement si `date_reglement` est saisie.

Effets du passage à payée ici : statut facture et dépôt, historique `paiement_manuel` avec le texte « Marquée payée (historique) en masse par … », tâches « compléter la saisie », NV1, NV2 et virement fermées via les hooks existants (motif `deja_reglee_hors_circuit`, `Task.php:49`), alertes du dépôt retirées. Montants, marché, fournisseur : inchangés. Pas de lignes de retenue créées.

## SYNTHÈSE

`php artisan factures:historique-marquer-payees` liste sans écrire. `--apply` marque chaque facture complète dans sa propre transaction. Une erreur n'arrête pas les suivantes. Relance : les déjà payées sont ignorées. Sans facture, sans montant, sans fournisseur, ou dépôt rejeté / archivé : liste « incomplètes, non modifiées ».

Acteur de la trace : l'utilisateur dont le nom est exactement « Robin PORTALES » (un seul, sinon arrêt avant écriture). `Auth::setUser` pour que la clôture des tâches enregistre ce valideur.

## CLOSURES RELUES

- `marquer` : une transaction, appelle `appliquerMarquage` avec la date saisie à l'écran. Contrat inchangé (date obligatoire).
- `marquerMasse` : une transaction par facture. `appliquerMarquage` (date dépôt écrite seulement si `date_reglement`), puis `cloturerTachesSansObjet`, puis `AlerteService::retirerToutesAlertesDepot`.
- `appliquerMarquage` : pas de closure. Écrit le drapeau manuel. Si un paiement effectif est en attente et qu'une date existe, `confirmerPaiementEffectifManuel`. Sans date, le workflow passe à `valide` sans `date_validation` (pas de date inventée).
- `cloturerTachesSansObjet` : boucle sur les workflows NV1/NV2 encore `en_attente`, statut `sans_objet`, puis le hook de clôture du niveau. Pas de closure imbriquée.
- Commande : closure du `where` historique ; closure `whereHas` sur l'e-mail ; closure du `with` facture ; `array_map` d'affichage. La boucle `--apply` est un `try/catch` par facture, la transaction est dans le service.

## DÉPLOIEMENT-TEST

```
git pull origin main
php artisan optimize:clear
php artisan factures:historique-marquer-payees
php artisan factures:historique-marquer-payees --apply
php artisan factures:historique-marquer-payees
```

La troisième commande doit afficher « À marquer : 0 ». Pas de `migrate`, pas de `journal:sync`, pas de build.

## LEÇON

Ne pas réutiliser `finaliserStatutHistoriquePaye` pour une masse : il invente `now()` quand `date_reglement` est vide. Ne pas appeler `FactureDejaRegleeClotureWorkflowService` : il repasse la facture à comptabiliser. Le dry-run est le défaut ; `--apply` et `--dry-run` ensemble sont refusés.
