Commit graph

408 commits

Author SHA1 Message Date
SJCoetz
c5fbb7422f test(context): OrderItemContextPopoverTrigger UI tests
Co-authored-by: Orca <help@stably.ai>
2026-08-07 02:55:39 +02:00
SJCoetz
f75c1b2bbd feat(context): OrderItemContextPopoverTrigger (ⓘ on orders page)
Co-authored-by: Orca <help@stably.ai>
2026-08-07 02:55:14 +02:00
SJCoetz
b3a73c0040 test(context): OrderItemContextPanel UI tests
Co-authored-by: Orca <help@stably.ai>
2026-08-07 02:54:24 +02:00
SJCoetz
efd2ad6540 feat(context): OrderItemContextPanel (inline expandable, 4 rows)
Co-authored-by: Orca <help@stably.ai>
2026-08-07 02:53:21 +02:00
SJCoetz
5291fd2fd1 test(context): /api/v1/order-items/[id]/context route tests
Co-authored-by: Orca <help@stably.ai>
2026-08-07 02:50:44 +02:00
SJCoetz
7ad7375dd2 feat(context): GET /api/v1/order-items/[id]/context route
Co-authored-by: Orca <help@stably.ai>
2026-08-07 02:46:18 +02:00
SJCoetz
351c1b2b96 test(context): getOrderItemContext unit tests (null, quote, stock low/out, invoiced)
Co-authored-by: Orca <help@stably.ai>
2026-08-07 02:42:57 +02:00
SJCoetz
ced25be47a feat(context): implement getOrderItemContext (5 PB reads, fuzzy fallback)
Co-authored-by: Orca <help@stably.ai>
2026-08-07 02:34:45 +02:00
SJCoetz
18afe7d2d9 feat(context): add order-item-context-service skeleton + types
Co-authored-by: Orca <help@stably.ai>
2026-08-07 02:23:45 +02:00
Claude
357decbb2b docs(plan): order-item context block — 12 TDD tasks
Implementation plan for the spec at
docs/superpowers/specs/2026-08-07-order-item-context-block-design.md.

Tasks: backend service skeleton + impl + tests, /api/v1/.../context
endpoint + tests, OrderItemContextPanel + tests,
OrderItemContextPopoverTrigger + tests, sprint modal wire-in, orders
page wire-in, full test suite + build smoke.

Each task follows a TDD cycle: write failing test, run to confirm,
implement minimal code, run to confirm pass, commit.

Co-Authored-By: Claude <noreply@anthropic.com>

Co-authored-by: Orca <help@stably.ai>
2026-08-07 02:18:28 +02:00
Claude
3f82b0784d docs(spec): order-item context block (sprint modal + orders page)
Replaces the AI Insights section in order-sprint-process-modal with a
deterministic PocketBase-derived context block (last quote, last order,
last invoiced, stock). Same backend exposed as a popover trigger on
the orders detail page, replacing the existing AI-history ⓘ there.

Backend: new src/lib/server/order-item-context-service.ts +
GET /api/v1/order-items/[id]/context. Reuses pure helpers from
item-history-service (normaliseSkuForHistory, findBestDescriptionMatch,
aggregateSuppliers, computeCheapest).

UI: new <OrderItemContextPanel/> (inline expandable for the sprint
modal) and <OrderItemContextPopoverTrigger/> (ⓘ popover for orders
page). Apply = cost + supplier only; selling stays locked to the order.

Co-Authored-By: Claude <noreply@anthropic.com>

Co-authored-by: Orca <help@stably.ai>
2026-08-07 02:16:31 +02:00
SJCoetz
f35779369a fix(stock-purchase-items): drop dead drv_collected_at write to unblock build
The markLineCollected service and the stock-orders page's
handleAssignDriver (delivery-sentinel auto-collect path) both
wrote `drv_collected_at` to `stock_purchase_items`, but that
field exists on `order_items`, not on `stock_purchase_items`
(verified against pb_schema-2.json). Per AGENTS.md "select
fields are not self-service", PB would 500 both writes at
runtime. The TS error from the service was the build break
flagged in the 2026-08-06 23:34 deployment.

The page.tsx write was a latent runtime bug — TypeScript
never caught it because PB's loose `update` patch typing
accepts any field name. Both writes are removed; the
collection moment is captured by PB's `updated` timestamp on
the line row, which is sufficient for the auto-collect audit
trail. Inline comments point to FEATURE-REQUESTS as the
follow-up if a dedicated collection-date field is wanted
later (would need a PB admin schema change).

Also drops the matching test assertions that read
`drv_collected_at` off the response and replaces them with
a comment explaining the absence.

Tests: vitest 59/59 across stock-purchase-items-service +
stock-orders/[id]; npm run build compiles clean
(Next.js 16.2.6 Turbopack + TypeScript).

Co-Authored-By: Claude <noreply@anthropic.com>

Co-authored-by: Orca <help@stably.ai>
2026-08-07 01:39:03 +02:00
SJCoetz
fe8a3c6872 feat: rework invoicing stock booking section
Move StockBookingSection from above the tab strip into the To Invoice tab's card list for consistent visual styling. Add expandable, lazy-loaded purchase order line items with session-based caching to reduce redundant network requests. Update component UI, styling, and documentation, and fix test mocks to prevent conflation of stock_purchases and order_items collection calls. Add ZAR currency formatting helper for displaying stock line item costs.
2026-08-07 01:07:56 +02:00
SJCoetz
c4125ee40a feat: add split-invoice stock PO workflow and supporting tooling
Ship full split-invoice stock purchase order workflow:
- Add 5 new MCP tools for per-line stock purchase item management and catalogue updates
- Add idempotent database migration adding sku, unit, and supplier_sku fields to stock_purchase_items
- Implement service layers for all new operations, including auto-closing the parent PO when all lines are fully collected
- Add complete test coverage for new services and API routes
- Update all relevant documentation including MCP API specs, agent instructions, and feature request logs
2026-08-07 00:53:29 +02:00
SJCoetz
d167f81ad5 feat(stock-orders): inline cost_price editing on lines table
Co-authored-by: Orca <help@stably.ai>
Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-06 23:36:27 +02:00
SJCoetz
d5ed390de4 feat(pb): add stock_purchases.additional_attachments file field (migration)
Co-authored-by: Orca <help@stably.ai>
2026-08-06 23:32:12 +02:00
SJCoetz
bbfe20ec2d docs: register stock_purchases.add_attachment in feature backlog + API reference
Co-authored-by: Orca <help@stably.ai>
2026-08-06 23:29:55 +02:00
SJCoetz
dd57d29de3 feat(stock-orders): attachments card on detail page
Co-authored-by: Orca <help@stably.ai>
2026-08-06 23:29:00 +02:00
SJCoetz
f89bbb3a35 feat(mcp): add stock_purchases.add_attachment tool
Co-authored-by: Orca <help@stably.ai>
2026-08-06 23:24:00 +02:00
SJCoetz
ccf04bc39f feat(api): add stock-purchase attachments delete route
Co-authored-by: Orca <help@stably.ai>
2026-08-06 23:21:25 +02:00
SJCoetz
a72c5ca0a7 feat(api): add stock-purchase attachments upload route
Co-authored-by: Orca <help@stably.ai>
2026-08-06 23:21:00 +02:00
SJCoetz
70c158b374 feat(stock-purchases): add additional_attachments service helpers
Co-authored-by: Orca <help@stably.ai>
2026-08-06 23:20:26 +02:00
SJCoetz
9e118a3b5f feat(stock-purchase): split warehouse confirm from accountant booking
Repositioned booking responsibility: warehouse confirms physical
collection only (records quantity_received + flips header to
"received"); the accountant books into inventory via the new
invoicing flow once the supplier invoice is processed. This way
the payment-cycle reasoning lives at the booking step, not at
receipt.

Changes
- Migration: add booked_at + booked_by to stock_purchases
- Service: bookStockFromInvoice (accountant-side, splits from
  bookStockRows)
- API route: POST /api/v1/invoicing/stock-book
- UI: stock rows surfaced on invoicing page (StockBookingSection)
- UI: stock-purchase detail page
  - Driver picker on header (sentinel "delivery" user auto-collects
    every line, real drivers set assigned_to_driver)
  - "Confirm collection" replaces "Mark received" (warehouse-side
    only — no inventory writes)
  - Cancel button with confirmation dialog
- collection-confirm: confirmStockRows stripped of inventory writes;
  the prior /api/v1/collection-confirm/book-stock route was renamed
  to /confirm-stock and is now strictly the warehouse-side confirm
- Tests for all new flows (5/5 passing on the stock-order detail
  page; 10/10 on StockBookingSection)

Co-Authored-By: Claude <noreply@anthropic.com>

Co-authored-by: Orca <help@stably.ai>
2026-08-06 23:01:15 +02:00
SJCoetz
df87094eb9 chore(playwright): add 2026-08-06 test artifacts
Add captured Playwright page state snapshots and console logs from the 2026-08-06 test session, stored in the .playwright-mcp directory.
2026-08-06 19:38:39 +02:00
SJCoetz
bf54511db1 fix(buyer-tasks): make card layout mobile-friendly
At <=640px the buyer-tasks card content was crushed by the action
column sitting beside it: the PO number badge broke mid-string
('PO-2026-08-042' wrapping to 4 lines), supplier names wrapped to
6 lines, and the new 'Sent to ...' caption overlapped the PO
badge on the PO Sent tab.

Three responsive tweaks, all using Tailwind breakpoint utilities:

1. Outer card container switches from 'flex items-start' to
   'flex flex-col sm:flex-row sm:items-start'. The action column
   drops below the info column on mobile, giving the info all the
   available width and the buttons full-width tap targets.

2. PO number badge gains 'whitespace-nowrap'. The badge stays
   atomic; the parent's 'flex-wrap' carries the whole badge to a
   new line when it doesn't fit.

3. PO Sent right column: buttons stack vertically on mobile
   ('flex-col sm:flex-row' + 'flex-1 sm:flex-none' on each
   button) and the caption switches from 'text-right' to
   'text-left sm:text-right' so it sits under the buttons.

Desktop layout is unchanged — verified at 1280px that the
side-by-side buttons, right-aligned caption, and inline single
button all still render exactly as before.

Co-Authored-By: Claude <noreply@anthropic.com>

Co-authored-by: Orca <help@stably.ai>
2026-08-06 18:21:38 +02:00
SJCoetz
d2ffbea6bc feat(buyer-tasks): show recipient + send date on PO Sent card
Adds a small muted caption under the Re-Send / Mark as ready buttons
on the PO Sent tab showing the email address the PO was sent to and
the send timestamp (en-GB short format like '5 Aug 2026, 14:23').

Data sources come from the existing BuyerTaskGroup.emailPayload
exposed in commit f61c173 — no new PB fields, no new types. The
caption only renders when sentAt is present, so legacy rows (or a
fresh draft flipped to po_sent without a successful send) stay clean.

Visible on mail_failed too: the operator can see who we tried to
reach and when, alongside the existing 'Mail failed' banner.

Co-Authored-By: Claude <noreply@anthropic.com>

Co-authored-by: Orca <help@stably.ai>
2026-08-06 18:16:22 +02:00
SJCoetz
f3052bfd40 Merge branch 'feat/buyer-tasks-resend-task1'
Adds a Re-Send button next to Mark as ready on the PO Sent tab of the buyer-tasks page. The button opens the existing SendPoModal in resend mode, pre-filled from the PO's previous email_payload (to/cc/bcc/subject/body). Also migrates the hardcoded purple Mark-as-ready color to the themed primary token, and fixes the mail-failed 'Resend' label that previously opened the wrong dialog.
2026-08-06 18:11:59 +02:00
SJCoetz
add7ab3302 fix(send-po-modal): seed default body when resend has no prior email_payload
Co-Authored-By: Claude <noreply@anthropic.com>

Co-authored-by: Orca <help@stably.ai>
2026-08-06 18:10:08 +02:00
SJCoetz
abdc3a4d9f fix(send-po-modal): preserve previous message body on resend (don't overwrite with default template)
Co-authored-by: Orca <help@stably.ai>
2026-08-06 18:06:22 +02:00
SJCoetz
f61c173a1a fix(buyer-tasks): surface PO email_payload + attachments on group for resend modal prefill
Co-Authored-By: Claude <noreply@anthropic.com>

Co-authored-by: Orca <help@stably.ai>
2026-08-06 18:01:58 +02:00
SJCoetz
6008f17c9a feat(buyer-tasks): add Re-Send button on PO Sent tab + theme-token cleanup
Co-Authored-By: Claude <noreply@anthropic.com>

Co-authored-by: Orca <help@stably.ai>
2026-08-06 17:43:17 +02:00
SJCoetz
ff94086ec0 docs(plan): add implementation plan for Re-Send button on PO Sent tab
Co-authored-by: Orca <help@stably.ai>
2026-08-06 17:34:28 +02:00
SJCoetz
3a954982d0 docs(spec): add Re-Send button on PO Sent tab of buyer-tasks
Co-authored-by: Orca <help@stably.ai>
2026-08-06 17:33:25 +02:00
SJCoetz
7f477ca949 fix: resolve PO bug, add sku, improve webhooks
Add `sku` to the order_item.patch MCP tool whitelist and update its documentation
Fix stuck stock POs in buyer tasks po_sent tab by filtering out downstream statuses
Rewrite margin approval webhook to use fire-and-forget dispatch to avoid UI blocking, add server-side error logging
Add MCP feature requests and local setup documentation
2026-08-06 13:13:57 +02:00
SJCoetz
4a69b57ec2 docs(pdf): remove stray duplicate 'from quoteSubtotal() in two ways:' line
Co-authored-by: Orca <help@stably.ai>
2026-08-06 12:22:22 +02:00
SJCoetz
68dcdd565d chore(pdf): silence unused-vars on intentional totalAmount destructure
Co-authored-by: Orca <help@stably.ai>
2026-08-06 12:21:00 +02:00
SJCoetz
180288e6e3 test(pdf): add render smoke tests for PO PDF (covers VAT totals)
Co-authored-by: Orca <help@stably.ai>
2026-08-06 12:13:52 +02:00
SJCoetz
07900075a4 docs(pdf): move VAT bullet to Layout block + tidy effective-qty comment
Co-authored-by: Orca <help@stably.ai>
2026-08-06 12:08:14 +02:00
SJCoetz
7a6e32cadb feat(pdf): add 15% VAT line + VAT-inclusive Total to PO PDF
Co-authored-by: Orca <help@stably.ai>
2026-08-06 12:02:55 +02:00
SJCoetz
a1714833a8 docs(pdf): fix poSubtotal JSDoc summary (effective-qty prose) + tidy blank lines
Co-authored-by: Orca <help@stably.ai>
2026-08-06 12:00:48 +02:00
SJCoetz
965f3e3bbe docs(pdf): restore poSubtotal JSDoc + clarify fallback uses || not ??
Co-authored-by: Orca <help@stably.ai>
2026-08-06 11:56:51 +02:00
SJCoetz
b3d9eeb5ce feat(pdf): add poSubtotal helper for PO PDF totals
Co-authored-by: Orca <help@stably.ai>
2026-08-06 11:54:23 +02:00
SJCoetz
40d069b5aa docs(plan): add 15% VAT to supplier PO PDF implementation plan
Co-authored-by: Orca <help@stably.ai>
2026-08-06 11:48:21 +02:00
SJCoetz
a663de2d36 docs(spec): clarify placement of vat computation
Co-authored-by: Orca <help@stably.ai>
2026-08-06 11:45:11 +02:00
SJCoetz
3beedc7ad6 docs(spec): add 15% VAT to supplier-facing PO PDF
Co-authored-by: Orca <help@stably.ai>
2026-08-06 11:44:54 +02:00
SJCoetz
5053ec96ea test: add quote detail page layout regression tests
Add a vitest suite that enforces critical layout invariants for the quote detail page, and include accompanying Playwright trace snapshots and console logs from the test execution.
2026-08-06 02:04:28 +02:00
SJCoetz
e2bcafe4d8 chore(playwright-mcp): add test snapshot and console logs 2026-08-06 01:56:47 +02:00
SJCoetz
2bd8fcf247 fix: resolve PocketBase expand projection bug
This commit fixes a critical PocketBase projection bug where omitting "expand" from fields lists silently drops related data, leading to missing supplier/customer/order info across the app. It also includes usability improvements and test coverage:

1.  Add "expand" to PB fields projections in invoicing page, quotes lookup API, sprint page, and quote search helper
2.  Update PO Sent tab filter to exclude "collected" and "ready_invoice" statuses
3.  Reorder buyer tasks list to sort by supplier first, then order number
4.  Add comprehensive regression tests for all fixed issues

Included Playwright test capture artifacts from local testing.
2026-08-06 01:33:16 +02:00
SJCoetz
d8dea63d16 feat(invoicing): include sibling order items in invoicing rows
- extract reusable constants and helper functions including escapeFilterValue, dedupeRawRows, listAllInvoicingRows, and loadInvoicingRows
- add safe filter value escaping to prevent query injection risks
- rewrite data fetching to pull all related order items for orders with ready-to-invoice rows, then deduplicate results
- replace raw getFullList calls with paginated PocketBase API usage
- update test suite to mock getList instead of getFullList and add coverage for new behavior
- clean up redundant eslint disable comments in modal components
2026-08-05 23:17:06 +02:00
SJCoetz
9f601002af refactor(collection-confirm): make PO cards start collapsed by default
Remove the initial open state for the first PO card, and update all tests to expect the default collapsed state. Users can expand cards manually to view contents, improving scannability for long PO queues.
2026-08-05 23:08:44 +02:00