Problème (vérifié LIVE sur la sandbox, 2026-07-11)
Les ids de transaction Qonto font ~67 caractères (arcodange-1246-1-transaction-019f14c5-e254-7ac9-9e9f-307ed9-d55f44) alors que Dolibarr stocke num_payment en varchar(50) (llx_paiement.num_paiement, llx_paiementfourn.num_paiement). Un POST /supplierinvoices/{id}/payments avec l'id complet échoue en HTTP 400 « value too long for type character varying(50) ». Les ids Wise (numériques courts, ex. 2159468139) passent.
Parade appliquée en live : stocker le suffixe UUID (strip du préfixe <org>-<n>-<n>-transaction-, reste ~37 chars, globalement unique) — 4 règlements fournisseurs enregistrés ainsi sur la sandbox (num ex. 019f14c5-e254-7ac9-9e9f-307ed9-d55f44). Cette PR fait de cette forme courte le format canonique, des deux côtés.
Côté écriture — dolibarr-sandbox-write/scripts/payment-record.sh
Normalise transaction_id avant POST : strip ^.*transaction- (pattern Qonto), les ids Wise passent inchangés.
Si le résultat dépasse encore 50 chars → erreur explicite citant varchar(50), avant tout POST — jamais de troncature silencieuse.
La normalisation est annoncée sur stderr ; la sortie JSON (transaction_id) émet le num normalisé réellement stocké (y compris sur le fallback de corrélation).
Côté lecture — arcodange-bank-reco/scripts/bank-match.sh (PASS 0, erp#28)
Les feed ids Qonto sont portés sous les deux formes (longue brute + courte canonique) et le num Dolibarr est comparé brut ET normalisé → un règlement stocké en forme courte (varchar(50)) ou longue (historique) matche dans tous les cas. Ids Wise intouchés.
Nouveau mode offline --fixtures DIR (aucun credential, aucun réseau) pour prouver le matcher sur fixtures — les pulls live sont inchangés hors de ce mode.
Docs
Les deux SKILL.md documentent le format canonique court + la contrainte varchar(50) (et l'exemple de payment-record.sh montre un id Qonto réel → num stocké court).
Vérifications faites (lecture seule — rien écrit vers sandbox/prod)
bash -n OK sur les deux scripts (aussi rejoué dans chaque runner).
arcodange-bank-reco/tests/run-tests.sh → PASS : fixture txid-normalize (feed long ↔ num court, feed long ↔ num long back-compat, Wise numérique — chaque paire à Δ+19j, hors fenêtre ±7j, donc seul le PASS 0 peut les apparier) → exit 0, 3×[tx-id], buckets propres ; fixture txid-no-num (num vide) → exit 1, 0 matched.
dolibarr-sandbox-write/tests/run-tests.sh → PASS : payment-record.sh exercé de bout en bout via un stub dol-write.sh injecté par le hook DOL_WRITE (long→court dans le body POST + JSON de sortie, Wise inchangé sans annonce, id >50 après normalisation refusé avant tout POST avec varchar(50) dans le message).
Sortie fixture-mode observée : les 3 paires matchées ↔[tx-id] avec Δ+19d, exit 0.
Non touché (travail parallèle) : test/scripts/admin/permissions.ts, .claude/skills/dolibarr-sandbox-checkpoint/scripts/*.
## Problème (vérifié LIVE sur la sandbox, 2026-07-11)
Les ids de transaction **Qonto** font ~67 caractères (`arcodange-1246-1-transaction-019f14c5-e254-7ac9-9e9f-307ed9-d55f44`) alors que Dolibarr stocke `num_payment` en **varchar(50)** (`llx_paiement.num_paiement`, `llx_paiementfourn.num_paiement`). Un `POST /supplierinvoices/{id}/payments` avec l'id complet échoue en HTTP 400 « value too long for type character varying(50) ». Les ids **Wise** (numériques courts, ex. `2159468139`) passent.
Parade appliquée en live : stocker le **suffixe UUID** (strip du préfixe `<org>-<n>-<n>-transaction-`, reste ~37 chars, globalement unique) — 4 règlements fournisseurs enregistrés ainsi sur la sandbox (num ex. `019f14c5-e254-7ac9-9e9f-307ed9-d55f44`). Cette PR fait de cette forme courte le **format canonique**, des deux côtés.
## Côté écriture — `dolibarr-sandbox-write/scripts/payment-record.sh`
- Normalise `transaction_id` avant POST : strip `^.*transaction-` (pattern Qonto), les ids Wise passent inchangés.
- Si le résultat dépasse encore 50 chars → **erreur explicite citant varchar(50), avant tout POST** — jamais de troncature silencieuse.
- La normalisation est annoncée sur stderr ; la sortie JSON (`transaction_id`) émet le **num normalisé** réellement stocké (y compris sur le fallback de corrélation).
## Côté lecture — `arcodange-bank-reco/scripts/bank-match.sh` (PASS 0, erp#28)
- Les feed ids Qonto sont portés sous **les deux formes** (longue brute + courte canonique) et le `num` Dolibarr est comparé **brut ET normalisé** → un règlement stocké en forme courte (varchar(50)) **ou** longue (historique) matche dans tous les cas. Ids Wise intouchés.
- Nouveau mode offline `--fixtures DIR` (aucun credential, aucun réseau) pour prouver le matcher sur fixtures — les pulls live sont inchangés hors de ce mode.
## Docs
Les deux `SKILL.md` documentent le format canonique court + la contrainte varchar(50) (et l'exemple de `payment-record.sh` montre un id Qonto réel → num stocké court).
## Vérifications faites (lecture seule — rien écrit vers sandbox/prod)
- `bash -n` OK sur les deux scripts (aussi rejoué dans chaque runner).
- **`arcodange-bank-reco/tests/run-tests.sh`** → PASS : fixture `txid-normalize` (feed long ↔ num court, feed long ↔ num long back-compat, Wise numérique — chaque paire à Δ+19j, hors fenêtre ±7j, donc seul le PASS 0 peut les apparier) → exit 0, 3×`[tx-id]`, buckets propres ; fixture `txid-no-num` (num vide) → exit 1, 0 matched.
- **`dolibarr-sandbox-write/tests/run-tests.sh`** → PASS : `payment-record.sh` exercé de bout en bout via un stub `dol-write.sh` injecté par le hook `DOL_WRITE` (long→court dans le body POST + JSON de sortie, Wise inchangé sans annonce, id >50 après normalisation refusé **avant** tout POST avec varchar(50) dans le message).
- Sortie fixture-mode observée : les 3 paires matchées `↔[tx-id]` avec `Δ+19d`, exit 0.
- Non touché (travail parallèle) : `test/scripts/admin/permissions.ts`, `.claude/skills/dolibarr-sandbox-checkpoint/scripts/*`.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Qonto transaction ids run ~67 chars (<org>-<n>-<n>-transaction-<uuid>) but
Dolibarr stores num_payment in varchar(50) (llx_paiement.num_paiement,
llx_paiementfourn.num_paiement) — POSTing a payment with the raw id fails
HTTP 400 "value too long for type character varying(50)". Parade proven live
on the sandbox (2026-07-11): store the UUID suffix (globally unique, ~37
chars). Wise ids (short numerics) are unaffected.
Writer side — payment-record.sh strips everything through "transaction-"
before POST, announces the normalization on stderr, REFUSES (never truncates)
ids still >50 chars after normalization, and emits the normalized num in the
output JSON.
Reader side — bank-match.sh PASS 0 (exact tx-id, erp#28) now compares BOTH
sides in raw AND canonical short form: Qonto feed ids are carried long+short,
payment nums are normalized on compare — so nums stored short (the varchar(50)
form) and historical long-form nums both keep matching. Wise ids untouched.
Proven offline (no credentials, no network, no sandbox/prod writes):
- arcodange-bank-reco/tests/run-tests.sh — new bank-match --fixtures offline
mode: long feed id ↔ short num, long ↔ long (back-compat), Wise numeric,
each Δ+19d outside the ±7d window so only PASS 0 can pair them (exit 0,
3×[tx-id]); plus the empty-num negative (exit 1, 0 matched).
- dolibarr-sandbox-write/tests/run-tests.sh — payment-record via a stubbed
dol-write.sh (DOL_WRITE hook): long→short in POST body + output JSON, Wise
untouched, >50-after-normalization refused BEFORE any POST, citing
varchar(50).
Both SKILL.md document the canonical short form + the varchar(50) constraint.
Co-Authored-By: Claude Fable 5 <[email protected]>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Problème (vérifié LIVE sur la sandbox, 2026-07-11)
Les ids de transaction Qonto font ~67 caractères (
arcodange-1246-1-transaction-019f14c5-e254-7ac9-9e9f-307ed9-d55f44) alors que Dolibarr stockenum_paymenten varchar(50) (llx_paiement.num_paiement,llx_paiementfourn.num_paiement). UnPOST /supplierinvoices/{id}/paymentsavec l'id complet échoue en HTTP 400 « value too long for type character varying(50) ». Les ids Wise (numériques courts, ex.2159468139) passent.Parade appliquée en live : stocker le suffixe UUID (strip du préfixe
<org>-<n>-<n>-transaction-, reste ~37 chars, globalement unique) — 4 règlements fournisseurs enregistrés ainsi sur la sandbox (num ex.019f14c5-e254-7ac9-9e9f-307ed9-d55f44). Cette PR fait de cette forme courte le format canonique, des deux côtés.Côté écriture —
dolibarr-sandbox-write/scripts/payment-record.shtransaction_idavant POST : strip^.*transaction-(pattern Qonto), les ids Wise passent inchangés.transaction_id) émet le num normalisé réellement stocké (y compris sur le fallback de corrélation).Côté lecture —
arcodange-bank-reco/scripts/bank-match.sh(PASS 0, erp#28)numDolibarr est comparé brut ET normalisé → un règlement stocké en forme courte (varchar(50)) ou longue (historique) matche dans tous les cas. Ids Wise intouchés.--fixtures DIR(aucun credential, aucun réseau) pour prouver le matcher sur fixtures — les pulls live sont inchangés hors de ce mode.Docs
Les deux
SKILL.mddocumentent le format canonique court + la contrainte varchar(50) (et l'exemple depayment-record.shmontre un id Qonto réel → num stocké court).Vérifications faites (lecture seule — rien écrit vers sandbox/prod)
bash -nOK sur les deux scripts (aussi rejoué dans chaque runner).arcodange-bank-reco/tests/run-tests.sh→ PASS : fixturetxid-normalize(feed long ↔ num court, feed long ↔ num long back-compat, Wise numérique — chaque paire à Δ+19j, hors fenêtre ±7j, donc seul le PASS 0 peut les apparier) → exit 0, 3×[tx-id], buckets propres ; fixturetxid-no-num(num vide) → exit 1, 0 matched.dolibarr-sandbox-write/tests/run-tests.sh→ PASS :payment-record.shexercé de bout en bout via un stubdol-write.shinjecté par le hookDOL_WRITE(long→court dans le body POST + JSON de sortie, Wise inchangé sans annonce, id >50 après normalisation refusé avant tout POST avec varchar(50) dans le message).↔[tx-id]avecΔ+19d, exit 0.test/scripts/admin/permissions.ts,.claude/skills/dolibarr-sandbox-checkpoint/scripts/*.🤖 Generated with Claude Code