feat: per-row location_id on purchase orders — client spec + MCP tools#946
Merged
Conversation
…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>
Contributor
There was a problem hiding this comment.
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_idto 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_idwhere 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. |
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>
c8e5c15 to
984e334
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Follow-up to #942, which added per-row
location_idto purchase order rows but leftgaps. This finishes the feature across the client spec and the MCP tools.
Two commits:
fix(client)— Closes #944#942 added
location_idto the standalone create/update row schemas and thePurchaseOrderRowresponse, but missed two row schemas the live gateway also carriesit on (both invisible to
audit-specbecause their endpoints use inline upstreamschemas):
PurchaseOrderReceiveRow(POST /purchase_order_receive)PurchaseOrderRowRequest(nested rows inPOST /purchase_orders)feat(mcp)— Closes #945Exposes per-row
location_idonly on the paths Katana actually honors (live-verified):modify_purchase_order→add_rows/update_rows(→POST/PATCH /purchase_order_rows)receive_purchase_order→ per-row receive locationtyped 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_idon whole-PO-create nested rows but the runtime silentlyoverrides them to the order-level location:
location_idhonored?POST /purchase_orders(nested rows)POST /purchase_order_rows(standalone)PATCH /purchase_order_rows/{id}POST /purchase_order_receiveSo the MCP layer deliberately does not expose
location_idoncreate_purchase_order'srow 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 checkgreen (lint, type-check, 4131 unit + 48 browser tests, strict audit)main(picked up the stricter audit-spec dimensions + enum fixes); re-validated, no generated-file drifthonor per-row
location_id; whole-PO-create does not. All probe fixtures self-cleaned.🤖 Generated with Claude Code
Review refinement (Copilot, #946)
location_id(set viaadd_rows/PATCH). Both the batched cache lookup and the rendered value use it. New test covers override / row-own / inherited.PurchaseOrderReceiveRow.location_idstays non-nullable (live gateway declaresnullable: false).