---
suivi: 1794
date: 2026-10-06
sujet: Diagnostic import relevés multi-comptes
chantier: tresorerie
type: diagnostic
statut: poussé
hash:
fichiers:
  - docs/suivi/SUIVI_1794_diag_import_releves_multi_comptes.md
---

# SUIVI #1794 — diagnostic import relevés, plusieurs comptes

Phase 1. Aucun code. Aucune écriture Sage. Aucune écriture en base. Le classeur n'est pas dans le dépôt.

Fiches lues : #1726 (flux `xml` créés par l'API, imports écran en `onl`), #1739 (envoi test, un compte, aperçu, empreinte).

## 1. Outil actuel (#1739)

### a. Écran, route, droits

Page `resources/js/Pages/Admin/RelevesBancairesSage/Index.vue:129` « Lecture des flux bancaires Sage », puis `:175` « Test d'envoi — compte 512266 seulement ».

Routes `routes/web.php:1878-1889`, middleware `m365.groups:GS_DSI,GS_ADMIN_ERP` :

- GET `/admin/releves-bancaires-sage` → `ReleveBancaireSageLectureController::index`
- POST `.../lire` → `lire` (lecture Sage)
- POST `.../apercu` → `apercu`
- POST `.../envoyer` → `envoyer`

Le contrôleur revérifie les groupes en brut : `ReleveBancaireSageLectureController.php:84-88`, `m365GroupNames()`, `GS_ADMIN_ERP` ou `GS_DSI`.

Services : `ReleveBancaireSuiteEntrepriseParser` (lecture du fichier), `ReleveBancaireSageEnvoiTestService` (aperçu et envoi), `ReleveBancaireSageLectureService` (relecture des flux).

### b. Lecture Suite Entreprise

`ReleveBancaireSuiteEntrepriseParser.php:12-29` attend un texte ISO-8859-1 ou UTF-8, séparateur `;`, et ces 16 en-têtes, dans cet ordre : Date d'opération, Société, Compte, N° compte, Montant, Devise, Nature d'Opération, Code d'Opération, Date de valeur, N° Pièce, Libellé, Référence, Informations Complémentaires, Commentaire, Catégorie, Pointée.

Colonnes réellement utilisées :

- Date d'opération `:197-213` : `JJ/MM/AAAA` seulement. Refus sinon (`:78-79`).
- N° compte `:71-74` : IBAN, espaces et séparateurs retirés (`:134-139`).
- Montant `:216-238` : virgule décimale, signe conservé. Montant nul refusé (`:85-86`). Positif = `deposit`, négatif = `withdrawal` (`:112-113`). Envoi : `number_format` 2 décimales, point, signe gardé (`:241-243`). Le test fige un retrait en `<AMOUNT>-270.00</AMOUNT>` (`tests/Unit/ReleveBancaireSageEnvoi1739Test.php:99`).
- Libellé + Référence : description = libellé, espace, référence (`:274-281`).
- Informations Complémentaires : seulement pour réparer la référence (`:249-266`). Si la référence est vide ou en notation scientifique (`1,1027E+11`), reprise du jeton après `Reference:`.

Date de valeur, société, devise, nature, code, n° de pièce, commentaire, catégorie et pointée ne partent pas.

Le champ fichier n'accepte que `.csv,.txt` (`Index.vue:185`). L'upload est plafonné à 1024 Ko (`ReleveBancaireSageLectureController.php:61`).

### c. Rattachement

`ReleveBancaireSageEnvoiTestService.php:18` : `COMPTE_TEST = '512266'` en dur.

`:256-259` charge `intacct_financial_entities` où `type = bank_account` et `intacct_id = 512266` (`IntacctFinancialEntity.php:10` et `:44-46`). L'IBAN comparé est `bank_account_no`.

`:444-454` refuse le fichier si l'IBAN n'est pas exactement celui de 512266, ou si ce compte est absent du miroir.

`:120-123` du parseur : un fichier, un seul IBAN. Plusieurs IBAN = refus, avant même le test 512266.

La table existe (`hectareenvol.sql:2191-2198`) : `intacct_id`, `name`, `bank_account_no`, `gl_account_no`, `location_id`. `programmes.iban` est une autre colonne, lue seulement pour afficher les programmes liés au compte (`ReleveBancaireSageLectureService.php:133-141`). Ce n'est pas la clé de rattachement de l'envoi.

### d. Objet Sage

Un seul `create` / `BANKACCTTXNFEED` (`ReleveBancaireSageEnvoiTestService.php:237-247`) :

- `FINANCIALENTITY` = 512266
- `FEEDDATE` = date du jour, `m/d/Y` (`:105`)
- `FEEDTYPE` = `xml`
- par ligne : `TRANSACTIONTYPE`, `AMOUNT` (signé), `POSTINGDATE` en `m/d/Y` (mois/jour, `:212`), `DESCRIPTION`, `DOCNO` si la référence n'est pas vide

Aucune troncature de `DESCRIPTION` dans le XML (`:231`). Côté ERP, `description_normalisee` est un `varchar(500)` et `reference` un `varchar(120)` (`database/migrations/2026_09_28_173900_create_releves_sage_envois_test_table.php:24-25`). Le dépôt ne contient pas de longueur maximale Sage pour ce libellé. #1726 ne documente que les `FEEDTYPE` `xml` et `onl`.

Session : `envoyerXmlSessionLecture` (`:116`), même choix d'entité que la lecture (#1726).

### e. Anti-doublon

Empreinte SHA-256 de `intacct_id | date ISO | montant 2 décimales | description normalisée | référence` (`ReleveBancaireSuiteEntrepriseParser.php:150-158`).

Comparée à `releves_sage_envois_test.empreinte` (unique, `:328-339`). Une ligne déjà dans cette table est marquée « déjà envoyée » et sortie du XML. La table ne se remplit qu'après un `RECORDNO` (`:166-180`, `:350-375`).

Ce n'est pas une comparaison avec les lignes déjà dans Sage. La lecture (`ReleveBancaireSageLectureService.php:48-54`) ramène les en-têtes de flux : `RECORDNO`, `FINANCIALENTITY`, `FEEDDATE`, `FEEDTYPE`, `FILENAME`. Elle voit donc un flux `onl` (import écran) ou `xml`, pas les écritures qu'il contient. L'envoi ne s'en sert pas pour écarter une ligne. La case « Ces transactions ne sont pas déjà dans Sage sur ce compte » (`Index.vue:273`) est une confirmation humaine.

### f. Aperçu et trace

L'aperçu existe : `apercu()` (`:29-50`) ne crée rien. L'écran montre compte, totaux, et un tableau date / description / montant / dépôt ou retrait / référence / « déjà envoyée » ou « à envoyer » (`Index.vue:213-265`). Pas de case par ligne : tout ce qui n'est pas déjà envoyé part ensemble.

Après envoi : réponse brute, `RECORDNO`, relecture des flux, lignes écrites dans `releves_sage_envois_test` (`intacct_id`, date, montant, description, référence, empreinte, `sage_feed_recordno`, utilisateur, horodatage). Journal canal `intacct` à l'aperçu, à l'envoi, à la réponse et à la relecture. Pas de journal utilisateur (#1739).

#1739 indique que l'envoi réel et le rapprochement dans l'écran Sage n'avaient pas été faits.

## 2. Nouveau format

`storage/app/tmp` n'existe pas. Le classeur lu est « TEST INTEGRATION BQ.xlsx » (téléchargements), non copié. Une feuille `Feuil1`, ligne d'en-têtes + 45 lignes, colonnes A à P. Les en-têtes sont ceux du parseur #1739. Le fichier actuel serait refusé quand même : ce n'est pas un CSV (pas de `;`), les dates ne sont pas `JJ/MM/AAAA`, et il y a 6 IBAN.

### a. Colonnes et champs Sage

| Colonne | Contenu lu | Champ Sage actuel |
| --- | --- | --- |
| A Date d'opération | série Excel, 45/45. 46204 = 2026-07-01. Min 2026-07-01, max 2026-09-18 | `POSTINGDATE` (`m/d/Y`) |
| B Société | SAS HECTARE, 45/45 | aucun |
| C Compte | libellé du compte, pas l'identifiant Sage | sert à choisir `FINANCIALENTITY` seulement via l'IBAN |
| D N° compte | IBAN, 27 caractères, 6 valeurs | comparé à `bank_account_no` |
| E Montant | signé, 8 positifs, 37 négatifs, aucun nul | signe → `deposit` / `withdrawal` ; valeur → `AMOUNT` |
| F Devise | EUR partout | aucun |
| G Nature d'opération | 22 virements émis, 6 commissions, etc. | aucun |
| H Code d'opération | présent, non repris | aucun |
| I Date de valeur | série Excel, 45/45. Différente de A sur 7 lignes | aucun (la date envoyée est A) |
| J N° pièce | renseigné 45/45 | aucun |
| K Libellé | max 66 caractères, aucun au-delà de 80 | début de `DESCRIPTION` |
| L Référence | vide sur 34/45 | fin de `DESCRIPTION`, et `DOCNO` |
| M Informations complémentaires | vide sur 6/45. Clés : Info Compl 41, Beneficiaire 11, Debiteur 11, Libelle 7, Reference 7, Informations additionnelles 7, Compte 6, Ref Remise 6, Nom du debiteur 3, Reference bout-en-bout 3 | aujourd'hui, seulement le motif `Reference:` pour réparer L |
| N Commentaire | vide 45/45 | aucun |
| O Catégorie | vide 45/45 | aucun |
| P Pointée | vide 45/45 | aucun |

`FEEDDATE` reste la date du jour, pas une colonne. `FEEDTYPE` reste `xml`.

### b. IBAN (4 derniers chiffres)

Le miroir n'a pas été lu : MySQL `127.0.0.1:3306`, base `erp_immo`, connexion refusée. Aucun appel Sage. Pour les 6 IBAN, le compte Sage est donc non établi. Le rattachement prévu par le code est `bank_account_no` → `intacct_id`. 512266 est le seul identifiant accepté aujourd'hui ; le libellé BECM de ce fichier est « H BECM CARCA DOMAINE SOLEIL », pas le compte Campagnan cité pour 512266.

| Fin d'IBAN | Libellé (colonne C) | Lignes | Compte Sage |
| --- | --- | --- | --- |
| 0156 | H BECM CARCA DOMAINE SOLEIL 1 550 | 27 | non lu |
| 4401 | H CE CLOS PARC 750 | 9 | non lu |
| 5709 | H SG NEW MONTAIGUT 320 | 4 | non lu |
| 8795 | H SG NEW REVEL T1 T2 318 | 3 | non lu |
| 5813 | X CLOT H BNP BOUILLADISE | 1 | non lu |
| 2548 | X CLOT H CRCA MELODIE | 1 | non lu |

Le fichier a 6 IBAN, pas 7. Les six libellés sont BECM, CE, SG, SG, BNP, CRCA.

### c. Pièges

- Dates : numéro de série Excel, pas `JJ/MM/AAAA`. Le parseur les refuse (`:198-200`). 46204 = 2026-07-01.
- Montants : le XML du classeur stocke des flottants, par exemple `-64877.760000000002`, `-520.54999999999995`, `-1306.3499999999999`. Il faut arrondir au centime avant l'empreinte et avant `AMOUNT`. `montantSage()` le fait déjà pour un flottant proche (`:241-243`).
- Pointée : vide sur les 45 lignes. Rien à filtrer.
- Clôture : 2 lignes dont le compte commence par `X CLOT`. Libellés : « SOLDE BNP BOUILLADISE » (…5813) et « H CRCA CC » (…2548).
- Virements internes : 5 lignes ont un bénéficiaire (colonne M) qui contient HECTARE, 6 un bénéficiaire qui ne le contient pas, 34 n'ont pas de bénéficiaire. Le seul libellé K qui nomme un autre compte du groupe est « H CRCA CC », sur la ligne de clôture …2548.

## 3. Conclusion

Réutilisable : les 16 en-têtes, le signe du montant, la description libellé + référence, la réparation `Reference:`, le XML `BANKACCTTXNFEED` / `xml`, l'aperçu global, l'empreinte, la table `releves_sage_envois_test`, la table `intacct_financial_entities`.

Manque : lecture xlsx et dates série ; plusieurs IBAN dans un fichier ; rattachement par IBAN au lieu de 512266 en dur ; un flux par compte ; libellé métier (K + extrait de M, 80 caractères) ; exclusion des clôtures et des virements internes ; anti-doublon contre les lignes déjà dans Sage, y compris les flux `onl` ; cases par ligne.

Proposition, non codée :

1. Lire le xlsx (mêmes en-têtes) et convertir les séries Excel en dates.
2. Arrondir chaque montant au centime avant empreinte et avant `AMOUNT`.
3. Rattacher chaque IBAN à `intacct_financial_entities.bank_account_no` ; refuser la ligne si l'IBAN est inconnu. Plus de constante 512266.
4. Produire un flux `xml` par compte, pas un flux pour tout le fichier.
5. Libellé : K, plus l'info utile de M (Libelle / MOTIF sans « REF: », sinon bénéficiaire hors HECTARE, sinon nom du débiteur, sinon informations additionnelles sans numéros, sinon premier Info Compl utile), bruit retiré, 80 caractères. Hors de ce diagnostic, règle déjà validée.
6. Écarter les comptes `X CLOT` et les virements dont le bénéficiaire est HECTARE, et les montrer comme écartées.
7. Aperçu ligne à ligne, case par ligne, envoi limité aux lignes cochées.
8. Anti-doublon : garder l'empreinte ERP, et signaler un flux `onl` ou `xml` déjà présent sur le compte. La comparaison ligne à ligne avec Sage n'existe pas encore : la lecture ne ramène pas les écritures du flux.

## DÉPLOIEMENT

Fiche seule. Pas de migration. Pas de journal. Pas de build.

git pull origin main

## LEÇON

Le parseur #1739 et le classeur parlent le même tableau, mais le parseur ne lit qu'un CSV à un seul IBAN, et l'envoi ne connaît que 512266. Étendre le format sans ouvrir le rattachement IBAN enverrait tout sur le mauvais compte, ou rien.
