Module Lettrage
Réconciliation de transactions bancaires contre les données contrats/factures — Ekwateur SA + PRO
Qu'est-ce que le lettrage ?
Le lettrage (en anglais "reconciliation" ou "matching") est le processus de rapprochement entre des transactions bancaires importées depuis un CSV et les données contractuelles/factures d'Ekwateur.
Chaque ligne importée représente un mouvement bancaire (débit ou crédit). L'équipe comptable doit confirmer que chaque transaction a bien été traitée (lettrée) ou la marquer comme non-lettrable, exclue, archivée.
La distinction
Architecture technique
| Couche | Technologie | Rôle |
|---|---|---|
| Backend | NestJS 11 | Controller + Service Lettrage |
| Queue | BullMQ | Import CSV asynchrone |
| BDD | PostgreSQL + Prisma 7 | Stockage lignes, imports, règles, prefs |
| Frontend | React 19 + TypeScript | Table virtuelle, filtres, dashboard |
| Permissions | RBAC custom | Granularité par action (voir/créer/modifier/supprimer) |
Fichiers clés
apps/api/src/lettrage/
├── lettrage.controller.ts ← 35 endpoints REST
├── lettrage.service.ts ← Logique métier (500+ lignes)
├── lettrage-import.processor.ts ← Processeur BullMQ CSV (400+ lignes)
└── lettrage.module.ts ← Module NestJS
apps/web/src/
├── pages/
│ ├── LettragePage.tsx ← Interface principale de traitement
│ ├── LettageDashboardPage.tsx ← Dashboard 11 sections
│ └── LettrageHistoriquePage.tsx ← Timeline des événements
├── hooks/useLettrage.ts ← 15+ hooks React Query
└── admin/
├── LettrageAdminTab.tsx ← Config mapping/banques/colonnes
├── LettrageSeuilsTab.tsx ← Seuils alertes
└── ReglesExclusionTab.tsx ← Constructeur de règles
Concepts & Terminologie
Vocabulaire métier et équivalences code/UI
| Terme UI | Champ BDD | Type | Signification |
|---|---|---|---|
| Non lettré | statutLettrage = 'non_lettre' |
Statut | Transaction importée, pas encore traitée par l'équipe |
| Partiel | statutLettrage = 'PARTIAL' |
Statut | Correspondance partielle — le champ restant est > 0 |
| Lettré | traite = true |
Booléen | Confirmé manuellement par un utilisateur. Historiquement "traité" dans le code |
| Exclue | statutLettrage = 'exclue' |
Statut | Ignorée par règle automatique ou action manuelle. Cachée par défaut |
| Archivée | statutLettrage = 'archivee' |
Statut | Clôturée, réouvrable si nécessaire |
| Non lettrable | nonLettrable = true |
Flag | Marquée comme impossible à lettrer (ne change pas le statut) |
| Réouverte | reouvert = true |
Flag | Était lettrée/archivée, réapparaît avec statut NL/Partiel dans un nouvel import |
| Restant | restant Decimal(15,2) |
Montant | Montant non encore réconcilié. 0 = totalement lettré |
| Sens | sens ENUM |
Direction | CRDT = Crédit entrant, DBIT = Débit sortant |
| Entité | Via banque → LettrageBank.entite |
SA/PRO | Déterminée par la banque de la ligne, pas stockée directement sur la ligne |
| Code lettrage | codeLettrage String? |
Identifiant | Code de regroupement de transactions liées (peut être null) |
| Seuil | AppSetting.seuil_gros_montant_sa/pro |
Config | Montant déclenchant les alertes "gros montants" dans le dashboard |
traite, statut 'traite') s'affiche "Lettré" dans l'UI depuis la refonte de mai 2026. Ne pas confondre lors de la lecture du code.Entité SA vs PRO
L'entité n'est pas stockée directement sur la ligne, mais déterminée via la table LettrageBank :
LettrageLigne.banque → LettrageBank.nom → LettrageBank.entite (SA | PRO | LES_DEUX)
L'admin peut reconfigurer à tout moment quel banque appartient à quelle entité via Admin → Banques SA/PRO.
Machine d'états
Cycle de vie d'une LettrageLigne
non_lettrePARTIAL ? cassetraite = trueexcluearchiveeCliquer sur un état pour filtrer les transitions — recliquer pour réinitialiser
Transitions possibles
nonLettrable=true
Flag orthogonal au statut — indique l'impossibilité métier
Flag reouvert
Lors d'un import, si une ligne existante était dans l'état traite=true ou archivee et qu'elle réapparaît dans le fichier CSV avec statutLettrage='non_lettre' ou 'PARTIAL', le processeur positionne reouvert=true.
Cela signale à l'équipe que la transaction a "régressé" et mérite une attention particulière. Le filtre "Réouvertes" dans l'interface permet de les retrouver rapidement.
Workflow Import CSV
Pipeline complet de traitement d'un fichier CSV
POST /lettrage/import — Multer reçoit le fichier CSV. Un enregistrement LettrageImport est créé avec statut='pending'.'process-csv'. Le jobId est stocké sur l'import. Réponse immédiate : { importId, jobId }.app_settings.csv_separator (défaut : ;). Configurable par l'admin.LettrageMapping (colonFichier → champQorvon) + auto-détection via CHAMPS_MAPPABLES. Chaque en-tête CSV est associé à un champ de LettrageLigne.Conversions : booléens (
t/true/1/oui), montants (virgule → point), dates (ISO ou JJ/MM/AAAA).
idTransaction dans le fichier courant. Les doublons sont loggés comme erreurs mais n'interrompent pas le traitement.idTransaction existe déjà en BDD. Si oui : mise à jour + gestion du flag reouvert. Sinon : création. Les lignes en BDD absentes du fichier sont marquées "disparues".LettrageRegleExclusion.actif=true) sont évaluées sur les nouvelles lignes. Les correspondances reçoivent exclueParRegle=true et statutLettrage='exclue'.LettrageSnapshot : comptages (NL/Partiel/Traité) et montants. Utilisé pour l'évolution historique dans le dashboard.LettrageImport.rollbackData. Permet l'annulation complète de l'import.statut='done', mise à jour des compteurs : nbLignes, nbNouvelles, nbMisesAJour, nbDisparues, finishedAt.
Rollback d'un import
POST /lettrage/imports/:importId/rollback — Nécessite que rollbackData soit présent sur l'import.
Ce que ça fait : restore les états précédents des lignes modifiées, supprime les nouvelles lignes créées par cet import, log un événement LettrageMasterRollback.
rollbackData est null. La suppression d'un import (DELETE) n'est possible que si nbLignes=0 ou statut='failed'.Lignes "disparues"
Quand un import ne contient plus une transaction qui existait en BDD, cette ligne est marquée "disparue". L'endpoint POST /lettrage/lignes/:id/resolve permet de la résoudre en la réouvrant ou en l'archivant.
Schéma Base de Données
Modèles Prisma du module lettrage
Table principale — LettrageLigne
| Champ | Type | Nullable | Description |
|---|---|---|---|
id | UUID | Non | Clé primaire |
idTransaction | String | Non | Identifiant unique de la transaction (source CSV) — unicité |
statutLettrage | StatutLettrage enum | Non | Statut principal de la ligne |
codeLettrage | String? | Oui | Code de regroupement de transactions liées |
dateOperation | DateTime? | Oui | Date de la transaction |
sens | SensLettrage enum | Non | CRDT (crédit) ou DBIT (débit) |
montant | Decimal(15,2)? | Oui | Montant total de la transaction |
restant | Decimal(15,2)? | Oui | Montant restant à réconcilier |
libelle | String? | Oui | Libellé de la transaction |
contrat | String? | Oui | Référence contrat |
facture | String? | Oui | Référence facture |
banque | String? | Oui | Nom de la banque → détermine l'entité SA/PRO |
classe, conso | String? | Oui | Classification interne |
gestionnaire | String? | Oui | Responsable |
domaine, famille, sousFamille, nature | String? | Oui | Hiérarchie de classification |
typeOperation, codeBank, entryErpFi | String? | Oui | Codes techniques |
iban | String? | Oui | IBAN associé |
rejet | Boolean | Non | Transaction en rejet |
codeRejet | String? | Oui | Code du rejet |
traite | Boolean | Non | Lettré (confirmé par l'utilisateur) |
traitePar | FK User? | Oui | Utilisateur ayant lettré |
traiteAt | DateTime? | Oui | Date/heure du lettrage |
nonLettrable | Boolean | Non | Marquée impossible à lettrer |
nonLettrablePar/At | FK/DateTime? | Oui | Audit du marquage |
exclueParRegle | Boolean | Non | Exclue automatiquement par une règle |
exclueParUser | Boolean | Non | Exclue manuellement |
exclueAt | DateTime? | Oui | Date de l'exclusion |
archivePar, archiveAt | String?/DateTime? | Oui | Audit de l'archivage |
reouvert | Boolean | Non | Réapparue après lettrage/archivage |
commentaire | String? | Oui | Note libre de l'utilisateur |
premiereVueAt, derniereVueAt | DateTime? | Oui | Timestamps de première/dernière occurrence en import |
createdAt, updatedAt | DateTime | Non | Audit standard Prisma |
LettrageImport — Suivi des fichiers importés
| Champ | Type | Description |
|---|---|---|
id | UUID | Clé primaire |
nomFichier | String | Nom du CSV uploadé |
statut | pending/processing/done/failed | État du traitement BullMQ |
jobId | String? | Référence du job BullMQ |
nbLignes | Int | Total de lignes dans le fichier |
nbNouvelles | Int | Lignes créées |
nbMisesAJour | Int | Lignes mises à jour |
nbDisparues | Int | Lignes présentes avant, absentes du fichier |
rollbackData | JSON? | États précédents pour annulation |
uploadedBy | FK User | Utilisateur ayant uploadé |
finishedAt | DateTime? | Fin du traitement |
snapshots | LettrageSnapshot[] | Stats par entité de cet import |
Tables de configuration & administration
Associe un nom de banque à une entité (SA, PRO, LES_DEUX). Sans mapping, la banque n'est pas filtrée par entité.
| Champ | Description |
|---|---|
nom | Nom unique (clé de jointure avec LettrageLigne.banque) |
entite | SA | PRO | LES_DEUX |
nomAffichage | Libellé affiché dans l'UI |
Associe un nom d'en-tête CSV au champ correspondant dans LettrageLigne. Si champQorvon est null, la colonne est ignorée.
Champs mappables : id_transaction, statut_lettrage, code_lettrage, date_operation, sens, montant, restant, libelle, contrat, facture, banque, classe, conso, gestionnaire, type_operation, entry_erp_fi, code_bank, domaine, famille, sous_famille, nature, iban, rejet, code_rejet, cree_par, annee
Règles déclaratives appliquées automatiquement à chaque import.
conditions: [
{ champ: "domaine", type: "equals", valeur: "SPAM" },
{ champ: "montant", type: "gt", valeur: "100000" }
]
actif: true/false
L'endpoint POST /admin/regles-exclusion/preview permet de tester une règle sur le dataset actuel avant de l'activer.
Toutes les actions sont loggées : action, fromStatut, toStatut, diff (JSON), isBulk.
Persistance par utilisateur des préférences UI : ordre des colonnes, largeurs, visibilité, filtres actifs.
Enums Prisma
StatutLettrage
SensLettrage
CRDT — Crédit (entrée)DBIT — Débit (sortie)
EntiteLettrage
API Endpoints
35 endpoints REST — NestJS 11 — Base : /lettrage
Import & Gestion des fichiers
| Méthode | Route | Permission | Description |
|---|---|---|---|
| POST | /lettrage/import | lettrage.creer | Upload d'un CSV — crée un job BullMQ |
| GET | /lettrage/import/:importId | lettrage.voir | Statut & progression d'un import |
| GET | /lettrage/imports | lettrage.voir | Liste de tous les imports |
| DELETE | /lettrage/imports/:importId | lettrage.supprimer | Suppression (uniquement si nbLignes=0 ou failed) |
| POST | /lettrage/imports/:importId/rollback | lettrage.supprimer | Annulation d'un import (nécessite rollbackData) |
Données & Filtres
| Méthode | Route | Permission | Description |
|---|---|---|---|
| GET | /lettrage/lignes | lettrage.voir | Lignes avec 30+ paramètres de filtre, pagination, tri |
| GET | /lettrage/export | lettrage.exporter | Export CSV avec les filtres courants |
| GET | /lettrage/filtres-valeurs | lettrage.voir | Valeurs distinctes pour tous les menus déroulants |
| GET | /lettrage/banques | lettrage.voir | Liste des banques avec leur entité |
| PUT | /lettrage/banques/:nom | lettrage.modifier | Créer ou mettre à jour le mapping banque → entité |
Actions sur les lignes
| Méthode | Route | Permission | Description |
|---|---|---|---|
| PATCH | /lettrage/lignes/:id | lettrage.modifier | Modifier une ligne (commentaire, statut) |
| POST | /lettrage/lignes/:id/resolve | lettrage.modifier | Résoudre une ligne "disparue" (réouvrir/archiver) |
| POST | /lettrage/lignes/bulk | lettrage.modifier | Action en masse : mark-traite, archive, exclude, reopen, mark-non-lettrable |
| GET | /lettrage/lignes/:id/events | lettrage.voir | Historique des événements d'une ligne |
Préférences utilisateur
| Méthode | Route | Description |
|---|---|---|
| GET | /lettrage/preferences | Récupérer préférences colonnes + filtres de l'utilisateur |
| PUT | /lettrage/preferences | Sauvegarder toutes les préférences |
| PATCH | /lettrage/preferences | Mise à jour partielle des préférences |
Administration
| Méthode | Route | Permission | Description |
|---|---|---|---|
| GET | /lettrage/admin/colonnes | administration.lettrage.voir | Configuration globale des colonnes |
| PUT | /lettrage/admin/colonnes | administration.lettrage.modifier | Modifier visibilité/ordre des colonnes globalement |
| GET | /lettrage/admin/mapping | administration.lettrage.voir | Mapping colonnes CSV |
| PUT | /lettrage/admin/mapping | administration.lettrage.modifier | Créer/modifier un mapping |
| DELETE | /lettrage/admin/mapping/:id | administration.lettrage.supprimer | Supprimer un mapping |
| GET | /lettrage/admin/regles-exclusion | lettrage.voir | Liste des règles d'exclusion |
| POST | /lettrage/admin/regles-exclusion | lettrage.modifier | Créer une règle |
| PATCH | /lettrage/admin/regles-exclusion/:id | lettrage.modifier | Modifier une règle |
| DELETE | /lettrage/admin/regles-exclusion/:id | lettrage.modifier | Supprimer une règle |
| POST | /lettrage/admin/regles-exclusion/preview | lettrage.voir | Prévisualiser l'impact d'une règle |
| POST | /lettrage/admin/regles-exclusion/appliquer | lettrage.modifier | Re-appliquer toutes les règles actives |
KPIs & Dashboard
| Méthode | Route | Permission | Description |
|---|---|---|---|
| GET | /lettrage/kpis | dashboard.lettrage.voir | KPIs rapides (6 compteurs, refresh 30s) |
| GET | /lettrage/dashboard | dashboard.lettrage.voir | Stats complètes dashboard (filtrables) |
| GET | /lettrage/snapshots | dashboard.lettrage.voir | Historique des snapshots par import |
Règles métier
Contraintes, calculs et comportements clés
Calcul des KPIs
| KPI | Règle de calcul |
|---|---|
| Non lettrées | statutLettrage = 'non_lettre' AND traite = false |
| Partielles | statutLettrage = 'PARTIAL' AND traite = false |
| Lettrées (traite) | traite = true (quel que soit le statut) |
| Non lettrables | nonLettrable = true AND statutLettrage IN [non_lettre, PARTIAL] |
| Réouvertes | reouvert = true |
| Nouvelles | premiereVueAt >= lastImport.finishedAt |
| Mises à jour | derniereVueAt >= lastImport.finishedAt AND premiereVueAt < lastImport.finishedAt |
| Délai moyen traitement | (traiteAt - premiereVueAt) / 3600000 en heures |
Règles de suppression/rollback
Suppression d'un import : uniquement si nbLignes = 0 (import vide) ou statut = 'failed'.
Rollback : uniquement si rollbackData est présent (non null) sur l'import.
Modification d'une ligne : un PATCH génère automatiquement un événement LettrageLignePatched avec l'ancien et le nouveau statut.
Règles d'exclusion automatiques
Les règles sont évaluées à chaque import. Elles peuvent être réappliquées manuellement via POST /admin/regles-exclusion/appliquer sur l'ensemble du dataset.
Une règle contient un tableau de conditions JSON. Toutes les conditions doivent être vraies (AND logique) pour déclencher l'exclusion.
{
"conditions": [
{ "champ": "domaine", "type": "equals", "valeur": "INTERNE" },
{ "champ": "montant", "type": "lt", "valeur": "10" }
],
"actif": true
}
Entité SA/PRO : règle de résolution
L'entité d'une ligne n'est jamais stockée directement sur LettrageLigne. Elle est résolue dynamiquement :
SELECT lb.entite FROM lettrage_banque lb WHERE lb.nom = ligne.banque
Si la banque n'est pas dans LettrageBank, la ligne n'apparaît dans aucun filtre entité (ni SA, ni PRO).
Unicité des transactions
Le champ idTransaction est unique en base. Deux imports du même fichier créeront des doublons détectés et loggés, mais pas persistés.
Lors d'une mise à jour (même idTransaction), les champs sont mis à jour et derniereVueAt est refreshé.
Filtres disponibles
30+ paramètres sur GET /lettrage/lignes
| Paramètre | Type | Description |
|---|---|---|
statut | StatutLettrage[] | Filtre multi-statuts (non_lettre, PARTIAL, traite, exclue, archivee) |
entite | SA | PRO | Entité via mapping banque (JOIN LettrageBank) |
banque | String | Banque exacte |
sens | CRDT | DBIT | Direction débit/crédit |
traite | boolean | Lettré ou non |
nonLettrable | boolean | Marqué comme impossible à lettrer |
reouvert | boolean | Réapparu après lettrage/archivage |
rejet | boolean | Transaction en rejet |
traitePar | String (userId) | Filtrer par utilisateur ayant lettré |
conso | String | Valeur de consolidation |
| Paramètre | Type | Description |
|---|---|---|
montantMin / montantMax | Decimal | Plage sur le montant total |
restantMin / restantMax | Decimal | Plage sur le montant restant |
restantNegatif | boolean | Lignes avec restant < 0 |
sansContrat | boolean | Lignes sans référence contrat |
sansFacture | boolean | Lignes sans référence facture |
dateDebut / dateFin | DateTime | Plage sur dateOperation |
annee | number | Année de dateOperation |
fichierId | UUID | Filtrer par import spécifique |
| Paramètre | Type | Description |
|---|---|---|
search | String | Recherche OR sur libelle + contrat + facture |
codeLettrage | String | Code de regroupement exact |
idTransaction | String | Transaction ID exacte |
contrat | String | Référence contrat exacte |
facture | String | Référence facture exacte |
iban | String | Recherche contains sur IBAN |
| Paramètre | Description |
|---|---|
typeOperation | Type d'opération |
codeBank | Code banque |
domaine | Domaine de classification |
famille | Famille |
sousFamille | Sous-famille |
nature | Nature |
creePar | Créateur de la transaction (source) |
codeRejet | Code du rejet |
| Paramètre | Valeur par défaut | Description |
|---|---|---|
sortBy | derniereVueAt | 24 champs triables (date, montants, libelle, statut...) |
sortOrder | desc | asc | desc |
limit | 50 | Lignes par page |
offset | 0 | Pagination offset |
total (count) et montantTotal (sum des montants filtrés).Permissions
Système RBAC — granularité par action
Permissions opérateurs
Permissions administration
lettrage.voir pour la lecture et le preview, et lettrage.modifier pour la création/modification/application — pas les permissions administration.*.Pages & Composants Frontend
Architecture React 19 — apps/web/src/
Table virtuelle avec 24 colonnes configurables. C'est la page principale utilisée au quotidien par l'équipe.
Colonnes visibles par défaut
Colonnes masquées par défaut
Actions disponibles
| Niveau | Actions |
|---|---|
| Ligne individuelle | Éditer commentaire, Marquer lettré, Marquer non-lettrable, Archiver, Exclure, Réouvrir, Voir historique |
| Bulk (sélection multiple) | Toutes les actions ci-dessus sur la sélection |
| Export | CSV avec les filtres courants |
Persistance : Largeur, ordre et visibilité des colonnes sont sauvegardés en BDD via UserPreferencesLettrage.
Dashboard hardcodé (refonte mai 2026). Filtres globaux : Année, Banque, Période, Entité (SA/PRO), Sens (Débit/Crédit).
| # | Section | Contenu |
|---|---|---|
| 1 | Statut global | 4 tuiles cliquables : Total / NL / Partiels / Lettrés. Grille 2×2 SA/PRO × Débit/Crédit |
| 2 | Alertes | NL critiques (90j + gros montant), Doublons, Sans contrat anciens |
| 3 | Évolution vs fichier précédent | 4 tuiles delta % (NL, Partiels, Lettrés, Total) |
| 4 | Qualité données | Sans contrat, Sans facture, Doublons, Gros montants SA/PRO (seuil configurable) |
| 5 | Ancienneté NL | Barres : ≤30j, 31-60j, 61-90j, >90j |
| 6 | Activité équipe | Lettrage aujourd'hui/semaine/mois + taux, délai moyen, utilisateurs actifs |
| 7 | Évolution montants | Graphe linéaire 6 séries (SA/PRO × NL/Partiels/Lettrés) |
| 8 | Détail par banque | Carte par banque : tableau Débit/Crédit/Total + barre progression |
| 9 | Détail par utilisateur | Carte par user : comptages + montant + dernière activité |
| 10 | Détail par fichier | Carte par import : décomposition Débit/Crédit |
| 11 | Imports récents | Liste des derniers imports avec statut |
/lettrage avec les query params pré-remplis pour filtrer directement.Timeline de tous les événements sur les lignes de lettrage. Filtrables par ligne, date, type d'action, utilisateur.
Source : table LettrageEvent. Endpoint : GET /lettrage/lignes/:id/events ? endpoint
| Composant | Onglet | Description |
|---|---|---|
LettrageAdminTab | Mapping colonnes | Associer en-têtes CSV aux champs LettrageLigne |
LettrageAdminTab | Banques SA/PRO | Assigner chaque banque à SA/PRO/LES_DEUX |
LettrageAdminTab | Colonnes globales | Visibilité/ordre par défaut pour tous les utilisateurs |
LettrageSeuilsTab | Seuils alertes | Montants déclenchant les alertes "gros montants" SA/PRO |
ReglesExclusionTab | Règles exclusion | Constructeur de règles avec prévisualisation + application |
Hooks React Query
| Hook | Cache key | Description |
|---|---|---|
useLettrageLignes(params) | ['lettrage','lignes',params] | Données paginées de la table principale |
useLettrageKpis() | ['lettrage','kpis'] | 6 compteurs, rafraîchissement toutes les 30s |
useLettrageImports() | ['lettrage','imports'] | Liste de tous les imports |
useLettrageImportStatus(id) | ['lettrage','import-status',id] | Polling du statut d'un import en cours |
useLettragesDashboard(params) | ['lettrage','dashboard',params] | Stats complètes dashboard filtrables |
useLettrageSnapshots() | ['lettrage','snapshots'] | Historique par import pour l'évolution |
useLettragesFiltresValeurs() | ['lettrage','filtres-valeurs'] | Valeurs pour les selects de filtres |
useLettragePatched() | — | Mutation PATCH ligne individuelle |
useBulkLettrage() | — | Mutation action en masse |
useLettrageUpload() | — | Mutation upload CSV |
Dashboard KPIs
Métriques exposées par GET /lettrage/dashboard et GET /lettrage/kpis
KPIs rapides (endpoint /kpis)
Stats dashboard complètes
Tous retournés avec segmentation SA/PRO × Débit/Crédit :
Pour chaque statut : count + montant + restant
| Métrique | Calcul |
|---|---|
| Sans contrat | Lignes actives où contrat IS NULL |
| Sans facture | Lignes actives où facture IS NULL |
| Restant négatif | Lignes où restant < 0 |
| Gros montants SA/PRO | Lignes NL/Partiel au-dessus du seuil configuré |
| Métrique | Description |
|---|---|
| traitéesAujourd'hui | Lignes lettrées aujourd'hui (traiteAt) |
| délaiMoyenTraitement | (traiteAt − premiereVueAt) / 3600000 → heures |
| dernierTraitement | ISO date du dernier lettrage |
| parUtilisateur | Count + montant + dernierTraitement par userId |
Tous disponibles dans /dashboard :
- parBanque : count + montant par banque
- parUtilisateur : count + montant + dernierTraitement par user
- parFichier : count + montant par import (fichierId)
- snapshots : évolution historique par import via
LettrageSnapshot
Snapshots — Évolution historique
À chaque import, un LettrageSnapshot est créé par entité (SA, PRO) avec les comptages et montants cumulés au moment de l'import.
Endpoint dédié : GET /lettrage/snapshots?banque=optional
Utilisé dans la section "Évolution montants" du dashboard (graphe linéaire).