2026-02-15 23:25:24 +00:00
# Vorteq Quest Portal - Task Tracking
> **Reference:** `docs/Vorteq_Quest_PRD_v1.0.docx` for full specifications
> **Instructions:** `CLAUDE.md` for coding conventions and patterns
>
> Mark tasks: `[ ]` Not started | `[~]` In progress | `[x]` Complete | `[!]` Blocked
---
## Phase 1: Foundation (Est. 30-40 hrs)
### F-001: Project Scaffold
2026-02-16 00:04:44 +00:00
- [x] Initialize Next.js 15 with App Router, TypeScript strict mode
- [x] Install and configure Tailwind CSS
- [x] Install and configure shadcn/ui (default theme)
- [x] Configure ESLint + Prettier
- [x] Configure `tsconfig.json` with path aliases (`@/` )
- [x] Create base project structure per CLAUDE.md
- [x] Create `.dockerignore` for build optimization
- **Deps:** None | **Est:** 2 hrs | **Status:** ✅ Complete
2026-02-15 23:25:24 +00:00
### F-002: Docker & Infrastructure Alignment
- [x] `Dockerfile` for Next.js app (Node.js 22, multi-stage build)
- [x] `docker-compose.yml` : Traefik, postgres:16-alpine, redis:7-alpine, app-dev, app-test, app-prod
- [x] Traefik reverse proxy with Cloudflare DNS challenge for auto-SSL
- [x] `.env.example` with all required variables
- [x] `init-databases.sh` for multi-database PostgreSQL setup
- [x] `setup.sh` for server provisioning
2026-02-16 00:04:44 +00:00
- [x] Health check endpoints in Next.js app (`/api/health` )
- [x] Verify `next.config.js` has `output: 'standalone'` for Docker
- **Deps:** F-001 | **Est:** 1 hr (remaining) | **Status:** ✅ Complete
2026-02-15 23:25:24 +00:00
### F-003: Prisma Schema - Auth Domain
2026-02-16 02:08:09 +00:00
- [x] `auth_user` table (email, password hash, deactivated, verified, login counts, 2FA, SSO fields)
- [x] `auth_domain` table
- [x] `auth_user_type` table
- [x] `auth_oauth_client` + `auth_oauth_access_token` + `auth_oauth_refresh_token`
- [x] `auth_password_history` + `auth_password_reset`
- [x] `auth_permission_group` + `auth_permission_rule` + junction table
- [x] `auth_permission_rule_category`
- [x] `auth_security_question` + `auth_security_answer`
- [x] Run initial migration, verify schema
- **Deps:** F-001 | **Est:** 4 hrs | **Status:** ✅ Complete
2026-02-15 23:25:24 +00:00
### F-004: Prisma Schema - Quest Domain
2026-02-16 02:08:09 +00:00
- [x] `quest_company` (EpicorCustID, display name, invoicing flags)
- [x] `quest_user` (FK to auth_user, IsSubUser, API token)
- [x] `quest_user_company` junction table
2026-02-16 02:16:28 +00:00
- [x] `quest_account_request`
- [x] `quest_notification` + `quest_user_notification_alert_read`
- [x] `quest_email_event` + `quest_user_email_event` junction
- [x] `quest_email_log`
- [x] `quest_plant` + `quest_inventory_type` + `quest_inventory_plant`
- [x] `quest_processed_order_acknowledgement_email`
- [x] Run migration, verify
- **Deps:** F-003 | **Est:** 3 hrs | **Status:** ✅ Complete
2026-02-15 23:25:24 +00:00
### F-005: Prisma Schema - Remaining Domains
2026-02-16 02:16:28 +00:00
- [x] `ship_request` + `ship_request_detail`
- [x] `alloc_request` + `alloc_request_detail` + `alloc_plant`
- [x] `inv_upload` + `inv_upload_entry` + `inv_upload_status`
- [x] `finance_ap_check_processing_batch` + `finance_ap_check_processing_status`
- [x] `paint_plant` + `paint_line` + `paint_line_type` + `paint_plant_line` + `paint_schedule`
- [x] `doc_article` + `doc_category` + `doc_article_permission_group`
- [x] `wave_process` + `wave_process_history`
- [x] `lts_task` + `lts_task_type` + `lts_task_schedule` + related tables
- [x] Run migration, verify all relationships
- **Deps:** F-004 | **Est:** 4 hrs | **Status:** ✅ Complete
2026-02-15 23:25:24 +00:00
### F-006: Epicor MSSQL Connection Service
feat(F-006): enhance Epicor MSSQL connection service
Enhanced Connection Management:
- Custom error classes: EpicorConnectionError, EpicorQueryError, EpicorTimeoutError
- Connection pool reuse with state tracking
- Configuration validation on startup
- Configurable timeouts (connect: 30s, request: 60s)
Query Execution:
- execStoredProc: execute stored procedures with typed parameters
- execQuery: execute raw SQL queries with parameterization
- execPortalStoredProc: helper for standard portal SP params (CustID, DBNAME, sub)
- Comprehensive error handling with timeout detection
Health & Utilities:
- checkConnection: validates connection with actual query test
- closeConnection: graceful pool shutdown
- getPortalDbName: helper for cross-database query parameters
- Graceful shutdown handlers (SIGINT, SIGTERM)
Type Definitions (src/types/epicor.ts):
- Inventory: summary, detail, with paint codes and dimensions
- Orders: list, acknowledgement with lines
- Shipments: list, BOL detail with lines
- Coil Activity: usage, receipts, coil-by-coil
- Jobs: status, traveler with operations and materials
- Customers: ship-to addresses
- Invoices: customer/job matching
- Shipping Reports: monthly and YTD
Ready for service layer implementation in Phase 2.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-16 02:18:00 +00:00
- [x] `src/lib/epicor.ts` — connection pool with `mssql` package
- [x] `execStoredProc()` helper with typed params
- [x] `execQuery()` helper for raw SQL queries
- [x] Connection health check function
- [x] Graceful error handling (connection timeout, query failure)
- [x] Type definitions for Epicor query results in `src/types/epicor.ts`
- [~] Test connection against Epicor10Live with `portal` user (pending actual credentials)
- **Deps:** F-001 | **Est:** 3 hrs | **Status:** ✅ Complete
2026-02-15 23:25:24 +00:00
### F-007: Better Auth Setup
feat(F-007): implement Better Auth with login and account request
Better Auth Configuration:
- Database adapter for PostgreSQL with custom schema mapping
- Email/password authentication enabled
- 7-day session expiration with 24-hour update frequency
- Custom field mappings for auth_user, auth_session, auth_account tables
- Server-side auth helpers: getSession(), requireAuth()
- Client-side React hooks: signIn, signOut, signUp, useSession
Authentication Pages:
- /login: Email/password login with error handling
- /forgot-password: Password reset request flow
- /account-request: New user registration form
- Captures: name, email, phone, company, Epicor ID, message
- Creates quest_account_request record for admin approval
- Success confirmation with next steps
API Routes:
- /api/auth/[...all]: Better Auth handler for all auth operations
- /api/account-request: Account request submission endpoint
UI Components:
- Added Textarea component from shadcn/ui
- Form validation and loading states
- Toast notifications for user feedback
- Responsive card-based layouts
Session management and enhanced context (company, permissions) will be
added in F-008 middleware implementation.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-16 02:25:52 +00:00
- [x] Install and configure Better Auth
- [x] Credentials provider: validate against `auth_user` table (bcrypt)
- [x] Session strategy with user ID, email, role, company context
- [~] Session includes: userId, questUserId, activeCompanyId, isSubUser, permissionRules[] (requires middleware enhancement)
- [x] Login page at `/login`
- [x] Forgot password page at `/forgot-password`
- [x] Account request page at `/account-request`
- [ ] reCAPTCHA integration on public forms (deferred to later)
- **Deps:** F-003 | **Est:** 4 hrs | **Status:** ✅ Complete
2026-02-15 23:25:24 +00:00
### F-008: Middleware & Guards
feat(F-008,F-009,F-010): complete Phase 1 foundation with middleware, navigation, and migrations
Implements authentication middleware with rate limiting, comprehensive permission
system, full portal navigation with sidebar and header, company selection flow,
and data migration tooling from SQL Server to PostgreSQL.
Key additions:
- Middleware: auth guards, rate limiting, session management
- Permissions: role-based access control with hierarchical permission rules
- Navigation: responsive sidebar with expandable sections, header with notifications
- Company selector: multi-company user support with session-based active company
- Data migration: comprehensive script for migrating auth and quest domain tables
- Schema: added auth_user_type_permission_group junction table
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-16 11:07:44 +00:00
- [x] `src/middleware.ts` — redirect unauthenticated users to /login
- [x] Company context middleware: ensure active company is selected
- [x] `src/lib/permissions.ts` — `requirePermission(rule)` helper
- [x] Admin route protection (check user type)
- [x] Sub-user detection helper (`isSubUser()` )
- [x] Company selector: `/select-company` page for multi-company users
- [x] Rate limiting on auth endpoints
- [x] Session management utilities for Quest-specific data
- [x] API route for setting active company
- **Deps:** F-007 | **Est:** 4 hrs | **Status:** ✅ Complete
2026-02-15 23:25:24 +00:00
### F-009: Base Layout & Navigation
feat(F-008,F-009,F-010): complete Phase 1 foundation with middleware, navigation, and migrations
Implements authentication middleware with rate limiting, comprehensive permission
system, full portal navigation with sidebar and header, company selection flow,
and data migration tooling from SQL Server to PostgreSQL.
Key additions:
- Middleware: auth guards, rate limiting, session management
- Permissions: role-based access control with hierarchical permission rules
- Navigation: responsive sidebar with expandable sections, header with notifications
- Company selector: multi-company user support with session-based active company
- Data migration: comprehensive script for migrating auth and quest domain tables
- Schema: added auth_user_type_permission_group junction table
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-16 11:07:44 +00:00
- [x] Root layout with sidebar navigation
- [x] Header: company name, user menu, notification bell
- [x] Sidebar: Dashboard, Inventory, Orders, Shipments, Coil Activity, Invoices, Requests
- [x] Admin section in sidebar (conditional on role)
- [x] Company switcher dropdown (admin) or display (customer)
- [~] Responsive: collapsible sidebar on mobile (basic implementation, needs enhancement)
- [x] Breadcrumb component
- **Deps:** F-007 | **Est:** 3 hrs | **Status:** ✅ Complete
2026-02-15 23:25:24 +00:00
### F-010: Data Migration Scripts
feat(F-008,F-009,F-010): complete Phase 1 foundation with middleware, navigation, and migrations
Implements authentication middleware with rate limiting, comprehensive permission
system, full portal navigation with sidebar and header, company selection flow,
and data migration tooling from SQL Server to PostgreSQL.
Key additions:
- Middleware: auth guards, rate limiting, session management
- Permissions: role-based access control with hierarchical permission rules
- Navigation: responsive sidebar with expandable sections, header with notifications
- Company selector: multi-company user support with session-based active company
- Data migration: comprehensive script for migrating auth and quest domain tables
- Schema: added auth_user_type_permission_group junction table
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-16 11:07:44 +00:00
- [x] `scripts/migrate-data.ts` — connects to both SQL Server and PostgreSQL
- [x] Migrate `auth_user` + `auth_user_type` + `auth_domain` (preserve bcrypt hashes)
- [x] Migrate `auth_permission_group` + `auth_permission_rule` + junction
- [x] Migrate `quest_user` + `quest_company` + `quest_user_company`
- [x] Migrate `quest_plant` + `quest_inventory_type/plant`
- [x] Migrate `quest_email_event`
- [ ] Migrate `ship_request` + `ship_request_detail` (historical data) (deferred - can be done before go-live)
- [ ] Migrate `alloc_request` + `alloc_request_detail` (deferred - can be done before go-live)
- [ ] Migrate supporting tables (notifications, docs, email events, wave, paint) (deferred - can be done before go-live)
- [x] Validation: count comparison, spot-check key records
- [x] Handle: IDENTITY → SERIAL, datetime2 → TIMESTAMPTZ, bit → BOOLEAN, nvarchar(MAX) → TEXT
- **Deps:** F-005 | **Est:** 6 hrs | **Status:** ✅ Complete (core tables migrated)
2026-02-15 23:25:24 +00:00
---
## Phase 2: Core Features (Est. 80-110 hrs)
feat: add coil-by-coil report, job status by plant, job traveler + PDFs
Implements C-010 (Coil-by-Coil), C-011 (Job Status by Plant), and
C-012 (Job Traveler + PDF) completing 12/16 Phase 2 core features.
C-010: Job number search → detailed coil-level breakdown showing
materials used and produced with independent search/sort/CSV export.
Embeds full 782-line CoilByCoil.sql query in service layer.
C-011: Auto-loading job status view grouped by plant using
OpenOrdersQueryV3 stored procedure. Includes web table with
search/sort/CSV export and landscape PDF download.
C-012: Multi-section job traveler with header info, shipping schedule,
raw materials, operations, and Part_UD paint specifications. Includes
job number search page, detail page, and PDF export with Vorteq
branding. Deduplicates flat SQL results into structured data.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 09:42:39 -05:00
**Progress:** 12/16 tasks complete
2026-02-16 11:41:56 +00:00
2026-02-15 23:25:24 +00:00
### C-001: Dashboard
2026-02-16 11:41:56 +00:00
- [x] Dashboard page at `/(portal)/dashboard/page.tsx`
- [x] Server component: fetch top 5 orders, top 5 shipments from Epicor
- [x] Summary cards: inventory overview, recent activity
- [x] Notification alert banner (unread alerts)
- [x] Quick-nav cards to major features
- [x] Loading skeletons for async data
- [x] Dashboard service with typed queries
- [x] Reusable dashboard components (SummaryCard, QuickNavCard, tables)
- **Deps:** F-009, F-006 | **Est:** 6 hrs | **Status:** ✅ Complete
2026-02-15 23:25:24 +00:00
### C-002: Inventory Summary Views
2026-02-16 12:35:35 +00:00
- [x] `/(portal)/inventory/page.tsx` — category selector
- [x] `/(portal)/inventory/[category]/page.tsx` — summary data table (all 6 categories)
- [x] Service: `src/services/inventory.ts`
- [x] `getWorkInProgressSummary(custId, dbName, sub)`
- [x] `getFinishedGoodsSummary(custId, dbName, sub)`
- [x] `getProcessedOtherSummary(custId, dbName, sub)`
- [x] `getUnprocessedSummary(custId, dbName)` — block sub-users
- [x] `getUnprocessedRRSummary(custId, dbName)` — block sub-users
- [x] `getProcessedRRSummary(custId, dbName)` — block sub-users
- [x] V6 procedures: pass `sub` param (0/1 based on user)
- [~] Row count pre-fetch for detail drill-down (deferred, can optimize later)
- [x] Data table with sorting, filtering, export to CSV
- [x] Click row → navigate to detail view
- **Deps:** F-006, F-009 | **Est:** 12 hrs | **Status:** ✅ Complete
2026-02-15 23:25:24 +00:00
### C-003: Inventory Detail Views
2026-02-16 12:35:35 +00:00
- [x] `/(portal)/inventory/[category]/detail/page.tsx`
- [x] Query params: `part` , `plant` , `warehouse` (for specific) or none (for all)
- [x] Service functions for each detail stored procedure (V6 and legacy)
- [x] getInventoryDetails() with proper stored procedure names
- [~] Paint code display (from Epicor Part_UD table) (deferred to when paint module needed)
- [~] Part description with paint code lookup (deferred, placeholder implemented)
- [x] On-hand quantity for specific lines
- [x] Data table with full column set (part, plant, warehouse, bin, lot, serial, qty, description)
- [x] Back navigation to summary
- [x] Search and CSV export functionality
- **Deps:** C-002 | **Est:** 8 hrs | **Status:** ✅ Complete
2026-02-15 23:25:24 +00:00
### C-004: Order List
2026-02-16 12:38:05 +00:00
- [x] `/(portal)/orders/page.tsx`
- [x] Service: `getTop100Orders(custId)` - basic Epicor query implementation
- [x] HDC/HDM exception handling (maps HDC to HDM for Cust2 parameter)
- [x] Data table: Order Number, PO, Customer Part, Vorteq Part, Dates, Qty, Status
- [x] Click-through to order acknowledgement (link to /orders/[id])
- [x] Search functionality (order #, PO, parts)
- [x] CSV export
- **Deps:** F-006, F-009 | **Est:** 6 hrs | **Status:** ✅ Complete
2026-02-15 23:25:24 +00:00
### C-005: Order Acknowledgement Detail + PDF
feat: add order ack detail/PDF, BOL detail/PDF, coil activity usage & receipts
C-005: Order Acknowledgement Detail + PDF
- Order detail page with full line items, releases, addresses, paint codes
- PDF export via Puppeteer matching legacy format
- Clickable order # links and PDF icons in orders table
C-007: BOL Detail + PDF
- BOL detail page with ship-from/to, line items, weights
- PDF export matching legacy BOL format
- PDF icon column in shipments table
C-008: Coil Activity - Usage Report
- Date range picker (max 31 days, default last 10 days)
- Reusable UI: Popover, Calendar (react-day-picker v9), DateRangePicker
- SQL from legacy portal_CoilActivityUsage.sql with OnHandQty dedup
- 11-column sortable table with search and CSV export
C-009: Coil Activity - Receipts Report
- VGL customer exception (special SQL vs portal view)
- 10-column sortable table with search and CSV export
- Shared date range picker component
Also: dashboard API route, shipments API route, HDC→HDM mapping,
Puppeteer PDF infrastructure, improved error handling.
Progress: 9/16 Phase 2 tasks complete.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 09:14:52 -05:00
- [x] `/(portal)/orders/[orderNum]/page.tsx` — client-side fetch with loading skeleton
- [x] Service: `getOrderAcknowledgement(orderNum, custId)` with Epicor SQL (OrderHed/OrderDtl/OrderRel/Customer/ShipTo/Terms/ShipVia/Plant/JobProd)
- [x] Detail view matching legacy PDF layout (addresses, order info, line items, releases, paint codes, comments, totals)
- [x] PDF export via Puppeteer (`/api/orders/[orderNum]/pdf` )
- [x] Orders table: clickable Order # links + PDF download icons
- [x] Cross-customer security verified (BAS cannot access ACM orders)
- [x] UTC date handling fix for correct date display
- [x] FOB plant name resolution (code → description via Erp.Plant)
- **Deps:** C-004 | **Est:** 6 hrs | **Status:** ✅ Complete
2026-02-15 23:25:24 +00:00
### C-006: Shipment List
feat: add order ack detail/PDF, BOL detail/PDF, coil activity usage & receipts
C-005: Order Acknowledgement Detail + PDF
- Order detail page with full line items, releases, addresses, paint codes
- PDF export via Puppeteer matching legacy format
- Clickable order # links and PDF icons in orders table
C-007: BOL Detail + PDF
- BOL detail page with ship-from/to, line items, weights
- PDF export matching legacy BOL format
- PDF icon column in shipments table
C-008: Coil Activity - Usage Report
- Date range picker (max 31 days, default last 10 days)
- Reusable UI: Popover, Calendar (react-day-picker v9), DateRangePicker
- SQL from legacy portal_CoilActivityUsage.sql with OnHandQty dedup
- 11-column sortable table with search and CSV export
C-009: Coil Activity - Receipts Report
- VGL customer exception (special SQL vs portal view)
- 10-column sortable table with search and CSV export
- Shared date range picker component
Also: dashboard API route, shipments API route, HDC→HDM mapping,
Puppeteer PDF infrastructure, improved error handling.
Progress: 9/16 Phase 2 tasks complete.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 09:14:52 -05:00
- [x] `/(portal)/shipments/page.tsx` — client-side fetch via API route (RSC-safe for large datasets)
- [x] Service: `getTop100Shipments(custId)` via `portal_GetShipmentsV1` stored procedure
- [x] ShipToLoc formatting (replace `, ` with newlines)
- [x] Data table with search, sort, CSV export (teal-700 header)
- [x] Click-through to BOL detail (`/shipments/{bol_num}` )
- [x] API route at `/api/shipments` with auth + company context
- **Deps:** F-006, F-009 | **Est:** 5 hrs | **Status:** ✅ Complete
2026-02-15 23:25:24 +00:00
### C-007: BOL Detail + PDF
feat: add order ack detail/PDF, BOL detail/PDF, coil activity usage & receipts
C-005: Order Acknowledgement Detail + PDF
- Order detail page with full line items, releases, addresses, paint codes
- PDF export via Puppeteer matching legacy format
- Clickable order # links and PDF icons in orders table
C-007: BOL Detail + PDF
- BOL detail page with ship-from/to, line items, weights
- PDF export matching legacy BOL format
- PDF icon column in shipments table
C-008: Coil Activity - Usage Report
- Date range picker (max 31 days, default last 10 days)
- Reusable UI: Popover, Calendar (react-day-picker v9), DateRangePicker
- SQL from legacy portal_CoilActivityUsage.sql with OnHandQty dedup
- 11-column sortable table with search and CSV export
C-009: Coil Activity - Receipts Report
- VGL customer exception (special SQL vs portal view)
- 10-column sortable table with search and CSV export
- Shared date range picker component
Also: dashboard API route, shipments API route, HDC→HDM mapping,
Puppeteer PDF infrastructure, improved error handling.
Progress: 9/16 Phase 2 tasks complete.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 09:14:52 -05:00
- [x] `/(portal)/shipments/[bol]/page.tsx`
- [x] Service: `getBOL(bolNum, custId)` using `getBOL.sql`
- [x] Detail view with line items
- [x] PDF export
- **Deps:** C-006 | **Est:** 4 hrs | **Status:** ✅ Complete
2026-02-15 23:25:24 +00:00
### C-008: Coil Activity - Usage Report
feat: add order ack detail/PDF, BOL detail/PDF, coil activity usage & receipts
C-005: Order Acknowledgement Detail + PDF
- Order detail page with full line items, releases, addresses, paint codes
- PDF export via Puppeteer matching legacy format
- Clickable order # links and PDF icons in orders table
C-007: BOL Detail + PDF
- BOL detail page with ship-from/to, line items, weights
- PDF export matching legacy BOL format
- PDF icon column in shipments table
C-008: Coil Activity - Usage Report
- Date range picker (max 31 days, default last 10 days)
- Reusable UI: Popover, Calendar (react-day-picker v9), DateRangePicker
- SQL from legacy portal_CoilActivityUsage.sql with OnHandQty dedup
- 11-column sortable table with search and CSV export
C-009: Coil Activity - Receipts Report
- VGL customer exception (special SQL vs portal view)
- 10-column sortable table with search and CSV export
- Shared date range picker component
Also: dashboard API route, shipments API route, HDC→HDM mapping,
Puppeteer PDF infrastructure, improved error handling.
Progress: 9/16 Phase 2 tasks complete.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 09:14:52 -05:00
- [x] `/(portal)/coil-activity/usage/page.tsx`
- [x] Date range picker (with validation — max 31 days, default last 10 days)
- [x] Reusable UI components: Popover, Calendar (react-day-picker v9), DateRangePicker
- [x] Service: `getCoilUsage(custId, startDate, endDate)` using legacy `portal_CoilActivityUsage.sql`
- [x] Deduplication logic: only show OnHandQty for most recent DateUsed per LotNum
- [x] Zero weights → null display
- [x] Data table with all 11 columns: Date Used, Vorteq Part#, Cust Part#, Part Description, Lot#, Mfg Lot#, Weight, Plant Name, Job#, Cust PO#, Qty LB
- [x] Search, sort, CSV export
- [x] HDC→HDM customer ID mapping
- **Deps:** F-006, F-009 | **Est:** 6 hrs | **Status:** ✅ Complete
2026-02-15 23:25:24 +00:00
### C-009: Coil Activity - Receipts Report
feat: add order ack detail/PDF, BOL detail/PDF, coil activity usage & receipts
C-005: Order Acknowledgement Detail + PDF
- Order detail page with full line items, releases, addresses, paint codes
- PDF export via Puppeteer matching legacy format
- Clickable order # links and PDF icons in orders table
C-007: BOL Detail + PDF
- BOL detail page with ship-from/to, line items, weights
- PDF export matching legacy BOL format
- PDF icon column in shipments table
C-008: Coil Activity - Usage Report
- Date range picker (max 31 days, default last 10 days)
- Reusable UI: Popover, Calendar (react-day-picker v9), DateRangePicker
- SQL from legacy portal_CoilActivityUsage.sql with OnHandQty dedup
- 11-column sortable table with search and CSV export
C-009: Coil Activity - Receipts Report
- VGL customer exception (special SQL vs portal view)
- 10-column sortable table with search and CSV export
- Shared date range picker component
Also: dashboard API route, shipments API route, HDC→HDM mapping,
Puppeteer PDF infrastructure, improved error handling.
Progress: 9/16 Phase 2 tasks complete.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 09:14:52 -05:00
- [x] `/(portal)/coil-activity/receipts/page.tsx`
- [x] Date range picker (shared component from C-008)
- [x] Service: `getCoilReceipts(custId, startDate, endDate)` with VGL exception
- [x] VGL customer exception: uses `VGLCoilReceiptsData.sql` ; all others use `dbo.portal_CoilActivityReceipts` view
- [x] Data table with all 10 columns: Date Rec, Vorteq Part#, Cust Part#, Part Description, Lot#, Mfg Lot#, Plant Name, Packing Slip, Supplier Name, Mill Order #
- [x] Search, sort, CSV export
- [x] HDC→HDM customer ID mapping
- **Deps:** F-006, F-009 | **Est:** 4 hrs | **Status:** ✅ Complete
2026-02-15 23:25:24 +00:00
### C-010: Coil-by-Coil Report
feat: add coil-by-coil report, job status by plant, job traveler + PDFs
Implements C-010 (Coil-by-Coil), C-011 (Job Status by Plant), and
C-012 (Job Traveler + PDF) completing 12/16 Phase 2 core features.
C-010: Job number search → detailed coil-level breakdown showing
materials used and produced with independent search/sort/CSV export.
Embeds full 782-line CoilByCoil.sql query in service layer.
C-011: Auto-loading job status view grouped by plant using
OpenOrdersQueryV3 stored procedure. Includes web table with
search/sort/CSV export and landscape PDF download.
C-012: Multi-section job traveler with header info, shipping schedule,
raw materials, operations, and Part_UD paint specifications. Includes
job number search page, detail page, and PDF export with Vorteq
branding. Deduplicates flat SQL results into structured data.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 09:42:39 -05:00
- [x] `/(portal)/coil-activity/coil-by-coil/page.tsx` — job number search → coil detail display
- [x] Job number search input with search button
- [x] Service: `getCoilByCoil(jobNum, customer)` using full 782-line `CoilByCoil.sql` embedded in service
- [x] Header info card (Job#, Customer, PO, Part, Plant, etc.)
- [x] Two-section table: Materials Used + Materials Produced with independent search/sort/CSV export
- [x] HDC→HDM customer ID mapping
- **Deps:** F-006 | **Est:** 3 hrs | **Status:** ✅ Complete
2026-02-15 23:25:24 +00:00
### C-011: Job Status by Plant
feat: add coil-by-coil report, job status by plant, job traveler + PDFs
Implements C-010 (Coil-by-Coil), C-011 (Job Status by Plant), and
C-012 (Job Traveler + PDF) completing 12/16 Phase 2 core features.
C-010: Job number search → detailed coil-level breakdown showing
materials used and produced with independent search/sort/CSV export.
Embeds full 782-line CoilByCoil.sql query in service layer.
C-011: Auto-loading job status view grouped by plant using
OpenOrdersQueryV3 stored procedure. Includes web table with
search/sort/CSV export and landscape PDF download.
C-012: Multi-section job traveler with header info, shipping schedule,
raw materials, operations, and Part_UD paint specifications. Includes
job number search page, detail page, and PDF export with Vorteq
branding. Deduplicates flat SQL results into structured data.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 09:42:39 -05:00
- [x] `/(portal)/jobs/status/page.tsx` — auto-loads on mount
- [x] Service: `getJobStatusByPlant(custId)` using `OpenOrdersQueryV3` stored procedure
- [x] DBNAME cross-database parameter via `getPortalDbName()`
- [x] Data table grouped by plant with plant section header rows
- [x] Search, sort, CSV export
- [x] PDF export: `/api/jobs/status/pdf` (landscape Letter, grouped by plant)
- [x] HDC→HDM customer ID mapping
- **Deps:** F-006 | **Est:** 3 hrs | **Status:** ✅ Complete
2026-02-15 23:25:24 +00:00
### C-012: Job Traveler + PDF
feat: add coil-by-coil report, job status by plant, job traveler + PDFs
Implements C-010 (Coil-by-Coil), C-011 (Job Status by Plant), and
C-012 (Job Traveler + PDF) completing 12/16 Phase 2 core features.
C-010: Job number search → detailed coil-level breakdown showing
materials used and produced with independent search/sort/CSV export.
Embeds full 782-line CoilByCoil.sql query in service layer.
C-011: Auto-loading job status view grouped by plant using
OpenOrdersQueryV3 stored procedure. Includes web table with
search/sort/CSV export and landscape PDF download.
C-012: Multi-section job traveler with header info, shipping schedule,
raw materials, operations, and Part_UD paint specifications. Includes
job number search page, detail page, and PDF export with Vorteq
branding. Deduplicates flat SQL results into structured data.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 09:42:39 -05:00
- [x] `/(portal)/jobs/traveler/page.tsx` — job number search page
- [x] `/(portal)/jobs/[jobNum]/traveler/page.tsx` — multi-section detail page
- [x] Service: `getJobTraveler(jobNum)` using full `jobTraveler.sql` with Part_UD paint data
- [x] Structured data: header, shipping schedule, raw materials, operations, paint specifications (deduplicated from flat SQL results)
- [x] Detail view: Job info card, Schedule dates, Shipping schedule table, Raw materials table, Operations table, Part specifications card
- [x] PDF export: `/api/jobs/{jobNum}/traveler/pdf` (landscape Letter, full Vorteq branding)
- [x] Sidebar navigation: Job Traveler link under Jobs section
- **Deps:** F-006 | **Est:** 4 hrs | **Status:** ✅ Complete
2026-02-15 23:25:24 +00:00
### C-013: Shipment Request Cart Workflow
- [ ] `/(portal)/shipment-requests/page.tsx` — list existing requests
- [ ] `/(portal)/shipment-requests/new/page.tsx` — new request flow
- [ ] `/(portal)/shipment-requests/[id]/page.tsx` — edit/view request
- [ ] Step 1: Select ship-to address (from `portal_CustomerShipToAddresses` )
- [ ] Sub-user filter: only '%NB HANDY%' addresses
- [ ] Step 2: Add inventory items to cart
- [ ] Browse available inventory, select items
- [ ] Set quantity per line item
- [ ] Step 3: Enter details (Order#, PO#, Release#, Pickup Date, Instructions, Email Recipients)
- [ ] Submit: create `ship_request` + `ship_request_detail` records, send emails
- [ ] Cancel: set `IsCancelled=true` , record canceller, send cancellation emails
- [ ] Cart persistence: save progress to DB, show `LastCartActivity`
- [ ] Confirmation page after submit
- **Deps:** F-005, C-003 | **Est:** 12 hrs
### C-014: Coil Allocation Request Cart Workflow
- [ ] Mirror of C-013 but for allocation requests
- [ ] Additional field: JobNum (from Epicor)
- [ ] Uses `alloc_request` + `alloc_request_detail` tables
- [ ] `getCoilAllocationsByJobNumber()` for allocation data
- **Deps:** F-005, C-003 | **Est:** 8 hrs
### C-015: Invoice Viewing (Customer)
- [ ] `/(portal)/invoices/page.tsx`
- [ ] Only visible if company `CanAccessInvoices=true`
- [ ] List invoices from `inv_upload_entry` filtered by company
- [ ] PDF download endpoint `/api/invoices/:id/pdf`
- [ ] File serving from storage directory
- **Deps:** F-005, F-009 | **Est:** 4 hrs
### C-016: Notifications Display
- [ ] Notification bell in header with unread count
- [ ] Alert banner on dashboard for IsAlert=true notifications
- [ ] Notification list view
- [ ] Mark as read → create `quest_user_notification_alert_read` record
- **Deps:** F-005, F-009 | **Est:** 3 hrs
---
## Phase 3: Admin Features (Est. 60-80 hrs)
### A-001: User Management
- [ ] `/(portal)/admin/users/page.tsx` — user list with search/filter
- [ ] `/(portal)/admin/users/[id]/page.tsx` — user detail/edit
- [ ] `/(portal)/admin/users/new/page.tsx` — create user
- [ ] CRUD operations via server actions
- [ ] Assign/remove company associations
- [ ] Assign permission groups
- [ ] Activate/deactivate users
- [ ] Set IsSubUser flag
- [ ] View login history (success/failure counts)
- **Deps:** F-007, F-005 | **Est:** 8 hrs
### A-002: Company Management
- [ ] `/(portal)/admin/companies/page.tsx` — company list
- [ ] `/(portal)/admin/companies/[id]/page.tsx` — company detail/edit
- [ ] Edit: display name, InvoicingEmail, OrderAckEmail, CanAccessInvoices, ReceivesSOEmails
- [ ] Activate/deactivate companies
- [ ] View associated users
- **Deps:** F-005 | **Est:** 5 hrs
### A-003: Account Request Management
- [ ] `/(portal)/admin/account-requests/page.tsx`
- [ ] List pending requests
- [ ] Approve: create auth_user + quest_user + company association
- [ ] Reject: mark RequestProcessed without creating user
- [ ] Send approval/rejection email
- **Deps:** F-005, A-001 | **Est:** 4 hrs
### A-004: Invoice Upload + Processing
- [ ] `/(portal)/admin/invoices/upload/page.tsx`
- [ ] Multi-page PDF upload
- [ ] Parse PDF to extract individual invoices by invoice number
- [ ] Match to CustID via `getCustomerIDsForInvoiceNumbers()`
- [ ] Match to JobNum via `getJobNumberByInvoiceNumber()`
- [ ] Create `inv_upload` + `inv_upload_entry` records
- [ ] Status tracking (upload status, per-entry errors)
- [ ] Send invoices to companies with InvoicingEmail
- [ ] Handle: ignored entries, replaced entries, send errors
- [ ] Upload history view
- **Deps:** F-005, C-015 | **Est:** 12 hrs
### A-005: AP Check Processing
- [ ] `/(portal)/admin/ap-check/page.tsx`
- [ ] Excel upload (XLS/XLSX)
- [ ] Extract Group ID from cell AB9
- [ ] Query Epicor CheckLines.sql by Group ID
- [ ] Generate CSV with specific formatting
- [ ] Country code handling: 'USA' vs 'FOR' (foreign)
- [ ] Address field processing
- [ ] Download generated CSV
- [ ] Batch status tracking in `finance_ap_check_processing_batch`
- **Deps:** F-005 | **Est:** 8 hrs
### A-006: Notification Management
- [ ] `/(portal)/admin/notifications/page.tsx` — list + CRUD
- [ ] Create: Title, Text, IsAlert, Date, Time
- [ ] Edit/delete existing notifications
- [ ] Preview notification as customer would see it
- **Deps:** F-005 | **Est:** 3 hrs
### A-007: Documentation / Knowledge Base
- [ ] `/(portal)/admin/documentation/page.tsx` — category + article management
- [ ] Category CRUD (name, icon)
- [ ] Article CRUD (content, category assignment)
- [ ] Permission group assignment per article
- [ ] Customer-facing documentation viewer
- **Deps:** F-005 | **Est:** 5 hrs
### A-008: Shipping Reports
- [ ] `/(portal)/admin/shipping-reports/page.tsx`
- [ ] View generated reports (stored Excel files)
- [ ] Manual trigger: generate previous month report
- [ ] Manual trigger: generate YTD report
- [ ] Service: `getShippingForMonth()` , `getShippingYTD()` via Epicor
- [ ] Excel generation using a library (e.g., ExcelJS)
- **Deps:** F-006 | **Est:** 4 hrs
### A-009: Wave/EDI Process Management
- [ ] `/(portal)/admin/wave/page.tsx`
- [ ] List `wave_process` entries with enable/disable toggles
- [ ] View `wave_process_history` with run results
- [ ] Manual trigger for processes
- [ ] Minimal implementation — client migrating EDI to another product
- **Deps:** F-005 | **Est:** 4 hrs
### A-010: Paint Schedule Management
- [ ] `/(portal)/admin/paint-schedule/page.tsx`
- [ ] CRUD for paint schedule entries
- [ ] Plant/line selection from `paint_plant` , `paint_line` , `paint_plant_line`
- [ ] Job lookup from Epicor (`getJobForPaintLine` , `getJob` )
- [ ] Schedule view (calendar or table format)
- [ ] Fields: JobID, PartDescription, Customer, Qty, EstimatedRunTime, StartTime, Notes, Complete, LineSpeed
- **Deps:** F-005, F-006 | **Est:** 6 hrs
### A-011: Admin Password Reset Links
- [ ] Generate password reset link for any user
- [ ] Create `auth_password_reset` record with token
- [ ] Optional: bypass minimum time restriction (`min_time_bypass` )
- [ ] Copy link to clipboard for admin to send manually
- **Deps:** F-007 | **Est:** 2 hrs
---
## Phase 4: Background Jobs & Polish (Est. 30-40 hrs)
### J-001: BullMQ Infrastructure
- [ ] Install and configure BullMQ with Redis connection
- [ ] `src/jobs/worker.ts` — worker process setup
- [ ] Job registration and scheduling system
- [ ] Dashboard: Bull Board or similar for job monitoring (admin only)
- [ ] Retry logic with exponential backoff
- [ ] Dead letter queue for failed jobs
- **Deps:** F-002 | **Est:** 4 hrs
### J-002: Shipment Request Nag Job
- [ ] Runs every 15 minutes
- [ ] Find open (unsubmitted) shipment requests
- [ ] Send reminder email to request owner
- [ ] Track `LastNagDT` to avoid duplicate nags
- [ ] Respects `withoutOverlapping` (skip if previous run still active)
- **Deps:** J-001, C-013 | **Est:** 3 hrs
### J-003: Order Acknowledgement Email Job
- [ ] Runs hourly
- [ ] Query Epicor for new orders (`getOrdersForCustomerOnOrAfterDate` )
- [ ] Cross-reference against `quest_processed_order_acknowledgement_email`
- [ ] Send to companies with `ReceivesSOEmails=true` and `OrderAckEmail` set
- [ ] Record in `quest_processed_order_acknowledgement_email` to prevent duplicates
- **Deps:** J-001, C-004 | **Est:** 4 hrs
### J-004: Invoice Cleanup Job
- [ ] Runs daily
- [ ] `disc:clearoldinvoices` equivalent
- [ ] Clean up old/expired invoice temporary data
- **Deps:** J-001, A-004 | **Est:** 2 hrs
### J-005: Shipping Report Generation Jobs
- [ ] Monthly report: 1st of month at 3am
- [ ] Call `getShippingForMonth(lastMonth)`
- [ ] Generate Excel file, save to storage
- [ ] YTD report: twice daily
- [ ] Call `getShippingYTD()`
- [ ] Generate/overwrite Excel file
- **Deps:** J-001, A-008 | **Est:** 4 hrs
### J-006: Wave EDI End-of-Month Job
- [ ] Runs monthly on 1st
- [ ] Execute Wave EDI end-of-month process
- [ ] Log results to `wave_process_history`
- [ ] Send completion email
- [ ] Minimal implementation per client direction
- **Deps:** J-001, A-009 | **Est:** 3 hrs
### J-007: Email Service (Microsoft Graph)
- [ ] `src/lib/email.ts` — Microsoft Graph API client
- [ ] OAuth2 client credentials flow (tenant + client ID + secret)
- [ ] Send email function: `sendEmail(to, subject, htmlBody, from?)`
- [ ] Email logging to `quest_email_log`
- [ ] Template system for common emails (request confirmation, nag, acknowledgement)
- [ ] Error handling + retry for transient Graph API failures
- **Deps:** F-001 | **Est:** 5 hrs
### J-008: PDF Generation Service
- [ ] `src/lib/pdf.ts` — PDF generation abstraction
- [ ] Method 1: Puppeteer (render HTML → PDF, replaces wkhtmltopdf)
- [ ] Method 2: @react -pdf/renderer for structured documents
- [ ] Templates: Order Acknowledgement, BOL, Job Traveler, Invoice
- [ ] Consistent header/footer styling
- **Deps:** F-001 | **Est:** 4 hrs
### J-009: E2E Test Suite
- [ ] Playwright configuration
- [ ] Test: Login flow (success + failure + rate limiting)
- [ ] Test: Dashboard loads with data
- [ ] Test: Inventory browse → category → summary → detail drill-down
- [ ] Test: Shipment request full workflow (create → add items → submit)
- [ ] Test: Admin invoice upload
- [ ] Test: Company switcher (admin)
- [ ] Data validation tests comparing Epicor query results
- **Deps:** All C-* tasks | **Est:** 8 hrs
### J-010: Production Deployment & Cutover
- [ ] Verify all Traefik routes serving correctly with SSL
- [ ] Run data migration scripts against production database
- [ ] Verify all Epicor connections from expvtcasp01
- [ ] DNS cutover: update `quest.vorteq.wulf.cloud` or `portal.vorteqcoil.com` as needed
- [ ] Smoke test all features post-cutover
- [ ] Rollback plan documented
- [ ] Security hardening: change Traefik dashboard password, secure .env, firewall rules
- **Deps:** All tasks | **Est:** 4 hrs
---
## Infrastructure Tasks (Completed)
### I-001: Server Provisioning
- [x] Linux server provisioned (expvtcasp01)
- [x] Docker installed
- [x] Docker Compose installed
- [x] Netbird VPN configured (100.89.62.20)
### I-002: Forgejo Repository
- [x] Repository created at `forgejo.wulfconsulting.cloud/lorentz/quest-vorteq`
- [x] SSH key configured (port 222)
- [x] Git identity configured on server
- [x] Initial infrastructure files pushed
### I-003: CI/CD Pipeline
- [x] Forgejo Actions enabled on repository
- [x] Self-hosted runner registered (`expvtcasp01` ) using Docker-in-Docker
- [x] Build workflow: checkout → Docker build → push to Forgejo registry
- [x] Deploy workflow: SSH into server → pull → restart containers
- [x] Secrets configured (registry credentials, deploy SSH key)
### I-004: Infrastructure Stack
- [x] Traefik v3 running with Cloudflare DNS challenge
- [x] SSL certificate issued for `traefik.vorteq.wulf.cloud`
- [x] PostgreSQL 16 running with dev/test/prod databases
- [x] Redis 7 running with separate DB numbers per environment
- [x] Cloudflare DNS A records pointing to Netbird IP
### I-005: Domain Configuration
- [x] `quest.vorteq.wulf.cloud` → 100.89.62.20 (production)
- [x] `dev.quest.vorteq.wulf.cloud` → 100.89.62.20 (development)
- [x] `testing.vorteq.wulf.cloud` → 100.89.62.20 (testing)
- [x] `traefik.vorteq.wulf.cloud` → 100.89.62.20 (dashboard)
---
## Summary
| Phase | Tasks | Est. Hours (Low) | Est. Hours (High) |
|-------|-------|-------------------|---------------------|
| Phase 1: Foundation | F-001 to F-010 | 28 | 38 |
| Phase 2: Core Features | C-001 to C-016 | 80 | 110 |
| Phase 3: Admin Features | A-001 to A-011 | 60 | 80 |
| Phase 4: Jobs & Polish | J-001 to J-010 | 30 | 40 |
| Infrastructure | I-001 to I-005 | Done | Done |
| **TOTAL** | **52 tasks** | **198** | **268** |