add dolibarr api skills for read-only inspection
First two of an expected family of dolibarr-* skills: - dolibarr/: platform reference — DOLAPIKEY auth, the voir_tous ACL trap, endpoint catalogue, the dol-curl.sh wrapper, .env credentials layout (gitignored, mode 600). Every future workflow skill depends on this one. - dolibarr-invoice-audit/: first workflow — list KissMetrics invoices, audit one invoice end-to-end (JSON facts + PDF mandatory-mention checklist against the French legal corpus), audit the KissMetrics thirdparty record. Live captures in examples/ include real audit findings to surface to the Arcodange × KissMetrics cohort review: PDFs are missing capital social, L.441-10 penalties, 40 € indemnity, L.123-22 / R.123-237; KissMetrics thirdparty has no EIN (idprof1..6 all empty); static/config/company.json holds placeholder values and a wrong forme juridique (claims SAS, the real Dolibarr is SARL). .gitignore hardened with *.credentials, secrets/, *.key, and an explicit .claude/skills/**/.env pattern. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
72
.claude/skills/dolibarr-invoice-audit/scripts/audit-km-thirdparty.sh
Executable file
72
.claude/skills/dolibarr-invoice-audit/scripts/audit-km-thirdparty.sh
Executable file
@@ -0,0 +1,72 @@
|
||||
#!/usr/bin/env bash
|
||||
# Audit the KissMetrics thirdparty record (socid=1) for completeness.
|
||||
#
|
||||
# Usage:
|
||||
# audit-km-thirdparty.sh
|
||||
#
|
||||
# Checks the contact fields and the idprof1..idprof6 slots where the US EIN
|
||||
# should live for a non-EU customer. Today EIN is missing — this script's
|
||||
# exit-1 IS the finding to surface to the cohort review.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
DOL_CURL="${SCRIPT_DIR}/../../dolibarr/scripts/dol-curl.sh"
|
||||
KM_SOCID=1
|
||||
|
||||
TMP_JSON="$(mktemp -t doltp.XXXXXX.json)"
|
||||
trap 'rm -f "${TMP_JSON}"' EXIT
|
||||
|
||||
"${DOL_CURL}" "/thirdparties/${KM_SOCID}" > "${TMP_JSON}"
|
||||
|
||||
python3 - "${TMP_JSON}" <<'PY'
|
||||
import json, sys
|
||||
with open(sys.argv[1]) as f:
|
||||
d = json.load(f)
|
||||
|
||||
print("=" * 80)
|
||||
print(f" KissMetrics thirdparty audit — socid={d.get('id')}")
|
||||
print("=" * 80)
|
||||
|
||||
required = [
|
||||
("name", d.get("name")),
|
||||
("client flag", "yes" if str(d.get("client")) == "1" else None),
|
||||
("country_code", d.get("country_code")),
|
||||
("state_id", d.get("state_id")),
|
||||
("address", d.get("address")),
|
||||
("zip", d.get("zip")),
|
||||
("town", d.get("town")),
|
||||
("email", d.get("email")),
|
||||
("phone", d.get("phone")),
|
||||
("url", d.get("url")),
|
||||
]
|
||||
idprofs = [(f"idprof{i}", d.get(f"idprof{i}")) for i in range(1, 7)]
|
||||
ein_present = any(v not in (None, "", "0") for _, v in idprofs)
|
||||
|
||||
passes = fails = 0
|
||||
def check(label, value):
|
||||
global passes, fails
|
||||
ok = value not in (None, "", "0")
|
||||
print(f" [{'OK' if ok else 'XX'}] {label:<18} = {value!r}")
|
||||
if ok: passes += 1
|
||||
else: fails += 1
|
||||
|
||||
for label, value in required:
|
||||
check(label, value)
|
||||
|
||||
print()
|
||||
print(" idprof1..idprof6 (EIN slot for non-EU customers):")
|
||||
for label, value in idprofs:
|
||||
print(f" {label:<10} = {value!r}")
|
||||
print(f" [{'OK' if ein_present else 'XX'}] EIN present (any idprof populated)")
|
||||
if ein_present: passes += 1
|
||||
else: fails += 1
|
||||
|
||||
ao = d.get("array_options") or {}
|
||||
print()
|
||||
print(f" array_options (Dolibarr extrafields): {ao if ao else '(none)'}")
|
||||
|
||||
print()
|
||||
print(f" {passes} pass / {fails} fail")
|
||||
sys.exit(0 if fails == 0 else 1)
|
||||
PY
|
||||
Reference in New Issue
Block a user