add dolibarr-payments-state skill for cash receipt tracking
V2 in the dolibarr-* family. Three workflows:
- km-payment-state.sh: per-invoice reconciliation (TTC vs sum of
payments) with OK / PARTIAL / UNPAID / OVERPAID classification.
More honest than the `paye` boolean for deferred-cycle agreements.
- km-payment-timeline.sh: all KM payments sorted by date with
cumulative balance — the foundation for cohort-review deferred
9-month-cycle tracking (actual cash receipts vs contractual schedule).
- payments-by-month.sh: monthly aggregation, KM-scoped by default
or --all-clients for accounting basis.
Also updates dolibarr/SKILL.md endpoint catalogue with
/invoices/{id}/payments (note the date-as-string vs unix-epoch quirk)
and /bankaccounts, plus captures the corresponding examples.
V1 baseline of live data: KM is fully reconciled across 5 invoices
(1 avoir + 4 regular), 8160 € total cash receipts spread Feb/Mar/Apr 2026,
all on WISE EURO (BE).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -88,6 +88,9 @@ Read-only endpoints we've validated against this instance. Live captures are und
|
||||
| `GET /users/info` | 200 | Current API user (auth sanity) | Returns `login`, `id`, `rights` tree | [users_info.json](examples/users_info.json) |
|
||||
| `GET /invoices` | 200 | List invoices | `limit`, `sortfield=t.datef`, `sortorder=DESC`, `status=draft\|unpaid\|paid`, `sqlfilters` | [invoices_list.json](examples/invoices_list.json) |
|
||||
| `GET /invoices/{id}` | 200 | Invoice detail | `paye=1` is the canonical "paid" flag | [invoice_detail.json](examples/invoice_detail.json) |
|
||||
| `GET /invoices/{id}/payments` | 200 | Payments applied to one invoice | Returns array of `{amount, type, date, num, ref, fk_bank_line}`. **`date` is a string `YYYY-MM-DD HH:MM:SS`, NOT unix epoch** like elsewhere. Amounts negative for AVOIRs. | [invoices_12_payments.json](examples/invoices_12_payments.json) |
|
||||
| `GET /payments` | 501 | (list-all not implemented) | Returns "API not found". To enumerate payments, iterate invoices. | — |
|
||||
| `GET /bankaccounts` / `/{id}` | 200 | List bank accounts / detail | Returns `ref`, `label`, `iban`, `country_code`. `fk_bank_line` on a payment doesn't directly map to the account id — see `dolibarr-payments-state` skill for the lookup. | [bankaccounts_list.json](examples/bankaccounts_list.json) |
|
||||
| `GET /thirdparties` | 200 | List thirdparties | `mode` MUST be integer (`mode=1` = customers). String fails 400. | (use `/{id}` below) |
|
||||
| `GET /thirdparties/{id}` | 200 | Thirdparty detail | KissMetrics is `id=1` in this instance | [thirdparty_km.json](examples/thirdparty_km.json) |
|
||||
| `GET /products` / `/products/{id}` | 200 | Product catalogue | `KM-audit` is `id=1` | — |
|
||||
@@ -118,11 +121,12 @@ Not available on this account (intentionally): `/setup/modules` (admin-only), `/
|
||||
|
||||
- **`mode` is an integer.** `?mode=1` works; `?mode=customer` → HTTP 400 `Invalid value specified for mode`.
|
||||
- **Empty list vs 404 vs 403.** `/invoices` returns `[]` (200) on empty/permission-filtered. `/thirdparties` returns 404 `"No third parties found"`. `/thirdparties/{id}` returns 403 if the ACL hides the row. All three can mean "no permission" — the diagnostic is to hit `/thirdparties/1` directly (see Permission gotcha above).
|
||||
- **Dates are unix epoch (seconds).** `.date`, `.datef`, `.date_lim_reglement`, `.tms` are integers.
|
||||
- **Dates are usually unix epoch (seconds)** on most objects: `.date`, `.datef`, `.date_lim_reglement`, `.tms` are integers.
|
||||
```bash
|
||||
python3 -c "import datetime,sys; print(datetime.datetime.fromtimestamp(int(sys.argv[1])))" 1771887600
|
||||
# → 2026-02-24 00:00:00
|
||||
```
|
||||
**Exception**: `/invoices/{id}/payments` returns `.date` as the string `"YYYY-MM-DD HH:MM:SS"`, not an int. Check the field type before parsing.
|
||||
- **`paye` is the paid flag, `status` is the workflow state.** `status=2` means "validated", `paye=1` means "fully paid". They're independent — a status-2 invoice can still be unpaid.
|
||||
- **`last_main_doc` paths** are relative to Dolibarr's document root. For `/documents/download`, pass `modulepart=facture` + URL-encoded `original_file=<dir>/<file>` (encode the `/`).
|
||||
- **`array_options=[]` vs `{}`.** Dolibarr returns `[]` when no extrafields are set and `{}` when there are some. Treat both as "no custom fields" in Python.
|
||||
@@ -130,6 +134,7 @@ Not available on this account (intentionally): `/setup/modules` (admin-only), `/
|
||||
## Pointers
|
||||
|
||||
- Workflow skill for invoice + thirdparty audits: [dolibarr-invoice-audit](../dolibarr-invoice-audit/SKILL.md).
|
||||
- Workflow skill for payment-state and cash-receipt tracking: [dolibarr-payments-state](../dolibarr-payments-state/SKILL.md).
|
||||
- Future workflow skills follow the `dolibarr-<topic>` convention. Each one depends on this skill for connection + permissions + endpoint reference; each one keeps its triggers focused on its specific business workflow.
|
||||
|
||||
## Out of scope
|
||||
|
||||
371
.claude/skills/dolibarr/examples/bankaccounts_list.json
Normal file
371
.claude/skills/dolibarr/examples/bankaccounts_list.json
Normal file
@@ -0,0 +1,371 @@
|
||||
[
|
||||
{
|
||||
"module": null,
|
||||
"id": "1",
|
||||
"entity": null,
|
||||
"import_key": null,
|
||||
"array_options": [],
|
||||
"array_languages": null,
|
||||
"contacts_ids": null,
|
||||
"contacts_ids_internal": null,
|
||||
"linkedObjectsIds": null,
|
||||
"canvas": null,
|
||||
"fk_project": null,
|
||||
"contact_id": null,
|
||||
"user": null,
|
||||
"origin_type": null,
|
||||
"origin_id": null,
|
||||
"ref": "QON1",
|
||||
"ref_ext": null,
|
||||
"statut": null,
|
||||
"status": "0",
|
||||
"country_id": "1",
|
||||
"country_code": "FR",
|
||||
"state_id": "378",
|
||||
"region_id": null,
|
||||
"barcode_type": null,
|
||||
"barcode_type_coder": null,
|
||||
"mode_reglement_id": null,
|
||||
"cond_reglement_id": null,
|
||||
"demand_reason_id": null,
|
||||
"transport_mode_id": null,
|
||||
"shipping_method_id": null,
|
||||
"shipping_method": null,
|
||||
"fk_multicurrency": null,
|
||||
"multicurrency_code": null,
|
||||
"multicurrency_tx": null,
|
||||
"multicurrency_total_ht": null,
|
||||
"multicurrency_total_tva": null,
|
||||
"multicurrency_total_localtax1": null,
|
||||
"multicurrency_total_localtax2": null,
|
||||
"multicurrency_total_ttc": null,
|
||||
"last_main_doc": null,
|
||||
"fk_account": null,
|
||||
"note_public": null,
|
||||
"note_private": null,
|
||||
"total_ht": null,
|
||||
"total_tva": null,
|
||||
"total_localtax1": null,
|
||||
"total_localtax2": null,
|
||||
"total_ttc": null,
|
||||
"lines": null,
|
||||
"actiontypecode": null,
|
||||
"name": null,
|
||||
"lastname": null,
|
||||
"firstname": null,
|
||||
"civility_id": null,
|
||||
"civility_code": null,
|
||||
"date_creation": 1769886460,
|
||||
"date_validation": null,
|
||||
"date_modification": 1769882860,
|
||||
"tms": null,
|
||||
"date_cloture": null,
|
||||
"user_author": null,
|
||||
"user_creation": null,
|
||||
"user_creation_id": null,
|
||||
"user_valid": null,
|
||||
"user_validation": null,
|
||||
"user_validation_id": null,
|
||||
"user_closing_id": null,
|
||||
"user_modification": null,
|
||||
"user_modification_id": null,
|
||||
"fk_user_creat": null,
|
||||
"fk_user_modif": null,
|
||||
"specimen": 0,
|
||||
"totalpaid": null,
|
||||
"extraparams": [],
|
||||
"product": null,
|
||||
"cond_reglement_supplier_id": null,
|
||||
"deposit_percent": null,
|
||||
"retained_warranty_fk_cond_reglement": null,
|
||||
"warehouse_id": null,
|
||||
"label": "QONTO",
|
||||
"courant": "1",
|
||||
"type": "1",
|
||||
"bank": "QONTO",
|
||||
"clos": "0",
|
||||
"rappro": "1",
|
||||
"url": "qonto.com",
|
||||
"code_banque": "16958",
|
||||
"code_guichet": "00001",
|
||||
"number": "90485256392",
|
||||
"cle_rib": "15",
|
||||
"bic": "QNTOFRP1XXX",
|
||||
"iban": "FR7616958000019048525639215",
|
||||
"iban_prefix": null,
|
||||
"pti_in_ctti": "0",
|
||||
"proprio": "ARCODANGE",
|
||||
"owner_name": "ARCODANGE",
|
||||
"owner_address": "73 boulevard de l'yerres",
|
||||
"owner_zip": "91000",
|
||||
"owner_town": "Courcouronnes",
|
||||
"owner_country_id": "1",
|
||||
"owner_country_code": null,
|
||||
"domiciliation": null,
|
||||
"address": "Qonto (Olinda SAS), 18 rue de Navarin, 75009 Paris, France",
|
||||
"type_lib": [
|
||||
"BankType0",
|
||||
"BankType1",
|
||||
"BankType2"
|
||||
],
|
||||
"account_number": "51211",
|
||||
"fk_accountancy_journal": "9",
|
||||
"accountancy_journal": "BQ1",
|
||||
"currency_code": "EUR",
|
||||
"account_currency_code": "EUR",
|
||||
"min_allowed": "0",
|
||||
"min_desired": "0",
|
||||
"comment": " <br />\r\nPour recevoir des virements internationaux, utilisez le BIC de notre banque intermédiaire:<br />\r\n<br />\r\nTRWIBEB3XXX<br />\r\n<br />\r\n<br />\r\n<br />\r\n(Privilégier Wise)<br />\r\n ",
|
||||
"date_solde": null,
|
||||
"solde": null,
|
||||
"balance": 5032,
|
||||
"ics": "",
|
||||
"ics_transfer": ""
|
||||
},
|
||||
{
|
||||
"module": null,
|
||||
"id": "2",
|
||||
"entity": null,
|
||||
"import_key": null,
|
||||
"array_options": [],
|
||||
"array_languages": null,
|
||||
"contacts_ids": null,
|
||||
"contacts_ids_internal": null,
|
||||
"linkedObjectsIds": null,
|
||||
"canvas": null,
|
||||
"fk_project": null,
|
||||
"contact_id": null,
|
||||
"user": null,
|
||||
"origin_type": null,
|
||||
"origin_id": null,
|
||||
"ref": "WIS2",
|
||||
"ref_ext": null,
|
||||
"statut": null,
|
||||
"status": "0",
|
||||
"country_id": "2",
|
||||
"country_code": "BE",
|
||||
"state_id": "140",
|
||||
"region_id": null,
|
||||
"barcode_type": null,
|
||||
"barcode_type_coder": null,
|
||||
"mode_reglement_id": null,
|
||||
"cond_reglement_id": null,
|
||||
"demand_reason_id": null,
|
||||
"transport_mode_id": null,
|
||||
"shipping_method_id": null,
|
||||
"shipping_method": null,
|
||||
"fk_multicurrency": null,
|
||||
"multicurrency_code": null,
|
||||
"multicurrency_tx": null,
|
||||
"multicurrency_total_ht": null,
|
||||
"multicurrency_total_tva": null,
|
||||
"multicurrency_total_localtax1": null,
|
||||
"multicurrency_total_localtax2": null,
|
||||
"multicurrency_total_ttc": null,
|
||||
"last_main_doc": null,
|
||||
"fk_account": null,
|
||||
"note_public": null,
|
||||
"note_private": null,
|
||||
"total_ht": null,
|
||||
"total_tva": null,
|
||||
"total_localtax1": null,
|
||||
"total_localtax2": null,
|
||||
"total_ttc": null,
|
||||
"lines": null,
|
||||
"actiontypecode": null,
|
||||
"name": null,
|
||||
"lastname": null,
|
||||
"firstname": null,
|
||||
"civility_id": null,
|
||||
"civility_code": null,
|
||||
"date_creation": 1769887227,
|
||||
"date_validation": null,
|
||||
"date_modification": 1769883627,
|
||||
"tms": null,
|
||||
"date_cloture": null,
|
||||
"user_author": null,
|
||||
"user_creation": null,
|
||||
"user_creation_id": null,
|
||||
"user_valid": null,
|
||||
"user_validation": null,
|
||||
"user_validation_id": null,
|
||||
"user_closing_id": null,
|
||||
"user_modification": null,
|
||||
"user_modification_id": null,
|
||||
"fk_user_creat": null,
|
||||
"fk_user_modif": null,
|
||||
"specimen": 0,
|
||||
"totalpaid": null,
|
||||
"extraparams": [],
|
||||
"product": null,
|
||||
"cond_reglement_supplier_id": null,
|
||||
"deposit_percent": null,
|
||||
"retained_warranty_fk_cond_reglement": null,
|
||||
"warehouse_id": null,
|
||||
"label": "WISE EURO",
|
||||
"courant": "1",
|
||||
"type": "1",
|
||||
"bank": "WISE",
|
||||
"clos": "0",
|
||||
"rappro": "1",
|
||||
"url": "https://wise.com",
|
||||
"code_banque": "",
|
||||
"code_guichet": "",
|
||||
"number": "",
|
||||
"cle_rib": "",
|
||||
"bic": "TRWIBEB1XXX",
|
||||
"iban": "BE58967543094979",
|
||||
"iban_prefix": null,
|
||||
"pti_in_ctti": "0",
|
||||
"proprio": "ARCODANGE",
|
||||
"owner_name": "ARCODANGE",
|
||||
"owner_address": "73 BD de l'yerres",
|
||||
"owner_zip": "91000",
|
||||
"owner_town": "\u00c9vry-Courcouronnes",
|
||||
"owner_country_id": "1",
|
||||
"owner_country_code": null,
|
||||
"domiciliation": null,
|
||||
"address": "Wise, Rue du Tr\u00f4ne 100, 3rd floor, Brussels, 1050, Belgium",
|
||||
"type_lib": [
|
||||
"BankType0",
|
||||
"BankType1",
|
||||
"BankType2"
|
||||
],
|
||||
"account_number": "51212",
|
||||
"fk_accountancy_journal": "8",
|
||||
"accountancy_journal": "BQ2",
|
||||
"currency_code": "EUR",
|
||||
"account_currency_code": "EUR",
|
||||
"min_allowed": "0",
|
||||
"min_desired": "0",
|
||||
"comment": "",
|
||||
"date_solde": null,
|
||||
"solde": null,
|
||||
"balance": 3160,
|
||||
"ics": "",
|
||||
"ics_transfer": ""
|
||||
},
|
||||
{
|
||||
"module": null,
|
||||
"id": "3",
|
||||
"entity": null,
|
||||
"import_key": null,
|
||||
"array_options": [],
|
||||
"array_languages": null,
|
||||
"contacts_ids": null,
|
||||
"contacts_ids_internal": null,
|
||||
"linkedObjectsIds": null,
|
||||
"canvas": null,
|
||||
"fk_project": null,
|
||||
"contact_id": null,
|
||||
"user": null,
|
||||
"origin_type": null,
|
||||
"origin_id": null,
|
||||
"ref": "CCA1",
|
||||
"ref_ext": null,
|
||||
"statut": null,
|
||||
"status": "0",
|
||||
"country_id": "1",
|
||||
"country_code": "FR",
|
||||
"state_id": null,
|
||||
"region_id": null,
|
||||
"barcode_type": null,
|
||||
"barcode_type_coder": null,
|
||||
"mode_reglement_id": null,
|
||||
"cond_reglement_id": null,
|
||||
"demand_reason_id": null,
|
||||
"transport_mode_id": null,
|
||||
"shipping_method_id": null,
|
||||
"shipping_method": null,
|
||||
"fk_multicurrency": null,
|
||||
"multicurrency_code": null,
|
||||
"multicurrency_tx": null,
|
||||
"multicurrency_total_ht": null,
|
||||
"multicurrency_total_tva": null,
|
||||
"multicurrency_total_localtax1": null,
|
||||
"multicurrency_total_localtax2": null,
|
||||
"multicurrency_total_ttc": null,
|
||||
"last_main_doc": null,
|
||||
"fk_account": null,
|
||||
"note_public": null,
|
||||
"note_private": null,
|
||||
"total_ht": null,
|
||||
"total_tva": null,
|
||||
"total_localtax1": null,
|
||||
"total_localtax2": null,
|
||||
"total_ttc": null,
|
||||
"lines": null,
|
||||
"actiontypecode": null,
|
||||
"name": null,
|
||||
"lastname": null,
|
||||
"firstname": null,
|
||||
"civility_id": null,
|
||||
"civility_code": null,
|
||||
"date_creation": 1772107398,
|
||||
"date_validation": null,
|
||||
"date_modification": 1772103843,
|
||||
"tms": null,
|
||||
"date_cloture": null,
|
||||
"user_author": null,
|
||||
"user_creation": null,
|
||||
"user_creation_id": null,
|
||||
"user_valid": null,
|
||||
"user_validation": null,
|
||||
"user_validation_id": null,
|
||||
"user_closing_id": null,
|
||||
"user_modification": null,
|
||||
"user_modification_id": null,
|
||||
"fk_user_creat": null,
|
||||
"fk_user_modif": null,
|
||||
"specimen": 0,
|
||||
"totalpaid": null,
|
||||
"extraparams": [],
|
||||
"product": null,
|
||||
"cond_reglement_supplier_id": null,
|
||||
"deposit_percent": null,
|
||||
"retained_warranty_fk_cond_reglement": null,
|
||||
"warehouse_id": null,
|
||||
"label": "G.RADUREAU Compte Courant Asso",
|
||||
"courant": "1",
|
||||
"type": "1",
|
||||
"bank": "",
|
||||
"clos": "0",
|
||||
"rappro": "1",
|
||||
"url": null,
|
||||
"code_banque": "",
|
||||
"code_guichet": "",
|
||||
"number": "",
|
||||
"cle_rib": "",
|
||||
"bic": "",
|
||||
"iban": "",
|
||||
"iban_prefix": null,
|
||||
"pti_in_ctti": "0",
|
||||
"proprio": "",
|
||||
"owner_name": "",
|
||||
"owner_address": "",
|
||||
"owner_zip": "",
|
||||
"owner_town": "",
|
||||
"owner_country_id": null,
|
||||
"owner_country_code": null,
|
||||
"domiciliation": null,
|
||||
"address": "",
|
||||
"type_lib": [
|
||||
"BankType0",
|
||||
"BankType1",
|
||||
"BankType2"
|
||||
],
|
||||
"account_number": "45511",
|
||||
"fk_accountancy_journal": "13",
|
||||
"accountancy_journal": "CCA1",
|
||||
"currency_code": "EUR",
|
||||
"account_currency_code": "EUR",
|
||||
"min_allowed": "0",
|
||||
"min_desired": "0",
|
||||
"comment": "",
|
||||
"date_solde": null,
|
||||
"solde": null,
|
||||
"balance": -429.75,
|
||||
"ics": "",
|
||||
"ics_transfer": ""
|
||||
}
|
||||
]
|
||||
12
.claude/skills/dolibarr/examples/invoices_12_payments.json
Normal file
12
.claude/skills/dolibarr/examples/invoices_12_payments.json
Normal file
@@ -0,0 +1,12 @@
|
||||
[
|
||||
{
|
||||
"amount": "5100.00000000",
|
||||
"type": "VIR",
|
||||
"typeline": "payment",
|
||||
"date": "2026-03-12 12:00:00",
|
||||
"num": "",
|
||||
"ref": "REC003-CL00002",
|
||||
"ref_ext": "",
|
||||
"fk_bank_line": "19"
|
||||
}
|
||||
]
|
||||
Reference in New Issue
Block a user