docs(mcp): document stock_items.set_pricing and create pricing fields
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
031666946f
commit
73127f10cc
4 changed files with 42 additions and 9 deletions
|
|
@ -135,6 +135,7 @@ specific** tool that fits the task.
|
||||||
| `stock_purchase_items.assign_driver` | Bind a stock_purchase_item to a driver. Transitions line status `null → assigned_to_driver` or `collection_pool → assigned_to_driver`. Wrong_status (409) when the line is already past the assignment step. |
|
| `stock_purchase_items.assign_driver` | Bind a stock_purchase_item to a driver. Transitions line status `null → assigned_to_driver` or `collection_pool → assigned_to_driver`. Wrong_status (409) when the line is already past the assignment step. |
|
||||||
| `stock_purchase_items.mark_collected` | Mark a line as physically delivered. Status → `collected`, bumps `quantity_received`. Does NOT book into stock — that's `stock_purchases.receive`. Header auto-flips to `received` when every line on the PO has `quantity_received >= quantity`. |
|
| `stock_purchase_items.mark_collected` | Mark a line as physically delivered. Status → `collected`, bumps `quantity_received`. Does NOT book into stock — that's `stock_purchases.receive`. Header auto-flips to `received` when every line on the PO has `quantity_received >= quantity`. |
|
||||||
| `stock_items.update` | Patch catalogue fields on a master stock_item: `sku`, `description`, `notes`, `unit`, `selling_price`, `markup`. For inventory qty use `stock_items.adjust`. Returns `{ok: true, item, previous}` on success or `{ok: false, reason, message, field?}` on rejection. |
|
| `stock_items.update` | Patch catalogue fields on a master stock_item: `sku`, `description`, `notes`, `unit`, `selling_price`, `markup`. For inventory qty use `stock_items.adjust`. Returns `{ok: true, item, previous}` on success or `{ok: false, reason, message, field?}` on rejection. |
|
||||||
|
| `stock_items.set_pricing` | Set `cost_price` / `selling_price` / `markup` on existing stock_items in one batch (max 100 per call). The POS till reads `selling_price` (not `markup`), so set both consistently: selling = cost × (1 + markup/100). Cost changes are audited in `stock_ledger` with the `actor`; quantities are NOT changed (use `stock_items.adjust`). Requires `actor.id`. Returns per-row `{ok, item, previous}` / `{ok: false, reason, message}`. |
|
||||||
|
|
||||||
### 4.5 CRM maintenance
|
### 4.5 CRM maintenance
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -220,6 +220,7 @@ JSON-RPC over HTTP. Same `Authorization` bearer as `/api/v1/*`.
|
||||||
| Tool | Purpose |
|
| Tool | Purpose |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| `stock_items.update` | Patch catalogue fields on a master `stock_item` (`sku`, `description`, `notes`, `unit`, `selling_price`, `markup`). For inventory qty use `stock_items.adjust`. |
|
| `stock_items.update` | Patch catalogue fields on a master `stock_item` (`sku`, `description`, `notes`, `unit`, `selling_price`, `markup`). For inventory qty use `stock_items.adjust`. |
|
||||||
|
| `stock_items.set_pricing` | Set `cost_price` / `selling_price` / `markup` on existing `stock_items` in one batch (max 100). The POS till reads `selling_price`, not `markup` — set both. Cost changes are audited in `stock_ledger` with the `actor`; quantities are not changed (use `stock_items.adjust`). |
|
||||||
|
|
||||||
### 3.3 Tool input shapes (condensed)
|
### 3.3 Tool input shapes (condensed)
|
||||||
|
|
||||||
|
|
@ -323,6 +324,28 @@ Anything else returns `reason: "forbidden_field"`. For inventory qty use
|
||||||
`stock_items.adjust`. Returns `{ok: true, item, previous}` on success or
|
`stock_items.adjust`. Returns `{ok: true, item, previous}` on success or
|
||||||
`{ok: false, reason, message, field?}` on rejection.
|
`{ok: false, reason, message, field?}` on rejection.
|
||||||
|
|
||||||
|
`stock_items.set_pricing` (required: `updates`; `actor.id` is required at runtime):
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"updates": [
|
||||||
|
{ "id": "15-char-stock-item-id", "cost_price": 100, "selling_price": 180, "markup": 80 },
|
||||||
|
{ "id": "15-char-stock-item-id", "markup": 50 }
|
||||||
|
],
|
||||||
|
"actor": { "id": "user-id", "name": "Dave" }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
1–100 updates per call; keys limited to `id`, `cost_price`, `selling_price`,
|
||||||
|
`markup` (anything else is an error naming the key). The POS till reads
|
||||||
|
`selling_price`, not `markup`, so set both consistently
|
||||||
|
(selling = cost × (1 + markup/100)). Cost changes are audited in
|
||||||
|
`stock_ledger`. Returns `{results: [...], summary: {total, succeeded, failed}}`;
|
||||||
|
per-row failures (`not_found`, `validation_error`, `pb_error`) are returned, not
|
||||||
|
thrown. `stock_items.create` also accepts optional `cost_price`,
|
||||||
|
`selling_price` and `markup`; a cost with neither selling price nor markup gets
|
||||||
|
the app default markup (80%).
|
||||||
|
|
||||||
`bulk_update_quote_items` (required: `items`):
|
`bulk_update_quote_items` (required: `items`):
|
||||||
|
|
||||||
```json
|
```json
|
||||||
|
|
@ -467,7 +490,7 @@ keys aren't set, so a clean checkout reports `passed, N skipped`.
|
||||||
|
|
||||||
<!-- BEGIN mcp-doc-gen: tools catalogue — do not edit by hand, regenerate with scripts/mcp-doc-gen.py -->
|
<!-- BEGIN mcp-doc-gen: tools catalogue — do not edit by hand, regenerate with scripts/mcp-doc-gen.py -->
|
||||||
|
|
||||||
This catalogue is auto-generated from the `tools` array in `src/app/api/mcp/route.ts` by `scripts/mcp-doc-gen.py`. There are **137 tools** as of this run. Re-run the script after adding or renaming a tool.
|
This catalogue is auto-generated from the `tools` array in `src/app/api/mcp/route.ts` by `scripts/mcp-doc-gen.py`. There are **144 tools** as of this run. Re-run the script after adding or renaming a tool.
|
||||||
|
|
||||||
Grouped by resource family. The full description is in the table column; the description text the agent sees is preserved verbatim.
|
Grouped by resource family. The full description is in the table column; the description text the agent sees is preserved verbatim.
|
||||||
|
|
||||||
|
|
@ -489,11 +512,15 @@ Grouped by resource family. The full description is in the table column; the des
|
||||||
| `orders.mark_invoiced` | Mark an order as invoiced. Mirrors the REST POST /api/v1/orders/{id}/mark_invoiced endpoint. Flips `order.invoiced = true` ONLY when every line item has `item_status === "invoiced"`. Refuses with 409 if any item is not yet invoiced; the ... |
|
| `orders.mark_invoiced` | Mark an order as invoiced. Mirrors the REST POST /api/v1/orders/{id}/mark_invoiced endpoint. Flips `order.invoiced = true` ONLY when every line item has `item_status === "invoiced"`. Refuses with 409 if any item is not yet invoiced; the ... |
|
||||||
| `orders.mark_delivered` | Mark every eligible line item on the order as `delivered`, stamping `delivered_at` and `delivered_date`. Mirrors the REST POST /api/v1/orders/{id}/mark_delivered endpoint. Eligible statuses: `ready_delivery \| collected \| with_driver \| ch... |
|
| `orders.mark_delivered` | Mark every eligible line item on the order as `delivered`, stamping `delivered_at` and `delivered_date`. Mirrors the REST POST /api/v1/orders/{id}/mark_delivered endpoint. Eligible statuses: `ready_delivery \| collected \| with_driver \| ch... |
|
||||||
| `orders.update` | Patch whitelisted header fields on an order. Mirrors the REST PATCH /api/v1/orders/{id} endpoint. Whitelist (from `ORDER_PATCHABLE_FIELDS`): `notes`, `contact_name`, `description`, `rep`, `email_cc`, `email_bcc`, `quote_reference_text`, ... |
|
| `orders.update` | Patch whitelisted header fields on an order. Mirrors the REST PATCH /api/v1/orders/{id} endpoint. Whitelist (from `ORDER_PATCHABLE_FIELDS`): `notes`, `contact_name`, `description`, `rep`, `email_cc`, `email_bcc`, `quote_reference_text`, ... |
|
||||||
|
| `orders.set_quote` | Link an EXISTING order to an EXISTING quote. Mirrors the REST POST /api/v1/orders/{id}/quote endpoint. Why this exists: only `createOrderFromQuote` writes the `orders.quote` relation today, so walk-in orders leave it null. When Hermes di... |
|
||||||
|
| `orders.quote_match_sweep` | Run quote auto-detection over orders that have never been attempted. Mirrors the REST POST /api/v1/orders/quote-match/sweep endpoint. Why this exists: orders created from now on are matched automatically at intake. This is the catch-up p... |
|
||||||
| `orders.add_note` | REPLACE the `notes` field on an order with `text`. Thin wrapper over `orders.update` (`patch: { notes: text }`). The `notes` field is a free-text header field, distinct from the per-line `order_items.notes` JSON audit feed. If you want t... |
|
| `orders.add_note` | REPLACE the `notes` field on an order with `text`. Thin wrapper over `orders.update` (`patch: { notes: text }`). The `notes` field is a free-text header field, distinct from the per-line `order_items.notes` JSON audit feed. If you want t... |
|
||||||
| `orders.add_attachment` | Upload a single attachment (proof, drawing, signed PO, supplier quote) to an order. The file is stored against the order's matched quote (WFDASH has no `order_attachments` collection; orders resolve to their matched quote for attachment ... |
|
| `orders.add_attachment` | Upload a single attachment (proof, drawing, signed PO, supplier quote) to an order. The file is stored on the order's OWN `order_attachements` multi-file field (PB-side misspelling kept in sync with the live schema) — the same field the ... |
|
||||||
| `orders.list_attachments` | List the attachments associated with an order. Returns the order's matched quote's attachments (since orders share the quote_attachments table with their source quote). Includes the original RFQ email attachments, the rendered quote PDF,... |
|
| `orders.list_attachments` | List the attachments associated with an order. Merges two sources: (a) files written to the order's own `order_attachements` multi-file field — operator uploads via `orders.add_attachment` and counter-sale photos from the in-store PWA; a... |
|
||||||
| `orders.sprint_counts` | Counts of sprint-pricing rows grouped by claim status (unclaimed / claimed-by-me / claimed-by-other / resolved). Used to render sprint badges in the operator UI and to decide whether an agent should claim a row. Wraps `GET /api/v1/orders... |
|
| `orders.sprint_counts` | Counts of sprint-pricing rows grouped by claim status (unclaimed / claimed-by-me / claimed-by-other / resolved). Used to render sprint badges in the operator UI and to decide whether an agent should claim a row. Wraps `GET /api/v1/orders... |
|
||||||
| `orders.find_duplicates` | Find probable duplicate orders for the same customer + recent window. Wraps `GET /api/v1/orders/duplicates`. Use this BEFORE creating a new order from a customer's RFQ so the operator doesn't accidentally double-order. Returns groups wit... |
|
| `orders.find_duplicates` | Find probable duplicate orders. Wraps `GET /api/v1/orders/duplicates`. Use this BEFORE creating a new order from a customer's RFQ so the operator doesn't accidentally double-order. Three pass kinds are supported: - `order_number` — same ... |
|
||||||
|
| `orders.find_by_order_number` | Exact-match lookup for one order by its `order_number`. Returns the matching `Order` record or `null` if not found. Use this when you need a deterministic `is there already an order for this order number?` check. The substring search `or... |
|
||||||
|
| `orders.find_by_email_message_id` | Exact-match lookup for one order by its `email_message_id` (RFC 5322 Message-ID of the inbound email that originated it). Returns the matching `Order` record or `null` if not found. Use this for the `is there already an order for this in... |
|
||||||
| `orders.review` | Read-only review bundle for one order: header, items grouped by supplier, PO readiness, attachment matches against quote items, and any pending decisions. Wraps `GET /api/v1/orders/[id]/review`. Use this BEFORE generating POs or splittin... |
|
| `orders.review` | Read-only review bundle for one order: header, items grouped by supplier, PO readiness, attachment matches against quote items, and any pending decisions. Wraps `GET /api/v1/orders/[id]/review`. Use this BEFORE generating POs or splittin... |
|
||||||
| `orders.matched_attachments` | Match the order's quote attachments against each order_item by description / SKU overlap. Wraps `GET /api/v1/orders/[id]/matched-attachments`. Returns `{ item_id → [attachment_filename, ...] }` so the agent can decide which proof applies... |
|
| `orders.matched_attachments` | Match the order's quote attachments against each order_item by description / SKU overlap. Wraps `GET /api/v1/orders/[id]/matched-attachments`. Returns `{ item_id → [attachment_filename, ...] }` so the agent can decide which proof applies... |
|
||||||
|
|
||||||
|
|
@ -503,7 +530,7 @@ Grouped by resource family. The full description is in the table column; the des
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| `order_items.update_status` | Update an order_item's `item_status` and/or `drv_status` fields. Use this when the operator needs to flip a single row through the workflow without bulk-pricing or per-line invoice reconciliation (`order_items.update` is the patch tool f... |
|
| `order_items.update_status` | Update an order_item's `item_status` and/or `drv_status` fields. Use this when the operator needs to flip a single row through the workflow without bulk-pricing or per-line invoice reconciliation (`order_items.update` is the patch tool f... |
|
||||||
| `order_items.confirm_collected` | Confirm collection of one or more customer order_items WITHOUT requiring a driver assignment. Mirrors the agent-side role that the stock-side `stock_purchase_items.mark_collected` already plays: marks `item_status` → `collected` and `drv... |
|
| `order_items.confirm_collected` | Confirm collection of one or more customer order_items WITHOUT requiring a driver assignment. Mirrors the agent-side role that the stock-side `stock_purchase_items.mark_collected` already plays: marks `item_status` → `collected` and `drv... |
|
||||||
| `order_items.create` | Add a new line item to an existing order. Mirrors the REST POST /api/v1/orders/{id}/items endpoint. **Strict pending gate**: refuses with 409 (`order_locked`) if any line item on the order is past `item_status === "pending"`. Adding a li... |
|
| `order_items.create` | Add a new line item to an existing order. Mirrors the REST POST /api/v1/orders/{id}/items endpoint. `selling_price` auto-derives from `cost_price * (1 + markup / 100)` when omitted. Per-row failures never abort the whole call (returns `c... |
|
||||||
| `order_items.update` | Patch fields on an order_item for invoice reconciliation. Whitelist: cost_price, selling_price, quantity, sku, unit, category, markup, markup_percent, notes, qty_processed, qty_assigned, qty_collected, qty_verified, qty_stocked, qty_pick... |
|
| `order_items.update` | Patch fields on an order_item for invoice reconciliation. Whitelist: cost_price, selling_price, quantity, sku, unit, category, markup, markup_percent, notes, qty_processed, qty_assigned, qty_collected, qty_verified, qty_stocked, qty_pick... |
|
||||||
| `order_items.list` | List order_items (the line items under each order). Useful for finding pending/PB-ready items, getting one supplier's items, etc. Pass PB filter syntax in `filter`. |
|
| `order_items.list` | List order_items (the line items under each order). Useful for finding pending/PB-ready items, getting one supplier's items, etc. Pass PB filter syntax in `filter`. |
|
||||||
| `order_items.get` | Fetch a single order_item by id. Pass `expand` to inline `order`, `purchase_order`, `category`, `supplier`. |
|
| `order_items.get` | Fetch a single order_item by id. Pass `expand` to inline `order`, `purchase_order`, `category`, `supplier`. |
|
||||||
|
|
@ -521,8 +548,8 @@ Grouped by resource family. The full description is in the table column; the des
|
||||||
| `quotes.find_by_message_id` | Look up an existing quote by the inbound email's RFC 5322 Message-ID header. Use this when the operator (or another agent) needs to correlate an inbound email back to a quote that was already created from it — e.g. to attach a reply, app... |
|
| `quotes.find_by_message_id` | Look up an existing quote by the inbound email's RFC 5322 Message-ID header. Use this when the operator (or another agent) needs to correlate an inbound email back to a quote that was already created from it — e.g. to attach a reply, app... |
|
||||||
| `quotes.list` | List quotes. Pass PB filter syntax in `filter` (e.g. `status="new"`). Default sort `-created`. |
|
| `quotes.list` | List quotes. Pass PB filter syntax in `filter` (e.g. `status="new"`). Default sort `-created`. |
|
||||||
| `quotes.get` | Fetch a single quote by id. Pass `expand` (e.g. `customer,company,items`). |
|
| `quotes.get` | Fetch a single quote by id. Pass `expand` (e.g. `customer,company,items`). |
|
||||||
| `quotes.update` | Patch fields on a quote header. Whitelist: `company_letterhead`, `quote_date`, `quote_reference`, `rfq_number`, `validity_days`, `notes`, `delivery_note`, `markup`, `email_cc`, `email_bcc`, `claimed_by`. Anything outside this set — inclu... |
|
| `quotes.update` | Patch fields on a quote header. Whitelist: `company_letterhead`, `quote_date`, `quote_reference`, `rfq_number`, `validity_days`, `notes`, `delivery_note`, `markup`, `email_cc`, `email_bcc`, `claimed_by`, `email_subject`, `email_sender`, ... |
|
||||||
| `quotes.send_email` | Front-door for the outbound email send pipeline. Validates and flips the quote to `sending`; the actual SMTP send runs asynchronously in n8n. `selectedAttachmentIds` is a list of PB file tokens from `quotes.outbound_attachments` (operator-uploaded customer-facing files — supplier quotes, drawings, NDAs). The PDF is always attached separately from `quote_attachments` kind="pdf". Tokens not present in the quote's outbound_attachments field are silently filtered server-side. `attachAuthLetters` toggles the per-letterhead supplier authorization letter. Walks four sources for the recipient: `to` → `customer.email` → `customer.alternative_email` → `quote.email_sender`. PDF is auto-regenerated if a staleness probe detects drift between the last render and the operator's latest edits. |
|
| `quotes.send_email` | Front-door for the outbound email send pipeline. Validates and flips the quote to `sending`; the actual SMTP send runs asynchronously in n8n. `selectedAttachmentIds` is a list of PB file tokens from `quotes.outbound_attachments` (operato... |
|
||||||
| `quotes.retry_email` | Retry the outbound email send for a quote currently in `mail_failed`. Use this when SMTP credentials have been rotated, the customer's MX changed, or the original send bounced. The quote must already be in `mail_failed` (409 if not) — fo... |
|
| `quotes.retry_email` | Retry the outbound email send for a quote currently in `mail_failed`. Use this when SMTP credentials have been rotated, the customer's MX changed, or the original send bounced. The quote must already be in `mail_failed` (409 if not) — fo... |
|
||||||
| `quotes.clone` | Clone a real quote into a new real quote with a fresh `quote_number` and `status="new"`. The source quote is untouched. Useful for re-quoting the same items to a different customer. |
|
| `quotes.clone` | Clone a real quote into a new real quote with a fresh `quote_number` and `status="new"`. The source quote is untouched. Useful for re-quoting the same items to a different customer. |
|
||||||
| `quotes.create_from_template` | Create a new real quote from a template (`is_template=true` quote). The template is not modified — a fresh quote is created with a new `Q-YYYY-MM-NNN` number, `status="new"`, and the template's customer / company / letterhead / items cop... |
|
| `quotes.create_from_template` | Create a new real quote from a template (`is_template=true` quote). The template is not modified — a fresh quote is created with a new `Q-YYYY-MM-NNN` number, `status="new"`, and the template's customer / company / letterhead / items cop... |
|
||||||
|
|
@ -631,6 +658,7 @@ Grouped by resource family. The full description is in the table column; the des
|
||||||
| `stock_items.create` | Create a new stock_item. `name` is required. When `current_qty > 0` an opening-balance ledger row is written so the running total and the ledger sum stay in sync (reason=`adjustment`, reference_type=`manual`). |
|
| `stock_items.create` | Create a new stock_item. `name` is required. When `current_qty > 0` an opening-balance ledger row is written so the running total and the ledger sum stay in sync (reason=`adjustment`, reference_type=`manual`). |
|
||||||
| `stock_items.adjust` | Record a manual stock adjustment. Inserts a `stock_ledger` row and updates `current_qty` on the parent item. `change_qty` is signed (positive = in, negative = out); zero is rejected. `reason` must be one of STOCK_REASON_VALUES. |
|
| `stock_items.adjust` | Record a manual stock adjustment. Inserts a `stock_ledger` row and updates `current_qty` on the parent item. `change_qty` is signed (positive = in, negative = out); zero is rejected. `reason` must be one of STOCK_REASON_VALUES. |
|
||||||
| `stock_items.update` | Patch catalogue fields on a master stock_item: sku, description, notes, unit, selling_price, markup. For inventory qty use stock_items.adjust. Returns {ok: true, item, previous} on success or {ok: false, reason, message, field?} on rejec... |
|
| `stock_items.update` | Patch catalogue fields on a master stock_item: sku, description, notes, unit, selling_price, markup. For inventory qty use stock_items.adjust. Returns {ok: true, item, previous} on success or {ok: false, reason, message, field?} on rejec... |
|
||||||
|
| `stock_items.set_pricing` | Set cost price / selling price / markup on existing stock_items in one batch (max 100 per call). The POS till reads `selling_price` (NOT markup), so set both consistently: selling = cost × (1 + markup/100). Cost changes are audited in st... |
|
||||||
|
|
||||||
### Collection pool
|
### Collection pool
|
||||||
|
|
||||||
|
|
@ -691,6 +719,7 @@ Grouped by resource family. The full description is in the table column; the des
|
||||||
|
|
||||||
| Tool | Description |
|
| Tool | Description |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
|
| `audit_log.get` | Change history for one quote, order or delivery note — who changed what and when, newest first. Each entry lists per-field changes (`from` → `to`), the actor and source (web / mcp / n8n / agent). Includes summary counts: quote PDFs gener... |
|
||||||
| `bulk_update_quote_items` | Patch many `quote_items` rows in a single MCP call (one JSON-RPC round-trip instead of N PATCHes to PB REST). Use this for AI auto-fill, supplier switches, or any bulk pricing update. Each row is independent — one row's failure never aff... |
|
| `bulk_update_quote_items` | Patch many `quote_items` rows in a single MCP call (one JSON-RPC round-trip instead of N PATCHes to PB REST). Use this for AI auto-fill, supplier switches, or any bulk pricing update. Each row is independent — one row's failure never aff... |
|
||||||
| `stock.fulfill` | Fulfill order items from stock. CREATE mode (`order_id` + `order_item_id` + `stock_item_id` + `qty` + `description` + `selling_price` + `cost_price`) creates a new order_item and decrements stock in one call. UPDATE mode (`order_item_id`... |
|
| `stock.fulfill` | Fulfill order items from stock. CREATE mode (`order_id` + `order_item_id` + `stock_item_id` + `qty` + `description` + `selling_price` + `cost_price`) creates a new order_item and decrements stock in one call. UPDATE mode (`order_item_id`... |
|
||||||
| `stock.surplus_book` | Book surplus from a collected order_item into a stock_item. Auto-picks the matching stock_item when `stock_item_id` is omitted. |
|
| `stock.surplus_book` | Book surplus from a collected order_item into a stock_item. Auto-picks the matching stock_item when `stock_item_id` is omitted. |
|
||||||
|
|
@ -703,7 +732,8 @@ Grouped by resource family. The full description is in the table column; the des
|
||||||
| `stock_quick_draft.search` | Search the quick-draft index for SKUs / descriptions / suppliers. Wraps `GET /api/v1/stock-quick-draft/search`. Returns ranked hits with last-known cost and supplier. Use this BEFORE adding a line so the agent can pre-fill cost + supplier. |
|
| `stock_quick_draft.search` | Search the quick-draft index for SKUs / descriptions / suppliers. Wraps `GET /api/v1/stock-quick-draft/search`. Returns ranked hits with last-known cost and supplier. Use this BEFORE adding a line so the agent can pre-fill cost + supplier. |
|
||||||
| `stock_quick_draft.add_line` | Add one line to an in-progress quick-draft PO. Wraps `POST /api/v1/stock-quick-draft/add-line`. The draft persists between calls until the operator hits 'Commit'. Use this when building up a stock PO one line at a time. Pass `stockItemId... |
|
| `stock_quick_draft.add_line` | Add one line to an in-progress quick-draft PO. Wraps `POST /api/v1/stock-quick-draft/add-line`. The draft persists between calls until the operator hits 'Commit'. Use this when building up a stock PO one line at a time. Pass `stockItemId... |
|
||||||
| `stock_quick_draft.suppliers` | List suppliers with quick-draft history (last ordered, line count, total spend). Wraps `GET /api/v1/stock-quick-draft/suppliers`. Use this to pick a supplier when the catalogue doesn't have a clear default. |
|
| `stock_quick_draft.suppliers` | List suppliers with quick-draft history (last ordered, line count, total spend). Wraps `GET /api/v1/stock-quick-draft/suppliers`. Use this to pick a supplier when the catalogue doesn't have a clear default. |
|
||||||
| `delivery_notes.list` | List delivery notes. Reads the `delivery_notes` collection via the admin PB client. Supports `status` filter (draft \| in_transit \| invoiced \| cancelled), `order_id` filter, and pagination. Newest-first. Use this when the operator asks 's... |
|
| `delivery_notes.list` | List delivery notes. Reads the `delivery_notes` collection via the admin PB client. Supports `status` filter, `order_id` filter, and pagination. Newest-first. Use this when the operator asks 'show me outstanding delivery notes' or 'what'... |
|
||||||
|
| `delivery_notes.set_order` | Link an EXISTING delivery note to an EXISTING order. Mirrors the REST POST /api/v1/delivery-notes/{id}/order endpoint. Why this exists: `delivery_notes.order` is a relation to `orders` but has no setter in the service layer — only the cr... |
|
||||||
| `delivery_notes.create` | Create a counter-pickup delivery note (Path B — no upstream order). Wraps `POST /api/v1/delivery-notes`. Body: `customer` (PB id, required), `items[]` (required, ≥1 with description + quantity), optional `company`, `notes`, `createdBy`. ... |
|
| `delivery_notes.create` | Create a counter-pickup delivery note (Path B — no upstream order). Wraps `POST /api/v1/delivery-notes`. Body: `customer` (PB id, required), `items[]` (required, ≥1 with description + quantity), optional `company`, `notes`, `createdBy`. ... |
|
||||||
| `delivery_notes.cancel` | Cancel a delivery note. Wraps `POST /api/v1/delivery-notes/[id]/cancel`. Body: optional `setById` (PB user id), `setByName`, and `note` for the audit trail. Use when a DN was created in error or the customer cancels the pickup. |
|
| `delivery_notes.cancel` | Cancel a delivery note. Wraps `POST /api/v1/delivery-notes/[id]/cancel`. Body: optional `setById` (PB user id), `setByName`, and `note` for the audit trail. Use when a DN was created in error or the customer cancels the pickup. |
|
||||||
| `delivery_notes.mark_invoiced` | Flip a delivery note to `invoiced` after the customer's invoice is raised. Wraps `POST /api/v1/delivery-notes/[id]/mark-invoiced`. Idempotent; returns the updated DN record. |
|
| `delivery_notes.mark_invoiced` | Flip a delivery note to `invoiced` after the customer's invoice is raised. Wraps `POST /api/v1/delivery-notes/[id]/mark-invoiced`. Idempotent; returns the updated DN record. |
|
||||||
|
|
@ -716,6 +746,6 @@ Grouped by resource family. The full description is in the table column; the des
|
||||||
|
|
||||||
### Alphabetical index
|
### Alphabetical index
|
||||||
|
|
||||||
`ai_insights.rerun`, `ai_settings.get`, `ai_settings.update`, `attachments.upload_for_quote`, `bulk_update_quote_items`, `buyer_tasks.generate_po`, `buyer_tasks.list`, `buyer_tasks.mark_ready`, `collection_confirm.confirm_order_items`, `collection_confirm.list`, `collection_confirm.upload_invoice`, `collection_pool.list`, `companies.create`, `companies.delete`, `companies.get`, `companies.list`, `companies.update`, `customers.create`, `customers.delete`, `customers.get`, `customers.list`, `customers.update`, `dashboard.daily_summary`, `delivery_notes.cancel`, `delivery_notes.combine`, `delivery_notes.create`, `delivery_notes.create_quote`, `delivery_notes.list`, `delivery_notes.mark_complete`, `delivery_notes.mark_invoiced`, `delivery_notes.regenerate_pdf`, `delivery_notes.set_customer_po`, `delivery_notes.set_item_quantity`, `drivers.list_stops`, `drivers.update_stop_status`, `files.fetch`, `order_items.confirm_collected`, `order_items.create`, `order_items.get`, `order_items.list`, `order_items.update`, `order_items.update_status`, `orders.add_attachment`, `orders.add_note`, `orders.archive`, `orders.cancel`, `orders.create`, `orders.create_from_quote`, `orders.daily_summary`, `orders.find_duplicates`, `orders.get`, `orders.list`, `orders.list_attachments`, `orders.mark_delivered`, `orders.mark_invoiced`, `orders.matched_attachments`, `orders.review`, `orders.review_save`, `orders.split`, `orders.sprint_counts`, `orders.stats`, `orders.update`, `price_list.add_items`, `purchase_orders.add_attachment`, `purchase_orders.diff`, `purchase_orders.get`, `purchase_orders.list`, `purchase_orders.record_diff_report`, `purchase_orders.record_send_outcome`, `purchase_orders.retry_email`, `purchase_orders.scan`, `purchase_orders.send_email`, `purchase_orders.stale`, `quote_items.create`, `quote_items.get`, `quote_items.list`, `quote_items.populate_insights`, `quote_items.update`, `quotes.append_reply`, `quotes.clone`, `quotes.create`, `quotes.create_from_email`, `quotes.create_from_template`, `quotes.find_by_message_id`, `quotes.get`, `quotes.get_pdf`, `quotes.ingest_from_email`, `quotes.list`, `quotes.list_attachments`, `quotes.lookup`, `quotes.next_number`, `quotes.partial_approve`, `quotes.process_pending`, `quotes.re_price`, `quotes.re_run_ai`, `quotes.retry_email`, `quotes.save_as_template`, `quotes.send_email`, `quotes.split`, `quotes.submit`, `quotes.update`, `sprint.attachment_counts`, `sprint.claim`, `sprint.item_attachments`, `sprint.list`, `stock.fulfill`, `stock.surplus_book`, `stock_items.adjust`, `stock_items.create`, `stock_items.get`, `stock_items.list`, `stock_items.update`, `stock_purchase_items.assign_driver`, `stock_purchase_items.bulk_update`, `stock_purchase_items.list`, `stock_purchase_items.mark_collected`, `stock_purchase_items.update`, `stock_purchases.add_attachment`, `stock_purchases.create`, `stock_purchases.get`, `stock_purchases.list`, `stock_purchases.match_and_receive_from_invoice`, `stock_purchases.next_number`, `stock_purchases.receive`, `stock_purchases.retry_email`, `stock_purchases.send`, `stock_purchases.send_email`, `stock_quick_draft.add_line`, `stock_quick_draft.search`, `stock_quick_draft.suppliers`, `suppliers.create`, `suppliers.delete`, `suppliers.get`, `suppliers.list`, `suppliers.update`, `tools.discovery`, `users.lookup`
|
`ai_insights.rerun`, `ai_settings.get`, `ai_settings.update`, `attachments.upload_for_quote`, `audit_log.get`, `bulk_update_quote_items`, `buyer_tasks.generate_po`, `buyer_tasks.list`, `buyer_tasks.mark_ready`, `collection_confirm.confirm_order_items`, `collection_confirm.list`, `collection_confirm.upload_invoice`, `collection_pool.list`, `companies.create`, `companies.delete`, `companies.get`, `companies.list`, `companies.update`, `customers.create`, `customers.delete`, `customers.get`, `customers.list`, `customers.update`, `dashboard.daily_summary`, `delivery_notes.cancel`, `delivery_notes.combine`, `delivery_notes.create`, `delivery_notes.create_quote`, `delivery_notes.list`, `delivery_notes.mark_complete`, `delivery_notes.mark_invoiced`, `delivery_notes.regenerate_pdf`, `delivery_notes.set_customer_po`, `delivery_notes.set_item_quantity`, `delivery_notes.set_order`, `drivers.list_stops`, `drivers.update_stop_status`, `files.fetch`, `order_items.confirm_collected`, `order_items.create`, `order_items.get`, `order_items.list`, `order_items.update`, `order_items.update_status`, `orders.add_attachment`, `orders.add_note`, `orders.archive`, `orders.cancel`, `orders.create`, `orders.create_from_quote`, `orders.daily_summary`, `orders.find_by_email_message_id`, `orders.find_by_order_number`, `orders.find_duplicates`, `orders.get`, `orders.list`, `orders.list_attachments`, `orders.mark_delivered`, `orders.mark_invoiced`, `orders.matched_attachments`, `orders.quote_match_sweep`, `orders.review`, `orders.review_save`, `orders.set_quote`, `orders.split`, `orders.sprint_counts`, `orders.stats`, `orders.update`, `price_list.add_items`, `purchase_orders.add_attachment`, `purchase_orders.diff`, `purchase_orders.get`, `purchase_orders.list`, `purchase_orders.record_diff_report`, `purchase_orders.record_send_outcome`, `purchase_orders.retry_email`, `purchase_orders.scan`, `purchase_orders.send_email`, `purchase_orders.stale`, `quote_items.create`, `quote_items.get`, `quote_items.list`, `quote_items.populate_insights`, `quote_items.update`, `quotes.append_reply`, `quotes.clone`, `quotes.create`, `quotes.create_from_email`, `quotes.create_from_template`, `quotes.find_by_message_id`, `quotes.get`, `quotes.get_pdf`, `quotes.ingest_from_email`, `quotes.list`, `quotes.list_attachments`, `quotes.lookup`, `quotes.next_number`, `quotes.partial_approve`, `quotes.process_pending`, `quotes.re_price`, `quotes.re_run_ai`, `quotes.retry_email`, `quotes.save_as_template`, `quotes.send_email`, `quotes.split`, `quotes.submit`, `quotes.update`, `sprint.attachment_counts`, `sprint.claim`, `sprint.item_attachments`, `sprint.list`, `stock.fulfill`, `stock.surplus_book`, `stock_items.adjust`, `stock_items.create`, `stock_items.get`, `stock_items.list`, `stock_items.set_pricing`, `stock_items.update`, `stock_purchase_items.assign_driver`, `stock_purchase_items.bulk_update`, `stock_purchase_items.list`, `stock_purchase_items.mark_collected`, `stock_purchase_items.update`, `stock_purchases.add_attachment`, `stock_purchases.create`, `stock_purchases.get`, `stock_purchases.list`, `stock_purchases.match_and_receive_from_invoice`, `stock_purchases.next_number`, `stock_purchases.receive`, `stock_purchases.retry_email`, `stock_purchases.send`, `stock_purchases.send_email`, `stock_quick_draft.add_line`, `stock_quick_draft.search`, `stock_quick_draft.suppliers`, `suppliers.create`, `suppliers.delete`, `suppliers.get`, `suppliers.list`, `suppliers.update`, `tools.discovery`, `users.lookup`
|
||||||
|
|
||||||
<!-- END mcp-doc-gen -->
|
<!-- END mcp-doc-gen -->
|
||||||
|
|
@ -258,6 +258,7 @@ Result: 14 capabilities, 9 fully covered, **5 partial/missing**.
|
||||||
| Create stock item | `/stock` form | `POST /stock/items/create` | `stock_items.create` | ✅ |
|
| Create stock item | `/stock` form | `POST /stock/items/create` | `stock_items.create` | ✅ |
|
||||||
| Update stock item | `/stock/[id]` | `PATCH /stock/items/[id]` | `stock_items.update` | ✅ |
|
| Update stock item | `/stock/[id]` | `PATCH /stock/items/[id]` | `stock_items.update` | ✅ |
|
||||||
| Manual adjust | `/stock/[id]` | `POST /stock/items/[id]/adjust` | `stock_items.adjust` | ✅ |
|
| Manual adjust | `/stock/[id]` | `POST /stock/items/[id]/adjust` | `stock_items.adjust` | ✅ |
|
||||||
|
| Set cost / selling price / markup (batch) | `/stock` inline edit | `POST /stock/items/set-pricing` | `stock_items.set_pricing` | ✅ |
|
||||||
| Fulfill from stock for order | fulfilment flow | `POST /stock/fulfill` | `stock.fulfill` | ✅ |
|
| Fulfill from stock for order | fulfilment flow | `POST /stock/fulfill` | `stock.fulfill` | ✅ |
|
||||||
| Surplus book | fulfilment flow | `POST /stock/surplus-book` | `stock.surplus_book` | ✅ |
|
| Surplus book | fulfilment flow | `POST /stock/surplus-book` | `stock.surplus_book` | ✅ |
|
||||||
| List stock purchases | `/stock-orders` | `GET /stock-purchases/list` | `stock_purchases.list` | ✅ |
|
| List stock purchases | `/stock-orders` | `GET /stock-purchases/list` | `stock_purchases.list` | ✅ |
|
||||||
|
|
|
||||||
|
|
@ -105,6 +105,7 @@ These came up but need a human answer before code changes:
|
||||||
|
|
||||||
## Implemented
|
## Implemented
|
||||||
|
|
||||||
|
- 2026-10-01 — **`stock_items.set_pricing` + pricing fields on `stock_items.create`.** Surfaced when Giellie added a stock item via `stock_items.create` but couldn't set a cost price or markup: `create` had no pricing fields and `stock_items.update` deliberately excludes `cost_price` (owned by the booking flow). New MCP tool `stock_items.set_pricing({updates: [{id, cost_price?, selling_price?, markup?}] (1–100), actor: {id, name}})` wraps the existing `updateStockItemsPricing` service (same one behind `POST /api/v1/stock/items/set-pricing` and the /stock inline edit): per-row results, cost changes audited in `stock_ledger` with the actor, quantities untouched. `actor.id` is required; unknown keys are rejected by name. `stock_items.create` now accepts optional `cost_price`, `selling_price`, `markup` (finite numbers >= 0) and runs the payload through `applyDefaultMarkupToPatch` like bulk import — a cost with no selling price/markup gets the 80% default and a seeded `cost_history`; caller-supplied values are never overwritten. The POS till reads `selling_price`, not `markup`, so the tool descriptions and Giellie's system prompt tell the agent to set both (selling = cost × (1 + markup/100)). Giellie policy: classified `write` (approval required). Schema needs: none. `docs/api-mcp-layer.md` catalogue regenerated (137 → 144 tools, includes drift from earlier tools).
|
||||||
- 2026-08-16 — **Phase H: orders-side coverage expansion (mega-PR, 10 items).** (a) New MCP wrappers for existing REST routes: `orders.archive`, `orders.cancel`, `orders.review_save`. (b) `orders.list` filter surface widened — `customer` (id or name), `createdAfter`, `createdBefore`, `status` (tab-group name; resolves via `getOrderIdsForTabGroup` and short-circuits with zero matches). (c) Brand-new analytics surface: `orders.stats` (REST + MCP, `from`/`to`/`groupBy=day|customer|supplier`) and `orders.daily_summary` (REST + MCP, `?date=YYYY-MM-DD`). `groupBy: "supplier"` is preserved for forward compat but documented as "(no order-level supplier)" until PB gets the relation. (d) New lifecycle actions: `orders.mark_invoiced` (idempotent; refuses 409 with `offendingItemIds[]` if any item ≠ `invoiced`) and `orders.mark_delivered` (flips every eligible item past `collected`/`picking`/`stock_verified`/`ready_delivery`/`ready_invoice`/`invoiced`/`stock_booked`/`with_driver`/`checked_in`/`completed` to `delivered`; stamps `delivered_at` + `delivered_date`; reports per-item failures). Both return `OrderHeaderActionResult` mirroring the `CancelOrderResult` shape. (e) New `orders.update` (PATCH `/api/v1/orders/[id]`, whitelisted to `notes`, `contact_name`, `description`, `rep`, `email_cc`, `email_bcc`, `quote_reference_text`, `invoiced`, `quote_match_method`) and `orders.add_note` (thin wrapper that REPLACES `notes` — operator reads first then patches). (f) New `order_items.create` on existing orders (POST `/api/v1/orders/[id]/items`) — strict-pending-gated: refuses 409 `order_locked` with `offendingItemIds[]` if any existing item on the order is past `item_status === "pending"`. Auto-derives `selling_price` from `cost_price × (1 + markup/100)` via the existing `deriveSellingPriceIfOmitted` helper; secondary fields (sku/unit/supplier/notes) patched via the existing post-create loop. (g) Whitelist consolidation: `ORDER_ITEM_PATCH_FIELDS` promoted to `ORDER_ITEM_PATCHABLE_FIELDS` in `src/lib/server/order-items-service.ts`; both the REST PATCH handler and the MCP dispatcher import from the service layer. The REST handler keeps a narrower `POPOVER_PATCHABLE_FIELDS` for the operator popover (lifecycle/invoice fields intentionally excluded). New tools: 9 (`orders.archive`, `orders.cancel`, `orders.review_save`, `orders.stats`, `orders.daily_summary`, `orders.mark_invoiced`, `orders.mark_delivered`, `orders.update`, `orders.add_note`, `order_items.create` — actually 10). Closes the `customer`/`createdAfter`/`createdBefore`/`status`/`aggregate`/daily-summary/`order_items.create`/PBCwhitelist-drift gaps from the Open Requests section above. Tool count: 127 → 137. `docs/api-mcp-layer.md` regenerated.
|
- 2026-08-16 — **Phase H: orders-side coverage expansion (mega-PR, 10 items).** (a) New MCP wrappers for existing REST routes: `orders.archive`, `orders.cancel`, `orders.review_save`. (b) `orders.list` filter surface widened — `customer` (id or name), `createdAfter`, `createdBefore`, `status` (tab-group name; resolves via `getOrderIdsForTabGroup` and short-circuits with zero matches). (c) Brand-new analytics surface: `orders.stats` (REST + MCP, `from`/`to`/`groupBy=day|customer|supplier`) and `orders.daily_summary` (REST + MCP, `?date=YYYY-MM-DD`). `groupBy: "supplier"` is preserved for forward compat but documented as "(no order-level supplier)" until PB gets the relation. (d) New lifecycle actions: `orders.mark_invoiced` (idempotent; refuses 409 with `offendingItemIds[]` if any item ≠ `invoiced`) and `orders.mark_delivered` (flips every eligible item past `collected`/`picking`/`stock_verified`/`ready_delivery`/`ready_invoice`/`invoiced`/`stock_booked`/`with_driver`/`checked_in`/`completed` to `delivered`; stamps `delivered_at` + `delivered_date`; reports per-item failures). Both return `OrderHeaderActionResult` mirroring the `CancelOrderResult` shape. (e) New `orders.update` (PATCH `/api/v1/orders/[id]`, whitelisted to `notes`, `contact_name`, `description`, `rep`, `email_cc`, `email_bcc`, `quote_reference_text`, `invoiced`, `quote_match_method`) and `orders.add_note` (thin wrapper that REPLACES `notes` — operator reads first then patches). (f) New `order_items.create` on existing orders (POST `/api/v1/orders/[id]/items`) — strict-pending-gated: refuses 409 `order_locked` with `offendingItemIds[]` if any existing item on the order is past `item_status === "pending"`. Auto-derives `selling_price` from `cost_price × (1 + markup/100)` via the existing `deriveSellingPriceIfOmitted` helper; secondary fields (sku/unit/supplier/notes) patched via the existing post-create loop. (g) Whitelist consolidation: `ORDER_ITEM_PATCH_FIELDS` promoted to `ORDER_ITEM_PATCHABLE_FIELDS` in `src/lib/server/order-items-service.ts`; both the REST PATCH handler and the MCP dispatcher import from the service layer. The REST handler keeps a narrower `POPOVER_PATCHABLE_FIELDS` for the operator popover (lifecycle/invoice fields intentionally excluded). New tools: 9 (`orders.archive`, `orders.cancel`, `orders.review_save`, `orders.stats`, `orders.daily_summary`, `orders.mark_invoiced`, `orders.mark_delivered`, `orders.update`, `orders.add_note`, `order_items.create` — actually 10). Closes the `customer`/`createdAfter`/`createdBefore`/`status`/`aggregate`/daily-summary/`order_items.create`/PBCwhitelist-drift gaps from the Open Requests section above. Tool count: 127 → 137. `docs/api-mcp-layer.md` regenerated.
|
||||||
- 2026-08-14 — **Block A: "feels restricted" MCP pain fixes.** (a) `scripts/mcp-doc-gen.py` now auto-regenerates the catalogue in `docs/api-mcp-layer.md` from the live `tools` array — the doc had drifted to claiming 23 tools when the real count was 103. Run `python3 scripts/mcp-doc-gen.py --check` in CI. (b) Hard-coded `actorId`/`actorName` in `purchase_orders.record_diff_report` and `stock_purchases.receive` replaced with required `actor: { id, name }` input — both match the shape already used by `order_items.confirm_collected`. Audit entries now record the real agent identity. (c) Whitelist drift closed: `category` added to `QUOTE_ITEM_PATCH_FIELDS`; `sku`, `category`, `unit` added to `ORDER_ITEM_PATCH_FIELDS` and to `order_items.update`'s inputSchema. Resolves the "can I change the category?" / "set the SKU on PO items" requests above. (d) Eight terse tool descriptions (`orders.create_from_quote`, `order_items.update_status`, `collection_pool.list`, `collection_confirm.list`, `quotes.find_by_message_id`, `quotes.create_from_template`, `purchase_orders.retry_email`, `quotes.retry_email`, `sprint.item_attachments`) bulked up to match the bar set by `order_items.confirm_collected`. (e) New `docs/agents/workflows.md` cookbook — six end-to-end recipes an agent can drive without further prompting (supplier invoice, order split, partial collection, bulk pricing, partial approve + split, sprint claim).
|
- 2026-08-14 — **Block A: "feels restricted" MCP pain fixes.** (a) `scripts/mcp-doc-gen.py` now auto-regenerates the catalogue in `docs/api-mcp-layer.md` from the live `tools` array — the doc had drifted to claiming 23 tools when the real count was 103. Run `python3 scripts/mcp-doc-gen.py --check` in CI. (b) Hard-coded `actorId`/`actorName` in `purchase_orders.record_diff_report` and `stock_purchases.receive` replaced with required `actor: { id, name }` input — both match the shape already used by `order_items.confirm_collected`. Audit entries now record the real agent identity. (c) Whitelist drift closed: `category` added to `QUOTE_ITEM_PATCH_FIELDS`; `sku`, `category`, `unit` added to `ORDER_ITEM_PATCH_FIELDS` and to `order_items.update`'s inputSchema. Resolves the "can I change the category?" / "set the SKU on PO items" requests above. (d) Eight terse tool descriptions (`orders.create_from_quote`, `order_items.update_status`, `collection_pool.list`, `collection_confirm.list`, `quotes.find_by_message_id`, `quotes.create_from_template`, `purchase_orders.retry_email`, `quotes.retry_email`, `sprint.item_attachments`) bulked up to match the bar set by `order_items.confirm_collected`. (e) New `docs/agents/workflows.md` cookbook — six end-to-end recipes an agent can drive without further prompting (supplier invoice, order split, partial collection, bulk pricing, partial approve + split, sprint claim).
|
||||||
- 2026-08-14 — **Block E: 22 new MCP tools wrapping the missing REST surface.** Categories added to the catalogue: `users.lookup` (operator identity for audit stamps); `dashboard.daily_summary`, `orders.sprint_counts`, `orders.find_duplicates` (aggregate reads); `orders.review`, `orders.matched_attachments` (operator-triage reads); `files.fetch` (PB file → base64 proxy); `drivers.list_stops`, `drivers.update_stop_status` (driver dispatch); `stock_quick_draft.search`, `.add_line`, `.suppliers` (buyer quick-draft); `delivery_notes.list`, `.create`, `.cancel`, `.mark_invoiced`, `.mark_complete`, `.regenerate_pdf`, `.create_quote`, `.set_customer_po`, `.set_item_quantity`, `.combine` (full DN write surface). Total tool count: 103 → 125. Each new tool wraps the matching `/api/v1/*` REST route via `fetch` (preserves the audit trail + service-layer behaviour). `delivery_notes.list` reads the `delivery_notes` collection directly via the admin PB client because the REST surface has no GET; all other reads/writes go through REST. Closes the "delivery-notes.*", "drivers.*", "stock_quick_draft.*", "dashboard.daily_summary", "users.lookup", "orders.review", "files.fetch" gaps surfaced in the audit.
|
- 2026-08-14 — **Block E: 22 new MCP tools wrapping the missing REST surface.** Categories added to the catalogue: `users.lookup` (operator identity for audit stamps); `dashboard.daily_summary`, `orders.sprint_counts`, `orders.find_duplicates` (aggregate reads); `orders.review`, `orders.matched_attachments` (operator-triage reads); `files.fetch` (PB file → base64 proxy); `drivers.list_stops`, `drivers.update_stop_status` (driver dispatch); `stock_quick_draft.search`, `.add_line`, `.suppliers` (buyer quick-draft); `delivery_notes.list`, `.create`, `.cancel`, `.mark_invoiced`, `.mark_complete`, `.regenerate_pdf`, `.create_quote`, `.set_customer_po`, `.set_item_quantity`, `.combine` (full DN write surface). Total tool count: 103 → 125. Each new tool wraps the matching `/api/v1/*` REST route via `fetch` (preserves the audit trail + service-layer behaviour). `delivery_notes.list` reads the `delivery_notes` collection directly via the admin PB client because the REST surface has no GET; all other reads/writes go through REST. Closes the "delivery-notes.*", "drivers.*", "stock_quick_draft.*", "dashboard.daily_summary", "users.lookup", "orders.review", "files.fetch" gaps surfaced in the audit.
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue