---
suivi: 1941
date: 2026-10-16
sujet: Diagnostic Valider et Comptabiliser FE sans envoi Sage
chantier: factures-electroniques
type: diagnostic
statut: poussé
hash: 58641791c
fichiers:
  - docs/suivi/SUIVI_1941_diag_valider_comptabiliser_fe_sans_sage.md
---

# SUIVI #1941 — PHASE 1 diagnostic (aucun correctif)

Diagnostic uniquement. Aucun code métier modifié. Aucune migration. Aucun build.

## Fiches lues

- #1940 LEÇON : le raccourci FE a été branché sur `envoyerIntacctCompta` / ExtBillUpdate ; effet « déjà réglée » exclu ; messages hérités / paiement posés. Robin refuse l’envoi Sage depuis ce bouton.
- #1939 LEÇON : toast « Échec » + `MESSAGE_COMPTABILISATION` = hard-abort sur `validerEtComptabiliser`, pas le bouton Comptabiliser de la page Comptabilisation.
- #1853 LEÇON : seule vraie compta FE = ExtBillUpdate depuis l’écran Comptabilisation ; interrupteur + `FactureElectroniqueComptaAcces`.

## PROMPT ENVOYÉ

PHASE 1 diagnostic. Robin refuse que « Valider et Comptabiliser » envoie Sage pour une FE. Aligner sur le chemin classique (valider → page Comptabilisation). Conserver exclusion paiement FE et messages #1940. Requête de contrôle prod des FE éventuellement comptabilisées via ce bouton depuis #1940.

## 1. Chemin CLASSIQUE « Valider et Comptabiliser » (aujourd’hui)

Entrée HTTP : `POST /depot-factures/{uuid}/valider-et-comptabiliser` → `DepotFactureController::validerEtComptabiliser` (`DepotFactureController.php:2859`).

Après le garde FE (#1940), branche classique (`:2875-2905`) :

1. Verrous saisie / historique / archive (`:2875-2884`).
2. Si pas encore engagé : `resolveEngagementPayloadPourValiderEtComptabiliser` — exige `deja_reglee` + date + mode règlement (`:2887-2893`, resolve `:3124+`).
3. `DepotFactureValiderEtComptabiliserService::executer($depot, $user, $engagement)` **sans** `sansEffetPaiement` (`:2896`).
4. Réponse JSON : `success`, message « Facture prête pour comptabilisation. », + `facture_id`, `depot_uuid`, `redirect_url`, `niveaux_valides` (`:2901-2905`).

Dans le service (`DepotFactureValiderEtComptabiliserService.php`) :

| Étape | Lignes | Effet |
|---|---|---|
| Contrôle groupes compta/admin | `:49-51` | refus sinon |
| Exige `deja_reglee` | `:53-59` | |
| Engagement si besoin | `:62-74` → `DepotFactureEngagerWorkflowService` | pose `deja_reglee=true`, NV1 en attente |
| Auto-valide NV1 puis NV2 | `:82-100` | historique `valide_nv*_compta_deja_reglee` |
| Statuts cibles | `:105-111` | `facture.statut = a_comptabiliser`, `depot.statut = a_comptabiliser` |
| Photos jalon | `:114-121` | |
| Skip tâches NV1 déjà réglée | `:123-125` | |
| Retour | `:131-136` | `redirect_url` = `route('factures.comptabilisation', ['facture' => uuid])` → `/factures/comptabilisation?facture={uuid}` |

**Aucun appel Sage / Intacct / ExtBillUpdate / APBILL** dans la branche classique ni dans le service. Grep de `:2875-2905` : aucune mention Sage.

Front (`DepotFactureSaisieForm.vue:4444-4456`) : toast succès puis `router.visit(data.redirect_url)` → page Comptabilisation. L’utilisateur saisit les écritures et clique Comptabiliser (`envoyer-intacct-compta`).

## 2. Différence FE introduite par #1940

Branche FE dès `:2871-2872` → `validerEtComptabiliserFactureElectronique` (`:2911-2959`).

| Point | Classique | FE #1940 | Fichier:ligne |
|---|---|---|---|
| Interrupteur FE | n/a | `FactureElectroniqueComptaAcces::autorise` sinon `MESSAGE_MISE_EN_ROUTE` | `DepotFactureController.php:2917-2918` |
| Paiement « déjà réglée » | requis | forcé à false (`sansEffetPaiement`) | `:2922-2926`, `:2945`, `:2953` |
| Validation workflow | oui → `a_comptabiliser` | oui → `a_comptabiliser` (même service, flag) | `:2953` |
| Envoi Sage | **non** | **oui** : `envoyerIntacctCompta` → `executerComptabilisationApbill` → `completerBrouillonElectronique` / ExtBillUpdate | `:2958-2959` |
| Réponse | message + `redirect_url` | payload Sage (`success`, `message`, `intacct_bill_id`…) **sans** `redirect_url` | retour `:2959` vs classique `:2901-2905` |
| Front après succès | visit page Comptabilisation | toast seulement (pas de redirect) | `DepotFactureSaisieForm.vue:4454-4456` |

Cause racine du refus Robin : #1940 a interprété « valider puis comptabiliser via #1853 » comme un envoi Sage immédiat depuis le raccourci. La règle métier est : le raccourci ne fait que la validation / mise en file ; seule la page Comptabilisation envoie Sage.

## 3. Origine des textes de modale

| Texte | Origine | Fichier:ligne |
|---|---|---|
| Message principal FE : « … validée puis comptabilisée dans Sage. Le paiement se fait ensuite depuis le volet Paiement. Continuer ? » | Ajouté par #1940 | `DepotFactureSaisieForm.vue:4371-4374` (`validerEtComptabiliserConfirmMessage`) |
| Message principal classique : « … déjà réglée sera validée et passée en comptabilisation… » | Antérieur (#196) | même computed, branche else |
| Sous-texte fixe : « La comptabilisation Intacct se fera ensuite sur la page dédiée. » | Antérieur (#196, commit `291b102f1`) — **commun** FE et classique | `DepotFactureSaisieForm.vue:12623-12625` |

Contradiction : le message FE #1940 promet une comptabilisation Sage immédiate ; le sous-texte (inchangé depuis #196) promet encore la page dédiée. Les deux s’affichent ensemble dans le Dialog `:12613-12645`.

## 4. Correctif PHASE 2 proposé (ne pas faire ici)

Objectif : FE = même sémantique que classique pour ce bouton (valider → page Comptabilisation), avec les gardes FE déjà décidées.

1. **`validerEtComptabiliserFactureElectronique`** : supprimer l’appel `envoyerIntacctCompta` (`:2958-2959`). Après `$service->executer(..., sansEffetPaiement: true)`, retourner le **même** JSON que la branche classique (`success` + « Facture prête pour comptabilisation. » + spread du `$result` avec `redirect_url`).
2. **Conserver** : merge `deja_reglee=false`, `sansEffetPaiement: true`, case FE désactivée côté front, payload force sans paiement.
3. **Interrupteur** : le retirer de ce raccourci (`:2917-2918`) — il reste sur le bouton Comptabiliser / `executerComptabilisationApbill` / aperçu de la page Comptabilisation (`FactureElectroniqueComptaAcces`), comme demandé.
4. **Messages #1940 à conserver** : `MESSAGE_UTILISER_COMPTABILISER` (envoyerIntacct / avoir / comptabiliser local), `MESSAGE_PAIEMENT_VOLET` (`confirmerPaiementApresCompta`).
5. **Modale FE — texte proposé** (aligné sur le sous-texte existant) :
   > Cette facture électronique sera validée et passée en comptabilisation, sans marquer payée. Continuer ?
   Le sous-texte « La comptabilisation Intacct se fera ensuite sur la page dédiée. » reste pertinent et n’est plus contradictoire.
6. **Tests** : ajuster #1940 source test (plus d’`envoyerIntacctCompta` dans le raccourci) ; garder couverture exclusion paiement + messages hérités ; classique inchangé (diff à l’appui).
7. **Ne pas toucher** : ExtBillUpdate, contrôle centime, `montant_ht`, CIE, facture classique, second bill.

## 5. Requête de contrôle prod (lecture seule)

Bornes : commit #1940 `171386967` poussé le **2026-10-16 08:54:14 UTC**. Ajuster la date si le `git pull` OVH est plus tardif.

Marqueurs exclusifs du raccourci FE #1940 : actions historique `valide_nv1_compta_fe` / `valide_nv2_compta_fe` (absentes du flux Comptabiliser normal).

```sql
-- FE passées par le raccourci « Valider et Comptabiliser » depuis le déploiement #1940
SELECT
  df.id AS depot_id,
  f.reference,
  df.uuid,
  fh.created_at AS date_raccourci,
  df.intacct_brouillon_recordno AS recordno_brouillon,
  df.intacct_bill_id AS recordno,
  df.statut,
  fh.action,
  fh.commentaire,
  u.id AS user_id,
  u.name AS utilisateur,
  u.email
FROM facture_historique fh
INNER JOIN depot_factures df ON df.id = fh.depot_facture_id
LEFT JOIN factures f ON f.id = COALESCE(fh.facture_id, df.facture_id)
LEFT JOIN users u ON u.id = fh.user_id
WHERE df.facture_electronique = 1
  AND fh.action IN ('valide_nv1_compta_fe', 'valide_nv2_compta_fe')
  AND fh.created_at >= '2026-10-16 08:54:14'
ORDER BY fh.created_at, df.id, fh.action;
```

```sql
-- Sous-ensemble : celles pour lesquelles Sage a été soumis dans la foulée du raccourci (fenêtre 5 min)
SELECT
  df.id AS depot_id,
  f.reference,
  MIN(fh_fe.created_at) AS date_raccourci,
  df.intacct_bill_id AS recordno,
  df.statut,
  u.name AS utilisateur,
  u.email,
  MIN(fh_s.created_at) AS date_compta_sage
FROM facture_historique fh_fe
INNER JOIN depot_factures df ON df.id = fh_fe.depot_facture_id
LEFT JOIN factures f ON f.id = COALESCE(fh_fe.facture_id, df.facture_id)
LEFT JOIN users u ON u.id = fh_fe.user_id
INNER JOIN facture_historique fh_s
  ON fh_s.depot_facture_id = df.id
 AND fh_s.action IN ('intacct_comptabilisee', 'envoye_intacct_comptabilisee')
 AND fh_s.created_at >= fh_fe.created_at
 AND fh_s.created_at <= fh_fe.created_at + INTERVAL 5 MINUTE
WHERE df.facture_electronique = 1
  AND fh_fe.action IN ('valide_nv1_compta_fe', 'valide_nv2_compta_fe')
  AND fh_fe.created_at >= '2026-10-16 08:54:14'
GROUP BY df.id, f.reference, df.intacct_bill_id, df.statut, u.name, u.email
ORDER BY date_raccourci;
```

## Risques PHASE 2

- Faible : retirer l’envoi Sage du raccourci restaure le comportement attendu ; les FE déjà soumises via #1940 restent comptabilisées (ne pas rejouer ExtBillUpdate).
- Ne pas réintroduire `MESSAGE_COMPTABILISATION`.
- Ne pas rouvrir un second bill depuis le raccourci.
- Rebuild Vite si le texte de modale change ; vérifier `grep -c cie_effacement_confirme` = 1 sur le bundle.

## DÉPLOIEMENT-TEST

Aucun déploiement applicatif (fiche seule). OVH : rien. Lancer les requêtes SQL ci-dessus en lecture seule.

## LEÇON

« Valider et Comptabiliser » est un raccourci de **mise en file comptable**, pas d’envoi Sage — y compris pour une FE. Le flux #1853 (ExtBillUpdate) reste exclusivement derrière le bouton Comptabiliser de la page Comptabilisation. #1940 a fusionné à tort validation et soumission ; le sous-texte de modale (#196) le rappelait déjà.
