add dolibarr-thirdparty-completeness and dolibarr-tva-deductible

V4 bundle — two more sibling skills, both read-only, both depending
on the dolibarr base skill.

dolibarr-thirdparty-completeness:
- audit-thirdparty.sh <socid>: country-aware completeness audit for
  any thirdparty (FR: SIREN + SIRET + tva_intra; EU non-FR: tva_intra;
  extra-EU: national tax id). Generalizes the V1 KM-hardcoded script.
- audit-all-thirdparties.sh: loops over /thirdparties and surfaces a
  compact table of gaps. --clients-only / --suppliers-only flags.
- Live baseline finds 5/10 thirdparties with mandatory gaps:
  KissMetrics (US tax id), Wise Europe SA (BE tva_intra), Medialex
  (FR SIRET + tva_intra), Qonto (SIRET), Infogreffe (SIRET).

dolibarr-tva-deductible:
- deductible-by-month.sh: TVA déductible aggregated per period × rate.
- deductible-line-detail.sh: per supplier-invoice line with country-
  based CA3 bucket assignment (ligne 20 for 20 % FR, ligne 19 for
  reduced rates, ligne 17+24 for intra-UE autoliquidation).
- Live baseline: 223.22 € total TVA déductible across 13 lines.
  Wise Europe SA correctly identified as intra-UE autoliquidation;
  La Poste correctly identified as FR exempt (timbres).
- Mirrors dolibarr-tva-reconciliation on the supplier side. Together
  they give the two numbers a CA3 monthly declaration needs.

Also extends dolibarr/SKILL.md endpoint catalogue with /supplierinvoices
(noting the 403 on the /lines sub-endpoint — inline lines on the detail
endpoint make this a non-issue). dolibarr/README.md gains two new
permission checkboxes for Factures fournisseurs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-29 06:14:28 +02:00
parent fe9e8274f1
commit 585b7beb03
18 changed files with 5736 additions and 0 deletions

View File

@@ -30,6 +30,8 @@ In the Dolibarr UI (https://erp.arcodange.lab/ → **Setup → Users & Groups
- [ ] **Tiers** → Voir tous les tiers (et pas seulement ceux liés à l'utilisateur courant)
- [ ] **Factures** → Lire les factures
- [ ] **Factures** → Voir toutes les factures (et pas seulement celles liées à l'utilisateur courant)
- [ ] **Factures fournisseurs** → Lire les factures fournisseurs (required by `dolibarr-tva-deductible`)
- [ ] **Factures fournisseurs** → Voir toutes les factures fournisseurs
Save. Future modules used by `dolibarr-*` sibling skills (Paiements, Produits, …) need the same treatment.

View File

@@ -94,6 +94,7 @@ Read-only endpoints we've validated against this instance. Live captures are und
| `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`, `KM-cloud-devops` is `id=2` | [products_list.json](examples/products_list.json) |
| `GET /supplierinvoices` / `/{id}` | 200 | Supplier (fournisseur) invoices | Lines are included inline on the detail endpoint (same shape as `/invoices/{id}`). Sub-endpoint `/lines` returns **HTTP 403** for `ai_agent` — not needed since inline lines work. | [supplierinvoices_list.json](examples/supplierinvoices_list.json) · [supplierinvoice_detail.json](examples/supplierinvoice_detail.json) |
| `GET /invoices/templates/{id}` | 200 | Recurring invoice template detail | **No list endpoint** — probe ids 1..N. Empty ids return HTTP 200 with `id=null` (sentinel for "doesn't exist"). Fields: `ref`, `socid`, `frequency`, `unit_frequency`, `nb_gen_done`, `date_when`, `date_last_gen`, `suspended`, `auto_validate`, `lines`. | [invoice_template_km.json](examples/invoice_template_km.json) |
| `GET /documents/download` | 200 | Download a stored document as base64 | `modulepart=facture&original_file=<REF>/<REF>.pdf` (URL-encode slashes). Returns `{filename, content-type, filesize, content}` with `content` base64. | [document_download_meta.json](examples/document_download_meta.json) |
@@ -139,6 +140,8 @@ Not available on this account (intentionally): `/setup/modules` (admin-only), `/
- Workflow skill for monthly TVA basis (CA3 / CA12 preparation): [dolibarr-tva-reconciliation](../dolibarr-tva-reconciliation/SKILL.md).
- Workflow skill for recurring invoice templates: [dolibarr-recurring-templates](../dolibarr-recurring-templates/SKILL.md).
- Workflow skill for point-in-time state archival: [dolibarr-data-snapshot](../dolibarr-data-snapshot/SKILL.md).
- Workflow skill for thirdparty completeness audit (any client / supplier): [dolibarr-thirdparty-completeness](../dolibarr-thirdparty-completeness/SKILL.md).
- Workflow skill for supplier-side TVA déductible (CA3 lignes 19 / 20 / 17+24): [dolibarr-tva-deductible](../dolibarr-tva-deductible/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

View File

@@ -0,0 +1,16 @@
{
"_captured_when": "2026-05-29 — ai_agent permission baseline. Lines come through inline on /supplierinvoices/{id} so this 403 is informational only and doesn't block any current workflow. If a future skill needs the dedicated /lines endpoint, ai_agent needs an additional permission grant.",
"_curl": "curl -H 'DOLAPIKEY: <key>' https://erp.arcodange.lab/api/index.php/supplierinvoices/1/lines",
"_http_status": 403,
"error": {
"code": 403,
"message": "Forbidden"
},
"debug": {
"source": "api_supplier_invoices.class.php:614 at call stage",
"stages": {
"success": ["get", "route", "negotiate", "authenticate", "validate"],
"failure": ["call", "message"]
}
}
}

View File

@@ -0,0 +1,257 @@
{
"module": null,
"id": "1",
"entity": "1",
"import_key": null,
"array_options": [],
"array_languages": null,
"contacts_ids": null,
"contacts_ids_internal": null,
"linkedObjectsIds": [],
"canvas": null,
"fk_project": null,
"contact_id": null,
"user": null,
"origin_type": null,
"origin_id": null,
"ref": "FAF2026001",
"ref_ext": "",
"statut": "2",
"status": "2",
"country_id": null,
"country_code": null,
"state_id": null,
"region_id": null,
"mode_reglement_id": "2",
"cond_reglement_id": null,
"demand_reason_id": null,
"transport_mode_id": null,
"shipping_method_id": null,
"shipping_method": null,
"fk_multicurrency": "0",
"multicurrency_code": "EUR",
"multicurrency_tx": "1.00000000",
"multicurrency_total_ht": "50.00000000",
"multicurrency_total_tva": "0.00000000",
"multicurrency_total_localtax1": null,
"multicurrency_total_localtax2": null,
"multicurrency_total_ttc": "50.00000000",
"last_main_doc": null,
"fk_account": "1",
"note_public": "",
"note_private": "",
"total_ht": "50.00000000",
"total_tva": "0.00000000",
"total_localtax1": "0.00000000",
"total_localtax2": "0.00000000",
"total_ttc": "50.00000000",
"lines": [
{
"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,
"origin_type": null,
"origin_id": null,
"ref": null,
"ref_ext": null,
"statut": null,
"status": null,
"state_id": null,
"region_id": null,
"demand_reason_id": null,
"transport_mode_id": null,
"shipping_method": null,
"multicurrency_tx": null,
"multicurrency_total_ht": "50.00000000",
"multicurrency_total_tva": "0.00000000",
"multicurrency_total_localtax1": null,
"multicurrency_total_localtax2": null,
"multicurrency_total_ttc": "50.00000000",
"last_main_doc": null,
"fk_account": null,
"total_ht": "50.00000000",
"total_tva": "0.00000000",
"total_localtax1": "0.00000000",
"total_localtax2": "0.00000000",
"total_ttc": "50.00000000",
"lines": null,
"actiontypecode": null,
"civility_code": null,
"date_creation": null,
"date_validation": null,
"date_modification": null,
"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,
"parent_element": "facture_fourn",
"fk_parent_attribute": "fk_facture_fourn",
"fk_unit": null,
"date_debut_prevue": null,
"date_debut_reel": null,
"date_fin_prevue": null,
"date_fin_reel": null,
"weight": null,
"weight_units": null,
"length": null,
"length_units": null,
"width": null,
"width_units": null,
"height": null,
"height_units": null,
"surface": null,
"surface_units": null,
"volume": null,
"volume_units": null,
"multilangs": null,
"product_type": "1",
"fk_product": null,
"desc": "Ouverture compte -&nbsp;<em>Exon&eacute;ration de TVA &ndash; Article 261 C du CGI</em>",
"description": "Ouverture compte -&nbsp;<em>Exon&eacute;ration de TVA &ndash; Article 261 C du CGI</em>",
"product_ref": null,
"product_label": null,
"product_barcode": null,
"product_desc": null,
"fk_product_type": null,
"qty": "1",
"duree": null,
"remise_percent": "0",
"info_bits": "0",
"special_code": "0",
"subprice": "50.00000000",
"subprice_ttc": null,
"tva_tx": "0.0000",
"multicurrency_subprice": "50.00000000",
"multicurrency_subprice_ttc": null,
"ref_supplier": "",
"pu_ht": "50.00000000",
"pu_ttc": "50.00000000",
"fk_facture_fourn": "1",
"label": null,
"date_start": "",
"date_end": "",
"fk_code_ventilation": null,
"situation_percent": null,
"fk_prev_id": null,
"vat_src_code": "",
"localtax1_tx": "0.0000",
"localtax2_tx": "0.0000",
"pa_ht": null,
"fk_remise_except": null,
"fk_parent_line": null,
"rang": "1",
"localtax1_type": "0",
"localtax2_type": "0",
"libelle": null,
"fk_accounting_account": "9"
}
],
"actiontypecode": null,
"name": null,
"lastname": null,
"firstname": null,
"civility_id": null,
"civility_code": null,
"date_creation": null,
"date_validation": null,
"date_modification": null,
"tms": 1771929935,
"date_cloture": null,
"user_author": null,
"user_creation": null,
"user_creation_id": "2",
"user_valid": null,
"user_validation": null,
"user_validation_id": "2",
"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,
"title": null,
"type": 0,
"subtype": 0,
"fk_soc": null,
"socid": "2",
"paye": "1",
"date": 1769382000,
"date_lim_reglement": null,
"cond_reglement_code": null,
"cond_reglement_label": null,
"cond_reglement_doc": null,
"mode_reglement_code": "VIR",
"revenuestamp": null,
"totaldeposits": null,
"totalcreditnotes": null,
"sumpayed": null,
"sumpayed_multicurrency": null,
"sumdeposit": null,
"sumdeposit_multicurrency": null,
"sumcreditnote": null,
"sumcreditnote_multicurrency": null,
"remaintopay": null,
"nbofopendirectdebitorcredittransfer": null,
"creditnote_ids": [],
"stripechargedone": null,
"stripechargeerror": null,
"description": null,
"ref_client": null,
"situation_cycle_ref": null,
"close_code": null,
"close_note": null,
"postactionmessages": null,
"fk_incoterms": "0",
"label_incoterms": null,
"location_incoterms": "",
"ref_supplier": "PLAN_ORDER_CHECKOUT-invoice-23917601",
"libelle": "",
"label": "",
"fk_statut": "2",
"paid": "1",
"datec": 1771931434,
"date_echeance": 1769382000,
"amount": 0,
"remise": 0,
"tva": null,
"localtax1": null,
"localtax2": null,
"propalid": null,
"vat_reverse_charge": 0,
"fournisseur": null,
"fk_facture_source": null,
"fac_rec": null,
"fk_fac_rec_source": null,
"fk_user_valid": null
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff