Une page unique, trois pavés, sans saut d'écran : sélectionner une écriture bancaire,
cliquer les factures qui la composent, et clôturer — le tampon, les écritures comptables de
contrepartie et le lettrage se font en un seul clic. Deux lectures indépendantes : une vue
métier (sans jargon technique) et une vue technique (tables, requêtes, fichiers).
Rubrique :
1. Pourquoi cette page existe
Le même rapprochement, sans les sauts d'écran
L'outil historique (Banq_ReleveBq.php) impose de sélectionner un
relevé, ouvrir une fenêtre de rapprochement, envoyer une sélection, revenir, valider l'import
GL séparément... Pour une grosse écriture ça passe, mais pour rapprocher une dépense de
quelques euros (un parking, un péage) contre son ticket, ce parcours coûte beaucoup plus de
clics que la difficulté réelle du rapprochement. Cette page fait la même chose — le même
tampon, les mêmes écritures comptables générées — mais sur un seul écran, avec un solde qui se
recalcule en direct au fil des clics.
2. Les 3 pavés, comment lire l'écran
Pavé
Contenu
Filtres
Gauche
Écritures bancaires non rapprochées (ReleveBanque.ETAT=0), groupées par banque
Banque, recherche libre dans le libellé
Haut droite
Factures d'achats et de ventes disponibles au rapprochement
Factures sélectionnées pour l'écriture bancaire en cours + solde à rapprocher + bouton Clôturer
Aucun (c'est la sélection en cours)
Le pavé gauche affiche un montant unique par écriture (au lieu de deux
colonnes Débit/Crédit) : un débit — une dépense — s'affiche en
rouge, pour repérer les sorties d'argent d'un coup d'œil. La colonne Libellé s'élargit
automatiquement pour occuper toute la place disponible du pavé (une poignée permet de la
réajuster manuellement si besoin).
3. Le flux pas à pas
Cliquer sur une écriture bancaire (pavé gauche) — elle se met en
surbrillance, et le "Solde à rapprocher" (pavé bas droite) prend sa valeur de départ.
Filtrer le pavé du haut pour retrouver la ou les factures concernées
(par annonceur, code facture, journal...).
Cliquer sur chaque facture à rapprocher — elle bascule du pavé du haut
vers le pavé du bas, et son montant se défalque du solde à rapprocher. Recommencer jusqu'à ce
que le solde affiche 0,00 € (il passe alors en vert).
Astuce — sous-total du pavé du haut : avant même de cliquer facture par
facture, un sous-total des lignes actuellement filtrées s'affiche à côté du compteur. Il passe
en vert dès que la somme des factures filtrées correspond exactement à ce qu'il reste à
rapprocher — un bon filtre (ex. un code facture) suffit alors à confirmer visuellement le bon
rapprochement avant de cliquer.
Cliquer "Clôturer l'écriture" (actif uniquement quand le solde est à
zéro) — un clic suffit, aucune confirmation supplémentaire ne s'affiche.
Se tromper de facture avant de clôturer ?
Cliquer sur une ligne du pavé bas droite (sélection) la retire et la renvoie dans le pavé du
haut — aucune écriture n'est faite en base tant que "Clôturer" n'a pas été cliqué. Le bouton
"Vider la sélection" retire tout d'un coup.
4. Ce que fait le bouton "Clôturer"
Trois opérations comptables en un seul clic
Historiquement, rapprocher une écriture bancaire nécessitait de déposer les factures dans un
tampon, PUIS d'aller valider séparément l'import des écritures GL. Ici, un seul clic sur
"Clôturer" enchaîne :
Dépôt des factures sélectionnées dans le tampon de rapprochement.
Génération des écritures comptables de contrepartie (la ligne banque et
les lignes de règlement) et passage de l'écriture bancaire à l'état "clôturée" — elle
disparaît alors du pavé gauche.
Lettrage immédiat : la facture d'origine et son écriture de règlement se
soldant à zéro sur le même compte, elles sont automatiquement marquées comme lettrées — pas
besoin de repasser par la page Lettrage séparément.
4bis. Solder un écart (arrondi, trop perçu / trop versé)
Quand les factures sélectionnées ne suffisent pas à ramener le solde à zéro
Un lien « + Ajuster l'écart », sous la liste des factures sélectionnées,
ouvre un petit pavé à 4 lignes (un compte à choisir + un montant chacune). Un bouton
« Ajouter » unique transforme les lignes remplies en entrées dans le pavé de
sélection, au même titre qu'une facture cliquée — même tableau, même calcul
de solde, retirables en cliquant dessus. Le formulaire se vide ensuite : on peut ainsi cumuler
autant de lignes d'ajustement que nécessaire (pas 4 au maximum — ex. deux clients différents
sur la même écriture). Dès qu'un compte est choisi sur une ligne, le montant nécessaire pour
ramener le solde courant à zéro est pré-rempli automatiquement (modifiable).
Ligne
Cas d'usage
Exemple
Compte de résultat
Écart d'arrondi/de règlement (petit montant) — part en perte ou profit
Facture 999,99 €, client paye 1000 € → 0,01 € sur le compte 758100000 (gain). Dans l'autre sens → 658100000 (perte).
Compte de bilan
Écart à ventiler sur un compte de bilan (hors client/fournisseur)
Cas particulier ne relevant ni d'un compte de résultat ni d'un tiers identifié.
Compte client
Trop perçu client (erreur du client, montant significatif) — reste sur son compte jusqu'au remboursement
Facture 1000 €, client paye 2000 € → les 1000 € en trop restent sur le compte du client, pas en perte/profit (ce n'est pas un écart, c'est une dette envers lui).
Compte fournisseur
Trop versé fournisseur — symétrique du cas client
Même logique, côté achats.
Les recherches "Compte de résultat" / "Compte de bilan" sont filtrées séparément
(TPCG.TYPE_BILAN) — chacune ne propose que les comptes de sa
catégorie. La ligne "Compte de résultat" propose en plus un axe analytique
(par défaut "FRAIS GENERAUX") — absent sur "Compte de bilan", qui n'en a pas besoin. Les
lignes "Compte client"/"Compte fournisseur" proposent quant à elles un
centralisateur (par défaut 411000000 / 401000000 — modifiable s'il existe
plusieurs centralisateurs pour le cas traité, ex. clients échange).
Le "trop perçu" laissé sur le compte client n'est pas oublié
Il apparaît ensuite comme une ligne disponible dans le pavé du haut (comme une facture
normale) pour le jour où le remboursement effectif du client sort en banque — il suffit de le
rapprocher à ce moment-là comme n'importe quelle autre écriture.
5. Ce que cette page ne fait pas (encore)
Paiements partiels — à venir
Une facture réglée en plusieurs virements n'est pas encore gérée avec un solde restant calculé
automatiquement (contrairement à Banq_ReleveBq.php) : une facture déjà touchée (même
partiellement) par un rapprochement disparaît simplement du pavé des factures disponibles,
sans proposer de solde restant à rapprocher. Ce sujet est prévu pour une prochaine évolution.
Pour les cas suivants, l'outil historique Banq_ReleveBq.php reste
disponible et doit être utilisé :
Cas
Pourquoi pas ici
Ligne bancaire sans facture GL correspondante (TVA, frais bancaires, salaires...)
Cette page ne rapproche que des factures GL existantes — pas de saisie de "ligne manuelle".
Annuler une clôture déjà validée
Pas de bouton "Dé-valider" ici — utiliser Banq_ReleveBq.php.
6. Glossaire
Solde à rapprocher
La différence, mise à jour en direct, entre le montant de l'écriture bancaire et la somme des factures déjà sélectionnées. Doit atteindre 0,00 € pour pouvoir clôturer.
Tampon (RapproBancaire)
La zone d'attente où sont déposées les factures rapprochées d'une écriture bancaire, avant génération des écritures comptables définitives.
Lettrage
Le fait de marquer une facture et son règlement comme définitivement "réglés l'un par l'autre" — ils se soldent à zéro sur le même compte.
Écriture clôturée
Une écriture bancaire dont le rapprochement est terminé : elle disparaît du pavé gauche (elle n'apparaît que tant qu'elle est en attente).
1. Vue d'ensemble du flux
ReleveBanque + GLchargés en un seul appel AJAX (ajax=data), rendus/filtrés 100% en JS — pas de phpGrid
→
Banq_Rappro_Express.php3 pavés HTML, sélection en mémoire JS, solde recalculé côté client
→
sql/Rappro_Express.phpcloseReleve() — validation puis mutation, appelé par ajax=close
Même esprit que Analyse_CA.php / EtatFi_BalGene.php :
volontairement sans C_DataGrid/phpGrid, tableaux HTML simples alimentés
en JSON, rendus et filtrés en JavaScript pur — page légère, pas de grille lourde.
2. Les requêtes sources (ajax=data)
ajax/Banq_Rappro_Express_ajax.php (action data)
charge en un seul aller-retour la liste des relevés, la liste des banques actives (filtre) et
le pool de factures — pas de pagination, pas de requête par filtre (tout est déjà en mémoire
côté client).
Relevés à rapprocher
SELECT ReleveBanque.ID_RELEVE, TListBanque.BANQUE, ReleveBanque.DATE_OPERATION,
ReleveBanque.LIBELLE_OPERATION, (ReleveBanque.DEBIT - ReleveBanque.CREDIT) AS MONTANT,
ReleveBanque.ECART
FROM ReleveBanque
INNER JOIN TListBanque ON TListBanque.ID_COMPTE = ReleveBanque.ID_COMPTE
INNER JOIN TPeriode ON TPeriode.ID_PERIODE = CONCAT(MONTH(DATE_OPERATION), YEAR(DATE_OPERATION))
WHERE ReleveBanque.ETAT = 0
AND TPeriode.CLOTURE = 0
Pourquoi filtrer TPeriode.CLOTURE=0 ici
Repris de Banq_ReleveBq.php : sans ce garde-fou, on pourrait
sélectionner un relevé dont la période comptable est déjà close puis cliquer "Clôturer" — le
bloc de génération GL (§4) filtre lui-même TPeriode.CLOTURE=0 et
n'insérerait alors aucune écriture GL tout en passant quand même
ETAT=1 (perte silencieuse de l'écriture comptable).
Pool de factures disponibles
SELECT GL.ID_GL, TJournal.CODE_JOURNAL, GL.DATE_COMPTABLE, ...
FROM GL
INNER JOIN TJournal ON TJournal.ID_JOURNAL = GL.ID_JOURNAL
INNER JOIN TAnnee ON TAnnee.ANNEE = YEAR(GL.DATE_COMPTABLE)
LEFT OUTER JOIN KM_MEDIAPILOT.MPClient ON MPClient.clnt_id = GL.ID_PAYEUR
LEFT OUTER JOIN KM_MEDIAPILOT.MPClient_custom ON MPClient_custom.CLNT_ID = MPClient.CLNT_ID
LEFT OUTER JOIN TSousGroupeClient ON TSousGroupeClient.ID_SOUSGROUPECLIENT = MPClient_custom.ID_SOUS_GROUPE_CLIENT
WHERE TAnnee.CLOTURE = 0
AND GL.ID_PHASE = 1
AND (GL.IS_LETTRAGE = 0 OR GL.IS_LETTRAGE IS NULL)
AND (LEFT(GL.CENTRALISATEUR, 3) = '401' OR LEFT(GL.CENTRALISATEUR, 3) = '411')
AND NOT EXISTS (SELECT 1 FROM RapproBancaire rb WHERE rb.ID_GL = GL.ID_GL)
Exclusion complémentaire volontairement simple : NOT EXISTS RapproBancaire
retire du pool toute facture déjà présente — même partiellement — dans le tampon d'un
autre relevé (pas de calcul de solde restant, cf. §6 limites).
2026-09 — Filtre TYPE_TIERS/ID_BASETVA remplacé par un filtre centralisateur
Le périmètre initial (repris de Banq_RapproBanq.php v1) filtrait sur
GL.TYPE_TIERS IN (1,2) et GL.ID_BASETVA IN (1,5,NULL).
Ni l'un ni l'autre n'empêchait en réalité la paie, les notes de frais ou les extournes de
provision (comptes 645xxx/641xxx/625xxx, TYPE_TIERS non renseigné)
de rentrer dès qu'un des deux filtres était retiré isolément — ce sont deux filtres orthogonaux
à la vraie question. Remplacés par LEFT(CENTRALISATEUR,3) IN ('401','411') :
cible directement les comptes collectifs client/fournisseur, ce qui exclut nativement toutes
ces écritures (elles n'ont jamais de centralisateur 401/411) sans dépendre de la bonne
saisie de TYPE_TIERS. Vérifié en base : sur le pool actuel, 100% des
lignes ont bien TYPE_TIERS 1 ou 2 (aucune ligne 0/NULL ne passe le
filtre centralisateur) — le déclenchement du lettrage à la clôture (§4, qui filtre encore
TYPE_TIERS IN (1,2)) reste donc pleinement cohérent avec ce nouveau pool.
3. Calcul du solde et du sous-total (JS)
Tout le calcul se fait côté client, sans aller-retour serveur, à chaque clic :
soldeARapprocher = currentReleve.ECART + somme(selectedInvoices[].MONTANT_SIGNE)
// Clôturer activé quand |soldeARapprocher| < 0.005
sousTotalFiltre = somme(rows visibles dans le pavé haut, apres filtres)[].MONTANT_SIGNE
sousTotalCorrespond = |sousTotalFiltre - (-soldeARapprocher)| < 0.005
currentReleve.ECART vient tel quel de la base (déjà maintenu par
MySQL, cf. §4) : partir de cette valeur plutôt que de recalculer
DEBIT - CREDIT gère automatiquement le cas — rare — d'un relevé déjà
partiellement travaillé via l'ancien outil.
4. La clôture en un clic (closeReleve)
ajax=close (POST, idReleve + ids[])
délègue tout le traitement à \BanqRapproExpress\closeReleve() dans
sql/Rappro_Express.php — l'endpoint AJAX ne fait que parser la requête
et traduire le résultat en JSON.
Phase 1 — validation seule (aucune écriture en base)
Relit ETAT/ECART du relevé depuis la
base — refuse si déjà clôturé (ETAT=1).
Relit les factures sélectionnées fraîches depuis la base (jamais les montants
envoyés par le client) — exclut celles déjà lettrées ou déjà déposées dans le tampon par
quelqu'un d'autre entretemps ; si le nombre de lignes trouvées ne correspond pas au nombre
demandé, refuse.
Recalcule l'écart final (ECART actuel + somme des montants relus)
et refuse si |écart| > 0.005.
Phase 2 — mutation (uniquement si la phase 1 est passée)
Dépôt tampon : INSERT INTO RapproBancaire ... SELECT ... FROM GL WHERE ID_GL IN (...)
(même requête que Banq_RapproBanq.php v1, étendue à une liste
d'ID_GL) + recalcul MONTANT_RAPPRO/ECART +
renumérotation NUM_LIGNE (row_number émulé en SQL) +
GL.PRELETTRAGE=1.
Écritures GL de contrepartie : reprise à l'identique du bloc SQL de
ajax/rappro_actions.php (action import_gl)
— dupliqué volontairement dans sql/Rappro_Express.php pour
ne pas toucher au flux existant de Banq_ReleveBq.php. Supprime
d'éventuelles écritures GL déjà générées pour ce relevé (journal banque,
TTypeJournal=3, période non close), puis réinsère la ligne banque et
les lignes de règlement (UNION), et passe ReleveBanque.ETAT=1.
Lettrage immédiat : reprise à l'identique du script
etats_financiers/sql/lettrage.php. Regroupe tous les
GL.PRELETTRAGE=1 de la base par (TYPE_TIERS, COMPTE)
dans Lettrage_Tampon ; les comptes dont la somme tombe exactement à
zéro sont marqués IS_LETTRAGE=1 (+ CODE_LETTRAGE,
DATE_LETTRAGE) et repassent PRELETTRAGE=0 ; les
autres restent en attente (PRELETTRAGE=1).
Aucune transaction SQL explicite (même convention que le reste de l'application — voir
executeSqlQueries() dans functions.php,
exécution séquentielle statement par statement). La phase 1 étant strictement en lecture, un
refus à cette étape ne laisse jamais la base dans un état intermédiaire.
4bis. Lignes d'ajustement (validateAdjustments)
closeReleve($db, $idReleve, $ids, $adjustments) accepte un 4e
paramètre optionnel — une liste (pas de limite fixe) de lignes complémentaires,
accumulées côté page (bouton "Ajouter" du pavé d'ajustement) et envoyées en un seul champ
POST adjustments encodé JSON (json_decode(...,
true) côté ajax=close) — pas de slots nommés fixes.
Aucune migration de schéma — l'axe analytique passe par PHP, pas par une colonne
RapproBancaire n'a historiquement vocation qu'à stocker des factures sélectionnées : pas de
colonne ajoutée. La ligne "compte_resultat" propose pourtant un vrai choix d'axe analytique
(GL.ID_AXE0, défaut 72 = FRAIS GENERAUX) — la valeur reste en mémoire
PHP le temps de closeReleve() (dans $adjValidation['items'])
et est injectée directement dans le SQL de génération GL sous forme d'un
CASE RapproBancaire.COMPTE WHEN ... THEN ... explicite construit
pour cette clôture précise (voir §"Génération GL" ci-dessous). RapproBancaire ne voit jamais
cette information passer.
validateAdjustments($db, $rawList)
Fonction pure de validation (aucune écriture), appelée en tout début de
closeReleve(), avant même la lecture de
ReleveBanque. Pour chaque ligne de la liste dont le montant est
non nul (> 0,0001 en valeur absolue — une ligne à montant vide est simplement ignorée),
relit la référence depuis la base — jamais les libellés envoyés par le client — et construit
un item normalisé. Une ligne malformée (compte/client/fournisseur/centralisateur/axe
introuvable, ou incohérence bilan/CdR) fait échouer toute la validation, sans
insertion partielle.
type
TYPE_TIERS
COMPTE
CENTRALISATEUR
ID_PAYEUR / manuel
id_axe0 (mémoire PHP)
compte_resultat
0
compte TPCG choisi (vérifié TYPE_BILAN='CdR')
= COMPTE (identique)
NULL
choisi, défaut 72
compte_bilan
0
compte TPCG choisi (vérifié TYPE_BILAN='Bilan')
= COMPTE (identique)
NULL
toujours NULL (pas de champ dans le formulaire)
client
1
MPClient.CODE_COMPTABLE
choisi, doit commencer par "411"
ID_PAYEUR = ID_CLTMANUEL = clnt_id
—
fournisseur
2
TFournisseurs.CODE_FOURNISSEUR
choisi, doit commencer par "401"
ID_PAYEUR = ID_FRSMANUEL = ID_FOURNISSEURS
—
La somme des montants validés (sum) s'ajoute à la somme des factures
pour le calcul de l'écart final (§4, phase 1).
Insertion du tampon (phase 2)
Chaque item validé génère un INSERT INTO RapproBancaire (...) VALUES (...)
direct (pas de SELECT ... FROM GL, il n'y a pas de facture source) —
même modèle que rappro_actions.php action add_manual :
ID_GL=0, CODE_FACTURE et
NUMERO_PIECE laissés NULL,
ID_STATUTRGLT=1, NUM_LIGNE=0 (renuméroté avec
toutes les autres lignes du relevé par le même bloc SQL de renumérotation que les lignes
facture). Ces INSERT sont concaténés avant le bloc de recalcul/renumérotation/génération GL.
Génération GL — CASE d'axe injecté
Juste avant d'assembler $sqlClose, closeReleve()
construit une table $axe0Overrides[COMPTE] = ID_AXE0 à partir des
seuls items compte_resultat de cette clôture, puis :
$axe0Sql = vide ? "CASE WHEN LEFT(COMPTE,1) IN (6,7) THEN 72 ELSE '' END" // règle historique seule, comportement 100% inchangé
: "CASE RapproBancaire.COMPTE
WHEN '758100000' THEN 72
WHEN '658100000' THEN 45
...
ELSE (règle historique ci-dessus)
END"
$axe0Sql remplace tel quel le CASE ... AS ID_AXE0
statique dans le SELECT de contrepartie (2e branche du UNION) — le reste du bloc de
génération GL est identique, ligne pour ligne, à avant l'ajout du pavé d'ajustement. Sans
aucun ajustement "compte de résultat" dans la clôture en cours, $axe0Sql
vaut exactement la règle historique : zéro changement de comportement pour le cas courant.
5. Tables impliquées
Table
Rôle dans ce flux
ReleveBanque
Écritures bancaires brutes. ETAT (0=à rapprocher, 1=clôturée), ECART = DEBIT - CREDIT + MONTANT_RAPPRO (le "solde à rapprocher" de départ).
GL
Écritures comptables — factures d'achats/ventes ET, après clôture, les écritures de contrepartie bancaires générées. PRELETTRAGE/IS_LETTRAGE pilotent respectivement le tampon et le lettrage final.
RapproBancaire
Le tampon — une ligne par facture déposée pour un relevé donné (ID_RELEVE, ID_GL, MONTANT_SIGNE).
TListBanque
Référentiel des comptes bancaires (BANQUE pour le regroupement/filtre, ACTIF pour la liste déroulante, COMTPE_BANQUE/ID_JOURNAL pour générer la ligne banque).
Lettrage_Tampon
Table de travail temporaire (TRUNCATE puis reconstruite à chaque clôture) utilisée uniquement par l'étape de lettrage.
6. Limites et points d'attention
Le lettrage traite toute la base, pas seulement le relevé en coursetats_financiers/sql/lettrage.php (repris tel quel) regroupe
tous les GL.PRELETTRAGE=1 existants, pas seulement ceux du
relevé qu'on vient de clôturer — comportement identique à l'outil historique. Un prélettrage
laissé en suspens ailleurs (ex. tampon non finalisé dans Banq_ReleveBq.php) peut donc être
lettré au passage s'il se solde lui aussi à zéro.
Pas de gestion des paiements partiels (facture réglée en plusieurs fois)
Le pool de factures exclut simplement toute facture déjà touchée par RapproBancaire
(NOT EXISTS, pas de solde restant calculé) — contrairement à
Banq_ReleveBq.php qui expose une colonne
SOLDE_RESTANT pour ce cas. La ventilation d'un écart résiduel vers un
compte de perte/profit ou un compte client/fournisseur (§4bis) est en revanche implémentée
depuis 2026-08 — ce point ne concerne donc que le règlement en plusieurs virements d'une même
facture, pas l'écart de règlement.
Bug de double-clic corrigé (2026-08)
Les champs de recherche texte (rxFTiers, rxFLibelle...)
n'écoutent que l'événement input, pas change.
change se déclenche au blur, c'est-à-dire au moment même où on clique
sur une ligne du tableau juste en dessous — ce qui reconstruisait le tableau
(innerHTML) en plein milieu du geste de clic et annulait ce premier
clic. Les <select> gardent change
(pas concernés par ce problème).
7. Fichiers concernés
Fichier
Rôle
Banq_Rappro_Express.php
Page principale — 3 pavés HTML, tout le rendu/filtrage en JS, sans phpGrid
Banq_Rappro_Express_Documentation.php
Cette page
ajax/Banq_Rappro_Express_ajax.php
Endpoint JSON — ajax=data (lecture), ajax=lookups (listes du pavé d'ajustement, paresseux), ajax=close (délègue à sql/Rappro_Express.php)
sql/Rappro_Express.php
Toute la logique de traitement — closeReleve() + validateAdjustments() (namespace BanqRapproExpress), validation puis mutation
Banq_ReleveBq.php
Outil historique multi-écrans — toujours disponible pour ligne manuelle, paiement partiel et dé-validation d'import
ajax/rappro_actions.php
Actions AJAX de l'outil historique — source du bloc SQL de génération GL, dupliqué dans sql/Rappro_Express.php
etats_financiers/sql/lettrage.php
Script de lettrage — repris tel quel (dupliqué) dans sql/Rappro_Express.php