rapprochement-paiements — étape ⑤> Action humaine : pointer les relevés avec les factures et dire qui a payé quoi.
> Lecture seule sur clients/. Écrit l'état du suivi, dont les deux
> fichiers que le backend Pocket-Claw lit : company.json + rapprochement.json.
Le travail est fait par scripts/main.py. Ce skill = quand le lancer, **la passe
vision obligatoire**, et comment en rendre compte.
python3 scripts/main.py [<racine_clients>] # défaut : ./clients
À lancer après un classement de nouvelles pièces (le pipeline le fait
automatiquement), ou quand le comptable demande un point sur les paiements. Le
script retraite tout le dossier (cache reconstructible), écrit un
rapprochement.json par client + un rapport consolidé, puis imprime un résumé et
un auto-contrôle d'invariant.
Le parseur déterministe ne fait que PROPOSER ; c'est un gate arithmétique qui
porte la confiance. Un relevé dont ouverture + Σ opérations ≠ clôture, une
facture dont HT + TVA ≠ TTC, ou un PDF scanné sans texte sont signalés dans
needs_vision.json au lieu d'être trustés en silence. Quand le run en signale, tu
DOIS enchaîner :
python3 scripts/resolve_vision.py <racine_clients>
→ il prépare, pour chaque document, les images des pages + un squelette de
sidecar. Tu lis les images (outil Read), corriges le squelette (montants
SIGNÉS : crédit +, débit − ; champ illisible = null, jamais inventé ; pour un
relevé, vérifie ouverture + Σ = clôture), sauves dans , puis
relances main.py. Le sidecar fait alors autorité — mais repasse par le même
gate : un sidecar qui ne tombe toujours pas juste est RE-signalé (jamais masqué).
Pour chaque facture (ou note de frais), on cherche l'opération qui la solde, avec
des garde-fous qui évitent les faux rapprochements :
out) se solde par un crédit, un achat (in, factures fournisseurs ET notes de frais) par un débit. Jamais de
comparaison en valeur absolue.
référence facture, soit le nom de la contrepartie dans le libellé, soit une date
proche. Deux factures à 100 € pile ne se confondent pas. À score égal, la date
départage ; sinon on n'écrit rien et on signale match_ambigu.
(un paiement ne solde jamais deux factures). Les acomptes + solde d'une même
référence sont sommés.
espèces, virements internes et virements de particuliers sont catégorisés
(excluded_bank_lines) : jamais rapprochés, jamais signalés comme suspects.
servent encore au matching, mais ne produisent ni orphelin ni doublon tant que la
vision ne l'a pas corrigé (rien de flaggé n'est présenté comme fiable).
Statuts de facture : paid, partial (solde restant calculé), unpaid,
overdue (échéance dépassée → relance proposée).
rapprochement.json (periods[])Un objet {"periods": [...]}, une entrée par mois, **passée telle quelle au
front** (snake_case exact). Par période : bank_statements_count,
bank_transactions_count, bank_matched_count, et :
invoices[] — `invoice_id, type, counterparty_name, amount, issued_date,due_date, status, bank_matched, amount_paid, amount_remaining, anomalies[]`.
unmatched_bank_lines[] — opération sans facture en face : type (facture_manquante = débit sans justificatif, paiement_orphelin = crédit sans
facture de vente), label, amount (signé), date, invoice_ref.
excluded_bank_lines[] — opérations non facturables (avec category).period_anomalies[] — doublon_paiement, releve_non_parseable, facture_illisible.
relances[] — invoice_id, counterparty, amount, due_date, days_late, step, ….Invariant garanti (auto-contrôlé à chaque run, jamais KO) : pour chaque
période, `bank_matched_count + len(unmatched) + len(excluded) ==
bank_transactions_count` — toute opération du relevé est représentée exactement une
fois. company.json (identité) est rafraîchi en parallèle. Les mois passés
entièrement résolus sont verrouillés (batch.lock.json) et conservés tels
quels ; un fichier qui change rouvre le mois.
Dans le ton habituel, sans jargon ni chemin technique. Structure :
(c'est une étape du run, pas un échec).
incohérentes, en premier.
vente à facturer ?) et les retards (relance à envoyer ?).
Pour un rapprochement medium, mentionne le doute (« réglée, sous réserve »).
Quand des relances sont dues, propose de les envoyer (niveaux J+30 / J+60 / J+90 /
escalade). Ne jamais escalader sans l'accord du comptable.
vient du gate + vision. On ne patche pas le parseur banque par banque : un
format inconnu échoue le gate → vision (robuste), jamais d'erreur silencieuse.
in) et **ne se relancepas** (remboursement interne au salarié).
classement-document) et ne rédige pas les relances(workflow e-mail). Il rapproche, écrit l'état, et rend compte.
共 1 个版本