feat(write-skill): client-dossier ops — thirdparty update (allowlisted) + idempotent contacts
Part of erp#65 (phase 1). Ledger grammar "thirdparty complete" gets its op: allowlisted non-ledger fields, per-field diff read-back. Contacts are born idempotent (dedupe by email then name). Promote ops wired both targets, offline stub tests, SKILL.md workflows, KM dossier manifest (unsigned-contract truth fix + EIN-to-collect note). Co-Authored-By: Claude Fable 5 <[email protected]>
This commit is contained in:
@@ -1,18 +1,74 @@
|
||||
#!/usr/bin/env bash
|
||||
# Offline stand-in for dol-write.sh, used ONLY by tests/run-tests.sh (injected via
|
||||
# the DOL_WRITE env hook). Records the POST body under $STUB_STATE, then serves it
|
||||
# back as the payments list on GET so payment-record.sh can correlate. Never talks
|
||||
# to any host — sandbox and prod are both out of reach by construction.
|
||||
# the DOL_WRITE env hook). Never talks to any host — sandbox and prod are both out
|
||||
# of reach by construction. Dispatch by endpoint:
|
||||
#
|
||||
# GET /thirdparties/<id> → serves $STUB_STATE/thirdparty.json (or a canned
|
||||
# "before" fiche on first read)
|
||||
# PUT /thirdparties/<id> → records put_body.json/put_endpoint, merges the body
|
||||
# into thirdparty.json (so the read-after sees it)
|
||||
# GET /contacts… → serves $STUB_STATE/contacts.json; mimics Dolibarr's
|
||||
# empty-list behavior (HTTP 404 + non-zero) when absent
|
||||
# POST /contacts… → records contact_post_body.json, appends the contact
|
||||
# (id 88) to contacts.json, echoes 88
|
||||
# POST <anything else> → payment behavior: records post_body.json/post_endpoint,
|
||||
# echoes 77 (unchanged from the erp#37 tests)
|
||||
# GET <anything else> → payments list served back from post_body.json
|
||||
set -euo pipefail
|
||||
STATE="${STUB_STATE:?stub-dol-write.sh: STUB_STATE not set}"
|
||||
METHOD="$1"; ENDPOINT="$2"; BODY="${3:-}"
|
||||
case "${METHOD}" in
|
||||
POST)
|
||||
printf '%s' "${BODY}" > "${STATE}/post_body.json"
|
||||
case "${METHOD} ${ENDPOINT}" in
|
||||
"GET /thirdparties/"*)
|
||||
if [[ -f "${STATE}/thirdparty.json" ]]; then
|
||||
cat "${STATE}/thirdparty.json"
|
||||
else
|
||||
printf '%s' '{"id":"1","name":"KissMetrics","name_alias":null,"email":"","note_public":"OLD NOTE (pre-dossier)","zip":null,"town":null}'
|
||||
fi
|
||||
;;
|
||||
"PUT /thirdparties/"*)
|
||||
printf '%s' "${BODY}" > "${STATE}/put_body.json"
|
||||
printf '%s\n' "${ENDPOINT}" > "${STATE}/put_endpoint"
|
||||
python3 - "${STATE}" "${BODY}" <<'PY'
|
||||
import json, os, sys
|
||||
state, body = sys.argv[1], json.loads(sys.argv[2])
|
||||
p = os.path.join(state, "thirdparty.json")
|
||||
cur = (json.load(open(p)) if os.path.exists(p)
|
||||
else {"id": "1", "name": "KissMetrics", "name_alias": None, "email": "",
|
||||
"note_public": "OLD NOTE (pre-dossier)", "zip": None, "town": None})
|
||||
cur.update(body)
|
||||
json.dump(cur, open(p, "w"), ensure_ascii=False)
|
||||
print(json.dumps(cur, ensure_ascii=False))
|
||||
PY
|
||||
;;
|
||||
"GET /contacts"*)
|
||||
if [[ -f "${STATE}/contacts.json" ]]; then
|
||||
cat "${STATE}/contacts.json"
|
||||
else
|
||||
# Dolibarr's list endpoints answer 404 (not []) when nothing matches.
|
||||
printf '%s' '{"error":{"code":404,"message":"No contact found"}}'
|
||||
echo "stub-dol-write.sh: HTTP 404 on GET ${ENDPOINT}" >&2
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
"POST /contacts"*)
|
||||
printf '%s' "${BODY}" > "${STATE}/contact_post_body.json"
|
||||
python3 - "${STATE}" "${BODY}" <<'PY'
|
||||
import json, os, sys
|
||||
state, body = sys.argv[1], json.loads(sys.argv[2])
|
||||
p = os.path.join(state, "contacts.json")
|
||||
rows = json.load(open(p)) if os.path.exists(p) else []
|
||||
body = dict(body); body["id"] = "88"
|
||||
rows.append(body)
|
||||
json.dump(rows, open(p, "w"), ensure_ascii=False)
|
||||
PY
|
||||
echo "88"
|
||||
;;
|
||||
POST\ *)
|
||||
printf '%s' "${BODY}" > "${STATE}/post_body.json"
|
||||
printf '%s\n' "${ENDPOINT}" > "${STATE}/post_endpoint"
|
||||
echo "77"
|
||||
;;
|
||||
GET)
|
||||
GET\ *)
|
||||
python3 - "${STATE}/post_body.json" <<'PY'
|
||||
import json, sys
|
||||
body = json.load(open(sys.argv[1]))
|
||||
|
||||
Reference in New Issue
Block a user