Two small, independent rendering improvements for /deliveries and /orders:
1. /deliveries — each delivery-note row gets a compact subline with
customer name, company name, parent order number, and a signed-copy
indicator (paperclip + filename tooltip). All data already on the
row payload — no server-side changes.
2. /orders — order card right-aligned metadata slot gets a colour-
coded age badge (today / Xd old) replacing the bare date string.
New src/lib/order-age.ts as a pure function with bucket thresholds
(green <3d, amber 3-7d, orange 8-14d, red 15+d) and a unit test.
No PB schema changes. No /api/v1 route changes. No MCP tool changes.
Co-Authored-By: Claude Code <noreply@anthropic.com>
Two spec-vs-implementation drifts caught by the final review:
- Move 'per-row validation → 200 with reason in results[]' out of the
'Reject 400' list. The route enforces body shape (json / empty /
too-many / bad id / missing actor) as 400; the service enforces
forbidden_field / non-finite / not_found / pb_error per row so one
bad sibling never aborts the rest.
- Move the 'realtime-conflict banner' from Page-behaviour to Out of
scope (the implementation deferred it; the spec still listed it).
Scopes hardening the existing POS mockup (superuser creds removed,
catalog moved to stock_items, checkout wired to stock_ledger) as a
route inside WFDASH-WEBAPP rather than a separate service.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Three documents behind the two features on this branch:
- specs/2026-08-30-non-invoiceable-order-extras-design.md — the design
the implementation followed, including why the flag must be named for
the exception (a positively-named field defaults to false and would
mark every existing row non-billable the moment it is created).
- plans/2026-08-30-non-invoiceable-order-extras.md — the task-by-task
plan, now fully implemented.
- specs/2026-08-30-quantity-handling-audit.md — the order_qty /
quantity audit that produced the preceding fix, plus the partial
collection findings that are still open.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Design for closing three gaps in the existing order↔quote matcher:
- The matcher only runs when an operator clicks it, so the ~85% of
orders that arrive against a quote stay unlinked. Adds a call from
createOrder plus a catch-up sweep for the backlog.
- order_items.quote_item is only written when an order is created
from a quote, so post-hoc links never pair lines. Adds persistence
for confident pairs.
- findMatchedQuoteItem re-guesses the pairing at render time using
exact/substring matching, so buyer notes and per-line attachments
silently vanish on any wording difference. Replaced with the
tokenised matcher already in the repo.
Fuzzy candidates are windowed to 90 days before the order's own date
(widening to 12 months only when nothing clears the threshold);
exact-identifier lookups stay unwindowed.
No PocketBase schema changes required.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Lifts the detail-screen "Approve & send email" button behaviour onto
the pending-approvals list rows. Replaces the list's existing
two-step approve + drill-in flow with the existing combined
review-approve endpoint behind the same SendQuoteModal the detail
page already uses.
Out of scope: "approve without send" toggle in the modal, inline
markup-edit on a row.
Co-Authored-By: Claude <noreply@anthropic.com>
Adds is_no_quote boolean to quotes collection so operators can send
an official decline letter on a quote the company cannot price.
Spec covers schema, service-layer gate relaxations, PDF rendering,
UI toggle placement, error edges, tests, and rollout.
Approach A (surgical flag relaxation) chosen over B/C during
brainstorming to keep v1 minimal and reversible.
Co-Authored-By: Claude <noreply@anthropic.com>
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>
Two small additions to /stock-orders:
- Wrap long text in Number + Supplier columns
- Two PDF download buttons (Stocktake PDF, Orders PDF)
Both PDFs always include all rows, ignore the active status
filter and pagination. No persistence — throwaway reports.
Design reviewed: covers architecture, data model, API contract,
error handling, testing, and manual smoke. No new PB schema,
no new types.
Co-authored-by: Orca <help@stably.ai>
Add an Approved design doc for the /stock-orders list table: two new
currency columns (Ordered, Received) showing sum(line.quantity *
line.cost_price) and sum(line.quantity_received * line.cost_price) per
stock purchase. Migrates the page from client-side direct PB read to
the service layer per AGENTS.md.
Co-authored-by: Orca <help@stably.ai>
Mail-failed POs currently vanish from every buyer-tasks tab because
the po_draft and po_sent filters both exclude the 'mail_failed' status.
This adds a focused design that surfaces them in place inside PO Draft
with a red warning row + 'Resend' button that re-opens the shared
SendPoModal.
Co-Authored-By: Claude <noreply@anthropic.com>
Co-authored-by: Orca <help@stably.ai>
Removes the Adjust Quantity modal, surfaces invoice photos in a per-PO
strip, exposes inline-editable cost prices, and migrates the page to a
thin service layer (listCollectedItems, updateOrderItemCost,
confirmOrderItemsForInvoicing) with three new /api/v1 routes. Cost edits
are audited in the existing notes feed as category=cost entries; confirm
is one PocketBase batch.
Co-authored-by: Orca <help@stably.ai>
Adds spec for the new item-first quick-draft modal on /stock-orders:
item-first stock-order entry, accumulates per supplier into draft POs,
reuses existing Send/Receive flow. No schema changes.
Co-authored-by: Orca <help@stably.ai>
Redesign the per-item ⓘ popover on /sprint so it surfaces actionable history
(cheapest supplier, other quotes to this company, last sold, recommendation)
instead of the current decorative rainbow card.
- Deterministic PB-join service (new) computes suppliers, other quotes, last
sold, stock from existing collections.
- Existing n8n AI blob keeps running — render side by side for comparison.
- After 1 week: delete whichever data source loses on speed / freshness /
cost.
- Process orders section is a separate follow-up round.
Also ignore .superpowers/ (visual companion mockups are local-only).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Orca <help@stably.ai>
Add full Tangerine brand theme with light and dark mode variants to the app theme system.
Add four new design and integration documents for collection pool, map and driver app workflows.
Add initial scaffolding for three new plugin source directories for the collection pool bulk assignment feature.
Two-pin model per supplier bucket: blue circle + letter per driver,
amber circle + ✓/✕ for unassigned. Filters (status, readiness, driver
multi-select, search) all leave; date picker stays. No backend or
schema changes. Awaiting user review before plan + implementation.
- Add Supplier Map component to suppliers page and reorganize sidebar navigation
- Implement picking slip PDF generation with supplier per line item and picked-by signature footer
- Add invoice bulk print tracking API and view models to track printed invoice state
- Extend company search and form to support email/telephone fields and improve searchability
- Fix data table debounce race condition by using useRef for onSearch handler
- Fix supplier page fetch race condition with debounced timeout
- Reduce list page item counts to 10 per page for customers, companies, and suppliers
- Update company search filter to include email and telephone in search queries
- Add comprehensive test suite for new and existing components and APIs
- Add pdf-lib dependency for PDF generation and update related tooling
- Clean up unused code and fix minor linting issues
Add complete end-to-end QuickBooks invoicing workflow for the invoicing page:
- Add `jspdf` dependency for client-side PDF generation
- Implement updated item status handling with fallback for new invoice statuses
- Add server-side proxy API for secure QuickBooks customer lookup
- Build utilities to combine QuickBooks invoices and picking slips into a single PDF
- Add invoicing view models for row grouping, payload construction, and status checks
- Add full test coverage for all new components, APIs, and utilities
- Include feature design documentation and sample n8n workflow config
Implement the complete collection confirm feature set:
- Add new `/collection-confirm` operational page for reviewing and confirming collected order items
- Add sidebar navigation entries for Collection Confirm and Invoicing
- Add `order_items` to the file proxy API whitelist for attachment access
- Install required testing dependencies and configure Vitest test setup
- Add full design documentation, test suite, and page overview screenshot
- Update package.json and build configuration files
Add optional nearby-supplier cluster sort mode to the collection pool table, keeping operational sort as the default. Also includes:
- Update UserSearch component to support fallback selected label for pre-selected values
- Refactor AssignDriverDialog into a separate inner component with intent and pre-filled driver label support
- Add assignment badge helper types and functions
- Add full test coverage for new sort logic and component behaviors
- Update implementation plans and documentation files
- Fix minor code consistency and lint issues across touched files
Remove redundant Assign Drivers top-level navigation link since driver assignment is now embedded directly in the collection pool page per-row, and add an Other nav section for leftover navigation items
Extract collection pool view logic into a dedicated view-model module with full Vitest test coverage for assignment state classification, row sorting, pool age labeling, and proximity marker grouping
Flatten the collection pool page into a single unified list replacing the old grouped assigned/unassigned layout, with updated row UI showing all required operational details and context-aware actions
Add database migration to add optional `collection_photo` field to order_items for driver pickup proof photos
Add complete design documentation, planning artifacts, and brainstorming session files for the collection pool redesign project