返回 Skill 列表
extension
分类: 数据与分析需要 API Key

Sportsinc Sportslink

Sports Inc SportsLink API 适配器 — 从 Sports Inc SportsWeb 发票中心拉取经销商的发票(“文档”)并标记为已消费。Sports Inc 是...

person作者: zmtuckerhubclawhub

Sports Inc SportsLink adapter

Sports Inc is a buying group: BaconCo (and every other SI dealer) buys through Sports Inc, and Sports Inc does not email individual vendor invoices — they're published in the SportsWeb Invoice Center and exposed through the SportsLink REST API. This skill is the source adapter for that API. It does one job: hand a payables workflow a clean, normalised list of invoices, and mark them consumed once they've been imported. It never touches Odoo.

The single helper is scripts/sportslink.py:

# The un-imported inbox: active documents that carry line items (EDI), normalised
python3 scripts/sportslink.py list '{"active": true, "lines": true, "ediOnly": true}'

# A specific document (ignores the active-only filter)
python3 scripts/sportslink.py get '{"poNumber": "P13189"}'

# Mark documents consumed — AFTER they've been billed (honors SPORTSINC_DRY_RUN)
python3 scripts/sportslink.py mark-historical '{"siDocNumbers": [12345, 23456]}'

Every command prints one JSON object, or {"error": {...}} with a non-zero exit. Needs SPORTSINC_API_KEY (if unset, exits config_error — stop and tell the user to configure it; never ask for the key in chat).

Normalised invoice shape

list/get return {count, total_count, invoices: [...]}, each invoice:

{
  "source": "sports_inc",
  "po_number": "P13189",          // dealer PO number → the match key to a PO
  "si_doc_number": 12345,          // SI's document id → used to mark-historical
  "invoice_number": "…",           // supplierDocNumber (falls back to si_doc_number)
  "invoice_date": "…",             // supplierDocDate, else siDocDate
  "due_date": "…", "supplier": "…",
  "is_credit": false,               // credit memo → handle separately, never a bill
  "has_lines": true,                // false for scanned/OCR docs (header totals only)
  "total": 0,                       // docTotal
  "charges": {"merchandise", "freight", "freight_allowance", "si_upcharge",
              "svc_handle", "sales_tax", "excise_tax", "discount"},
  "lines": [{"item","upc","description","size","color","unit",
             "qty_ordered","qty_shipped","qty_backordered",
             "list_price","discount_pct","net_price","extension"}]
}

This is the same shape a PDF-extracted invoice would have, so a payables workflow reconciles it without caring that it came from SportsLink.

Rules that matter

  • Don't pull before ~10:30am ET — SI's internal processing runs first; earlier reads can be incomplete. Schedule accordingly.
  • Line data is EDI-only. Scanned/OCR documents come back with header totals but no lines (has_lines: false). Pass ediOnly: true to fetch only documents with line items; a header-only doc can't be line-verified and should be escalated by the workflow, not blind-billed.
  • is_credit: true is a credit memo — route it to a human / vendor credit, never create it as a payable.
  • Exactly-once — the golden rule. Import first, mark-historical after the bill is created. This adapter deliberately does not use the API's moveToHistorical=true GET flag (which marks on read, before billing) — a crash between read and bill would silently drop the invoice. The natural loop: list active → bill each in the ERP → mark-historical the ones that succeeded; failures/escalations stay active and are retried next run.
  • Paging is automatic (all: true, the default). Max 1000 docs/call on SI's side; the helper pages to the end (capped at 50 pages as a backstop).

Where this fits

Source adapter (this) → payables workflow (drivethru-payable-matching) → ERP adapter (drivethru-odoo / drivethru_mcp). This skill owns only the "get the invoices + mark them consumed" half; matching to POs, correcting pricing, and creating the draft bill live in the workflow. See that skill's references/sportsinc_payables.md for the end-to-end procedure.