Builds on cf70021, which added the read-only yeeke client/session/sync core
but left it unreachable and unconfigurable. This commit:
- Wires config.ExtConfig.Yeeke (settings.yml + config.yaml + GOAUTO_YEEKE_*
env vars), mirroring the existing SYB credential pattern exactly, with a
dedicated OcrURL and shared OCR client from sybclient.
- Adds yeeke.StartSync as the single entry point for both a manual admin
trigger and the scheduled job, sharing one in-memory gate plus the existing
DB-level unique active_slot lease so they can never run concurrently.
- Fixes sync.go bugs found in review: Service.Sync always returned a nil
error even when the run failed (start/resume semantics were untestable),
item upserts on ctx-less s.db calls, and no error_message/last_success_at
was ever recorded on the run row.
- Adds status_unrecognized to yeeke_return_package: an unknown claim status
is preserved verbatim and flagged rather than silently bucketed.
- Adds the admin read-only surface (GET .../sync-runs, GET
.../sync-runs/:runId, POST .../sync) under /api/admin/v1/yeeke-returns,
visible to admin and purchaser per the #336 review comment, registered as
a GoAuto access module/menu group and purchaser API.
- Registers GoAutoYeekeReturnSync in the existing job/lease framework
(app/jobs), seeded disabled (Status 2) by a new version-local migration,
following 1786701600000_syb_hourly_sync_job.go's pattern exactly.
- Expands tests: session reuse/bounded re-login/timeout-preserves-cache in
yeekeclient; paging robustness (total changing mid-run, duplicate page,
empty page, timeout, simulated restart/resume), idempotent upserts,
unrecognized-status flagging, active_slot lease contention, StartSync gate
contention, and a credential/captcha redaction check in yeeke; settings.yml
binding and env var precedence in config.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NTDbDcwbDw1TSAcE6wfh2F
Every API request logged one bare "info" line with no message: upstream
calls log.WithFields(logData).Info(), and the console formatter does not
render fields, so status, latency, IP, method and URI all went nowhere.
One line of pure noise per request.
Give the line its message and demote it to debug. The payload is worth
having when diagnosing a slow or failing request, so it is recoverable
by setting logger.level back to debug rather than deleted.
settings.yml drops from trace to info accordingly. Nothing else in the
project logs below info: the many .Debug() calls are gorm SQL echo, which
is unaffected by logger level.
This patches upstream go-admin middleware, marked as such in a comment.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Port the SYB ERP HTTP client from the upstream cmautobuy project. The
package is stdlib-only (no DB, no gin), so client.go, columns.go, ocr.go
and their httptest suites carry over almost verbatim; only the package
name and doc references changed.
Add on top of the port:
- models.SYBSession + gorm SessionStore, so a restart does not force a
fresh captcha. Cookies are credential-equivalent and carry json:"-".
Expired sessions read as absent because SYB has no rolling renewal.
- config.Extend.SYB. Non-secret settings live in settings.yml;
username and password come only from GOAUTO_SYB_* environment
variables, so no credential lands in a tracked file.
- docs/12-syb-erp-interface.md, the ported interface contract.
The guard tests were mutation-checked: reverting json:"-" and renaming a
settings.yml key each make their test fail.
No import endpoint yet — that needs real credentials and live network
verification, which is Stage 2 of #48.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>