Skip to main content

What it is

Purchase order lines — header and line combined in one row (order_no + sku), Katana-compatible. Each row is one article on one supplier order, with ordered vs. received quantities, expected arrival, price, and a full provenance trail (who created it — user or agent — and who approved it). The status machine is draftpending_approvalorderedpartially_receivedreceived (or cancelled). Katana mapping: draftDRAFT, orderedNOT_RECEIVED, partially_receivedPARTIALLY_RECEIVED, receivedRECEIVED (pending_approval is a Concierca addition, exported as DRAFT). Open quantity is always computed as quantity_ordered − quantity_received, never stored. Open lines feed the Procurement Queue: open_purchase_order_quantity and arrival dates there are aggregated from lines in ordered / partially_received. A unique index on recommendation_key over open lines is the physical double-order lock — one queue recommendation can never spawn two open orders.

How it gets data

Three paths write here: the procurement agent creates draft lines from queue recommendations, admins edit in the app, and external systems (e.g. an existing PO list) push through the Ingest API:
  • One JSON record per request; unknown fields are dropped.
  • Idempotent upsert on (tenant_id, external_id) — use a stable per-line id (e.g. PO-2026-014-1).
  • tenant_id / workspace_id come from the API key context, never from the body.
  • product_name, supplier_name, variant_external_id, product_external_id are filled by a database trigger from the SKU — don’t send or maintain them by hand.
Minimal example payload:

Fields

Order line

Snapshot columns (trigger-filled)

Provenance, approval & external sync

✓ = editable in the app, settable on create, and accepted on ingest. “trigger” = computed by the database on write. “API only” = real database column not registered as a visible app column — readable via query, maintained by the system or specialized flows.
Like every workspace table, purchase order lines also carry the system columns id, tenant_id, workspace_id, created_at, and updated_at — set automatically, never sent by integrations.

Query it