Skip to content

feat: per-row location_id on purchase orders — client spec + MCP tools#946

Merged
dougborg merged 2 commits into
mainfrom
feat/po-row-location-id
Jun 10, 2026
Merged

feat: per-row location_id on purchase orders — client spec + MCP tools#946
dougborg merged 2 commits into
mainfrom
feat/po-row-location-id

Conversation

@dougborg

@dougborg dougborg commented Jun 9, 2026

Copy link
Copy Markdown
Owner

Summary

Follow-up to #942, which added per-row location_id to purchase order rows but left
gaps. This finishes the feature across the client spec and the MCP tools.

Two commits:

fix(client)Closes #944

#942 added location_id to the standalone create/update row schemas and the
PurchaseOrderRow response, but missed two row schemas the live gateway also carries
it on (both invisible to audit-spec because their endpoints use inline upstream
schemas):

  • PurchaseOrderReceiveRow (POST /purchase_order_receive)
  • PurchaseOrderRowRequest (nested rows in POST /purchase_orders)

feat(mcp)Closes #945

Exposes per-row location_id only on the paths Katana actually honors (live-verified):

  • modify_purchase_orderadd_rows / update_rows (→ POST/PATCH /purchase_order_rows)
  • receive_purchase_order → per-row receive location
  • Receipt card → new Destination column (batched location-name resolution from the
    typed cache; blank when the row inherits the order-level location)

Key finding: not all paths honor it

I live-probed the test tenant rather than trusting the published spec — and the gateway
declares location_id on whole-PO-create nested rows but the runtime silently
overrides
them to the order-level location:

Path Per-row location_id honored?
POST /purchase_orders (nested rows) ❌ silently overridden to order-level
POST /purchase_order_rows (standalone)
PATCH /purchase_order_rows/{id}
POST /purchase_order_receive

So the MCP layer deliberately does not expose location_id on create_purchase_order's
row input — it would be a silent no-op (the silent-drop failure mode the backlog tracks).
The client spec keeps the field (it's in the published gateway contract) but its docstring
now carries the "not honored at create time" caveat.

Test plan

  • uv run poe check green (lint, type-check, 4131 unit + 48 browser tests, strict audit)
  • Rebased on latest main (picked up the stricter audit-spec dimensions + enum fixes); re-validated, no generated-file drift
  • New + updated prefab tests pin the Destination column + per-row location rendering
  • Live-verified on the test tenant: standalone create-row, PATCH, and receive all
    honor per-row location_id; whole-PO-create does not. All probe fixtures self-cleaned.

🤖 Generated with Claude Code

Review refinement (Copilot, #946)

  • Receipt card now resolves each row's effective destination — the receive-time override when given, else the row's own location_id (set via add_rows/PATCH). Both the batched cache lookup and the rendered value use it. New test covers override / row-own / inherited.
  • Confirmed PurchaseOrderReceiveRow.location_id stays non-nullable (live gateway declares nullable: false).

…chemas

The 2026-06-09 spec sweep (#942) added per-row location_id to the standalone
create/update purchase-order-row request schemas and the PurchaseOrderRow response,
but missed two row schemas that the live gateway also carries it on:

- PurchaseOrderReceiveRow (POST /purchase_order_receive) — receive each row into a
  different location.
- PurchaseOrderRowRequest (nested rows in POST /purchase_orders) — set per-row
  location at order-create time.

Both gaps are invisible to audit-spec because /purchase_order_receive and
/purchase_orders use inline upstream schemas (on the inline-skip list). Regenerated
all three clients.

Closes #944

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 9, 2026 19:53

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Completes per-row location_id support for purchase order rows across the OpenAPI spec/generated clients and the MCP purchase-order tools, including receipt-card rendering for multi-location receiving.

Changes:

  • Adds location_id to the missing PO row request schemas (PurchaseOrderRowRequest, PurchaseOrderReceiveRow) and propagates through generated TS + Python clients.
  • Extends MCP purchase order flows to accept per-row location_id where Katana honors it (modify row add/update + receive), and renders a new Destination column on the receipt card.
  • Pins/extends prefab UI tests to cover the new receipt table column and per-row destination rendering behavior.

Reviewed changes

Copilot reviewed 7 out of 8 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
packages/katana-client/src/generated/types.gen.ts Adds location_id to generated TS types for nested PO row create and PO receive rows, with gateway caveat docs.
katana_public_api_client/models/purchase_order_row_request.py Adds location_id to the attrs model and (de)serialization.
katana_public_api_client/models/purchase_order_receive_row.py Adds location_id to the attrs model and (de)serialization.
katana_public_api_client/models_pydantic/_generated/purchase_orders.py Adds location_id fields + constraints/descriptions to generated Pydantic models.
katana_mcp_server/tests/test_prefab_ui.py Updates receipt DataTable column pinning and adds destination rendering test coverage.
katana_mcp_server/src/katana_mcp/tools/prefab_ui.py Adds “Destination” column and row-level location display logic for receipt UI.
katana_mcp_server/src/katana_mcp/tools/foundation/purchase_orders.py Adds per-row location_id to receive requests, enriches receipt rows with location info via typed cache, and adds row-level location fields for PO row add/update.
docs/katana-openapi.yaml Updates the spec schemas to include the missing location_id fields and user-facing caveats.

Comment thread katana_mcp_server/src/katana_mcp/tools/foundation/purchase_orders.py Outdated
Comment thread docs/katana-openapi.yaml
Multi-location receiving (#945) — expose the new per-row purchase-order
location_id on the paths Katana actually honors (live-verified 2026-06-09):

- modify_purchase_order: add_rows (PORowAdd) and update_rows (PORowUpdate) now
  carry location_id, flowing through to POST/PATCH /purchase_order_rows.
- receive_purchase_order: ReceiveItemRequest carries per-row location_id so a
  single PO can be received across multiple locations.
- Receipt card: per-row destination column, resolving location names from the
  typed cache in one batched lookup (blank when the row inherits the order-level
  location).

Deliberately NOT exposed on create_purchase_order's nested rows: Katana silently
overrides nested rows to the order-level location at PO-create time, so exposing
it there would be a silent no-op. The standalone create-row / update-row / receive
endpoints all honor it.

Closes #945

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 9 changed files in this pull request and generated no new comments.

@dougborg dougborg merged commit 7b0d044 into main Jun 10, 2026
20 checks passed
@dougborg dougborg deleted the feat/po-row-location-id branch June 10, 2026 17:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants