Commit graph

40 commits

Author SHA1 Message Date
SJCoetz
02458909f7 docs(collection-map): tighten Refresh-button open question wording 2026-07-11 23:31:41 +02:00
SJCoetz
191668088c docs(collection-map): spec — drop filter console + collapse pin taxonomy
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.
2026-07-11 23:31:17 +02:00
SJCoetz
cdaa2e2b25 fix, feat, style: standardize quote numbers, polish UI
- Standardize quote number format from Q-YYYY-MM-NNN to QYYYYMMNNN across all client, server, test and API code
- Add atomic backfill logic for quote counters to avoid sequence collisions with existing records
- Rearrange Delivery Notes and Repairs to the Operations sidebar section
- Add supplier count badge to pricelist catalogue and improve filter tab overflow styling
- Optimize font loading in root layout to skip preloading unused font weights
- Improve table styling for customer and company pages with better text wrapping and empty states
- Fix rep display logic in quotes page to show "Unassigned" when no rep is assigned
- Add supporting documentation, PocketBase counter schemas and setup migration scripts
- Remove embedded SupplierMap from suppliers page for cleaner layout
- Improve invoice card layout for company and customer info spacing
- Improve filter label styling and accessibility in collection map page
2026-07-10 22:21:50 +02:00
SJCoetz
47b01bddfa feat: add picking slips, bulk print tracking, supplier map
- 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
2026-07-10 10:47:11 +02:00
SJCoetz
6598c86093 Add order color stripe implementation plan 2026-07-10 02:03:57 +02:00
SJCoetz
0d508095f0 Add order color stripe spec 2026-07-10 02:03:16 +02:00
SJCoetz
d4b3f7c041 Add collection confirm rewrite implementation plan 2026-07-10 01:00:08 +02:00
SJCoetz
683b6c8d0a Add collection confirm rewrite spec 2026-07-10 00:59:26 +02:00
SJCoetz
728bab1671 Add collection map date filter and unassign spec 2026-07-10 00:47:42 +02:00
SJCoetz
f15fb5b49f Add collection map date filter and unassign implementation plan 2026-07-10 00:47:11 +02:00
SJCoetz
72b2ec09e2 test(collection-pool): simplify operational sort test + correct spec reasoning 2026-07-10 00:38:31 +02:00
SJCoetz
7a7ad71ac0 Add collection pool nearby sort implementation plan 2026-07-10 00:34:50 +02:00
SJCoetz
8d742e5e87 Add collection pool nearby sort spec 2026-07-10 00:30:14 +02:00
SJCoetz
4e0d45198b Add collection pool mark-ready notes implementation plan 2026-07-10 00:02:43 +02:00
SJCoetz
dbbb3e2b2c Add collection pool mark-ready notes spec 2026-07-10 00:00:40 +02:00
SJCoetz
3a1467fc91 Add PO additional attachments implementation plan 2026-07-09 23:00:18 +02:00
SJCoetz
e19bb7dbf7 Add PO additional attachments spec 2026-07-09 22:55:16 +02:00
SJCoetz
169c1d82c5 Add PO PDF token-vs-filename implementation plan 2026-07-09 22:15:22 +02:00
SJCoetz
538986d7db Add PO PDF token-vs-filename spec 2026-07-09 22:13:53 +02:00
SJCoetz
87a59fc579 Add customer-search disambiguation implementation plan 2026-07-09 21:33:07 +02:00
SJCoetz
1a3ce560c6 Add customer search company-disambiguation spec 2026-07-09 21:31:45 +02:00
SJCoetz
1992b0f4af Add new quote form redesign spec 2026-07-09 17:53:44 +02:00
SJCoetz
18334721cb feat(invoicing): add QuickBooks invoicing flow and print functionality
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
2026-07-09 09:44:55 +02:00
SJCoetz
9378685164 feat(collection-confirm): add full collection confirm workflow
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
2026-07-08 01:35:00 +02:00
SJCoetz
5f1838051f feat(collection-pool): add nearby supplier cluster sort mode
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
2026-07-07 21:56:29 +02:00
SJCoetz
b9828def38 feat(collection-pool): add unified redesigned collection pool view
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
2026-07-07 20:49:31 +02:00
SJCoetz
05abe499b0 feat(sprint): add new sprint pricing workflow and supporting code
Add full sprint pricing workflow and supporting infrastructure:
- New sidebar navigation entry for the sprint dashboard
- PocketBase category collection schema and migration script
- Server API routes for sprint item claims, attachments, counts, and file proxying
- Dev identity utilities and UI switcher for multi-user testing
- Reusable FilterTabs component replacing ItemStatusTabs
- Updated TypeScript types for sprint-related entities

Also include:
- Fix PocketBase file URL method casing (getUrl → getURL) across codebase
- Add development utility, smoke test, and helper scripts
- Update package.json with new sprint migration command
2026-07-03 07:29:43 +02:00
SJCoetz
9cdcb3b096 feat: implement sku-based catalogue pricing matching workflow
This commit adds the full end-to-end SKU pricing match flow for quote items:
- Add new QuoteItem and PriceListRow fields for SKU and pricing metadata
- Add sku_normalised to price_list for robust format-agnostic SKU matching
- Refactor price list search to use modular search builder and filter helpers
- Add database migrations, backfill scripts, and new package commands
- Update catalogue search UI and fix quote list accidental click behavior
- Add comprehensive unit, smoke, and end-to-end test suites
- Update documentation for the new price search and extraction logic
2026-06-30 21:20:53 +02:00
SJCoetz
1fb67efaee feat(pricelist): Catalogue search hits every field (incl. synonyms)
The Catalogue tab's search box used to OR across just sku,
description, and brand. Now it hits:

  - sku, description, brand, supplier, category, subcategory
    (PB's case-insensitive `~` operator, each indexed)
  - search_text (a denormalised text blob)

The denormalised column is the key part: PB can't substring-
match a JSON field, so without this, synonyms from
`specifications.synonyms` ("slugger cutter", "turbo tough",
etc.) would never match in the search box. The n8n workflow's
Code node now flattens every searchable bit — including the
synonyms array — into search_text on every POST. The 46 pre-
existing rows were backfilled once with the same formula.

The `price_list.supplier` field also stored the PB id on the
46 pre-existing rows (n8n was setting the resolved name, but
the original LLM tests that seeded the table didn't). Fixed
that in the same backfill — supplier now reads 'JEISA -
WESTSCOTT GROUP' instead of 'q6hpwbxsicyoiuu', which makes
the supplier filter dropdown work AND makes
'supplier ~ "jeisa"' match.

Migration `2026-06-30-add-price-list-search-text`:
  - Adds `search_text` (text) column
  - Adds `idx_pl_search_text` non-unique index
  - Idempotent — re-runs are safe and self-heal the index

Updates:
  - `getPriceLists` helper ORs across all 6 columns + search_text
  - `PriceList` TS type gains `search_text: string`
  - `pricelist-extraction.md` Code node snippet shows how the
    n8n workflow should populate `search_text` on every POST
  - Search input placeholder reads 'Search anything — SKU,
    description, brand, supplier, synonyms…'

Tests: 229/230 (same pre-existing failure, unrelated).
TypeScript clean.
2026-06-30 12:10:27 +02:00
SJCoetz
81c9f64158 feat(pricelist): notes field for AI instructions + file_name on upload
Operators can now type per-upload instructions for the AI extraction
step in the Pricelist upload form. The notes go into a new
`raw_price_list.notes` field that the n8n workflow reads and
injects into the LLM user message as per-upload context.

Common uses:
  - "Brand is JEI" → AI stamps every item with brand="JEI"
  - "Apply 30% markup" → Code node regexes this out for selling_price
  - "All prices in ZAR excl. VAT" → AI uses ZAR
  - "Page 4 has discount codes" → AI skips those rows

Also auto-populates `raw_price_list.file_name` (the original
browser-side filename) on upload — PB slugifies the upload to a
token stored inside supplier_file, so without this field the
operator saw the slugged version. Existing rows backfilled by the
admin script.

The `log_summary` field is now reserved for the AI's write-back
summary (set by the n8n workflow after extraction). It was
previously operator-editable on the form, which was wrong —
overwriting it clobbered the AI's output.

New migration: scripts/migrations/2026-06-30-add-pricelist-notes.ts
(idempotent, only adds `notes` if missing — `file_name` was
added manually via the PB admin UI before this commit).

doc/pricelist-extraction.md updated with the n8n LLM user message
shape, the markup regex, and the notes field's role in the pipeline.
2026-06-30 11:09:27 +02:00
SJCoetz
7f70258037 feat(management): new Pricelist page with drag-drop upload + queue table
Adds /pricelist under the Management section. Operators drag a supplier
price-list file (PDF / CSV / text / image) into the upload zone — or
use the explicit Choose file button — and it lands in PocketBase as an
attachment on the raw_price_list collection. The table below shows the
queue: file, supplier (relation to suppliers), status badge, log
summary preview, upload date, and a delete action per row.

Layout matches the rest of the app: Card for the upload zone, DataTable
for the queue, DeleteDialog for the destructive action. Live updates
via the PB subscribe channel so other tabs / the n8n ingest workflow
show new rows without a manual refresh.

PB schema is sourced from docs/pocketbase/raw_price_list.collection.json.
The migration script is idempotent: it creates the collection from the
schema file on a fresh deploy, and on a pre-existing one (the live PB
already had it, with PB's default null/superuser-only rules) it relaxes
the auth rules to @request.auth.id != '' so any logged-in user can
CRUD — matching every other collection in the app.

Field names match the live PB collection (discovered via admin API):
  - supplier_file (the file)
  - supplier_name (relation to suppliers)
  - status        (select: Pending / Processing / Completed / Failed)
  - log_summary   (free text)
2026-06-30 09:14:36 +02:00
SJCoetz
6c07a91693 refactor: drop order-level status, shift to item-driven workflow
This commit overhauls the order management system to use item-level status tracking instead of a single order-level status:
- Remove deprecated `orders.status` field and add `invoiced` and quote match audit fields
- Add `isOrderComplete` utility with tests to validate fully delivered orders
- Add purchase order PDF rendering support and tooling
- Add geo coordinate fields for companies/customers with map link UI
- Add REST management APIs for customers, companies, and suppliers
- Update customer/company services to use relation fields instead of free text
- Add status pill and tab filter components for item status visualization
- Add quote-to-order matching logic and unit tests
- Update all pages, components, and tests to match the new schema
- Include all required PocketBase migrations and schema updates
2026-06-29 13:06:01 +02:00
SJCoetz
bb4233a9f2 feat(dashboard): add multi-theme system and supporting improvements
Add complete multi-theme dashboard system including:
- 8 selectable themes with persistent per-browser preferences
- Theme bootstrap script to prevent FOUC on page load
- 12+ reusable chart components (area, bar, donut, radial gauge, etc)
- Custom checkbox UI component
- New settings page for appearance customization

Other changes:
- Optimize supplier map API payload with getMappableSuppliers helper
- Add aria-label attributes to back buttons on detail pages for better accessibility
- Update next.config.ts to include new local development IP 192.168.1.128
- Update site manifest with all new favicon and PWA assets
- Fix styling and layout spacing in rewrite quote modal
2026-06-26 17:59:40 +02:00
SJCoetz
588e9762c2 feat: add quote templates, improved email, new statuses
Add complete quote template functionality, enhanced outbound email sending, new quote statuses, and supporting infrastructure:
- Add new quote statuses (template, sending, mail_failed) with tailored UI styling for status pills
- Implement full template workflows: save real quotes as templates, create new quotes from existing templates
- Add support for custom quote dates and extended validity periods on generated PDF documents
- Build out improved email pipeline with persisted compose fields and retry functionality for failed sends
- Add attachment direction tracking to categorize inbound, outbound, and generated quote attachments
- Fix tooltip component to properly handle Radix `asChild` prop to avoid React DOM attribute errors
- Add comprehensive test coverage, schema migrations, and update sample test and production data
2026-06-24 22:57:01 +02:00
SJCoetz
714e910949 feat: add branded quote PDF generation and in-app viewer
This commit adds full quote PDF generation functionality with per-company letterhead branding:
- Server-side PDF rendering using @react-pdf/renderer matching the sample quote layout
- In-app modal PDF viewer with print, download, and new-tab controls
- Letterhead service to fetch and apply company-specific branding (CNL/ISHERWOOD)
- ZAR currency and date formatting utilities for South African quotes
- Updated QuoteAttachment type to handle PocketBase's array-based file tokens
- Fixed PocketBase attachment URL generation in quote email card
- Removed deprecated `included_in_quote` field from QuoteItem and quotes service
- Updated quote item creation test to validate draft item logic
- Added comprehensive unit tests for PDF rendering and formatting helpers
- Added dev scripts for debugging PDF and image rendering issues
- Added sample generated PDF files for visual verification
- Updated tsconfig to exclude development scripts directory
- Added @react-pdf/renderer production dependency
- Removed JEI as a valid letterhead option per requirements
2026-06-23 08:30:38 +02:00
SJCoetz
a18ab0f19f feat: add quote email tracking, user color coding, and improved attachments
Add comprehensive quote management and UI improvements:
- Add `email_received_at` field to quotes collection, TypeScript types, and setup script
- Update quote attachments schema to mark `kind` optional for legacy attachments, add `uploaded_at` field, and improve documentation comments
- Create `/api/v1/users/lookup` server endpoint to resolve user IDs to display names
- Add stable user ID → color mapping for visual grouping of claimed quotes
- Enhance quotes list page: reorder tab filters, show claimer names, color-code rows per claimant
- Update quote detail page to display claimer info with user icon
- Expand DataTable component to support per-row custom class and style props
- Overhaul QuoteEmailCard: add proper HTML/plain text body sanitization/linkification, inline PDF/image previews, improved metadata display, and fixed auth-aware attachment previews via blob URLs
2026-06-22 15:15:00 +02:00
SJCoetz
33591959c2 feat: add quote email intake and atomic numbering
This commit implements the full inbound quote email processing workflow and atomic quote numbering:
- Add PocketBase collections for monthly atomic quote counters, email attachments, and threaded replies
- Add idempotent migration script to set up new collections and add deduplication field to existing quotes table
- Implement `/api/v1/quotes/next-number` endpoint for properly formatted Q-YYYY-MM-NNN quote numbers
- Add MCP tools for idempotent quote creation, reply threading, and message ID lookup
- Add end-to-end and concurrent smoke tests for pipeline validation
- Update TypeScript types for new quote-related entities
- Update project documentation and package.json scripts
- Mark quote email intake as complete in the parity backlog
- Add n8n v2 workflows for automated email monitoring and error alerts
2026-06-22 13:58:24 +02:00
SJCoetz
41b5fc4cbf feat(quotes): add email-to-quote pipeline with attachments and replies 2026-06-16 20:46:28 +02:00
SJCoetz
c4e1c62882 chore: standardize line endings and add full test + config scaffolding
Fix inconsistent line endings across all project files for cross-environment consistency.
Add complete unit test suite covering core utilities, API routes, and server services.
Add Playwright E2E test setup with smoke, auth, and agent API tests.
Update all project configuration files to match standardized formatting.
Fix MCP API error handling to properly propagate HTTP status codes and use correct JSON-RPC error codes.
Add VSCode workspace configuration, extensions, and example MCP config files.
Update .gitignore to exclude new test and build artifacts.
2026-06-11 20:30:02 +02:00
SJCoetz
fd1571e294 Add PocketBase collections, APIs & migration docs
Introduce PocketBase workflow support, migration tooling, server APIs and documentation. Adds a set of PocketBase collection JSONs (order_items, order_items_v2, collection_pool, delivery_notes, delivery_note_items, repairs) and a large import manifest for workflow collections; includes docs describing MCP/API layer, migration audit, order-item schema and rollout plans. Adds server-side agent/MCP endpoints and services (api/mcp, api/v1/orders, collection-pool, order-items status, health) plus helper modules (pocketbase-admin, orders-service, order-item-status, agent-auth) and a migration script to create order_items_v2/collection_pool. UI: new pages for collection-pool, delivery-notes, repairs and several updates to orders/quotes pages, sidebar, tooltip and pb helpers/types. Also updates package.json (migration script and related changes) and global styles. Required env vars and suggested migration command are documented (e.g. NEXT_PUBLIC_POCKETBASE_URL, PB_ADMIN_EMAIL, PB_ADMIN_PASSWORD, ORDER_ITEMS_COLLECTION; run npm run pb:migrate:orders-v2).
2026-05-25 18:39:33 +02:00