Quest Domain Complete (F-004): - quest_account_request: new user registration requests - quest_notification + alert reads: notification/alert system - quest_email_event + subscriptions: email event management - quest_email_log: email tracking - quest_plant + inventory_type + inventory_plant: plant/inventory configuration - quest_processed_order_acknowledgement_email: duplicate prevention Remaining Domains Complete (F-005): Shipment Requests: - ship_request + ship_request_detail: shipment request cart workflow Allocation Requests: - alloc_request + alloc_request_detail + alloc_plant: coil allocation workflow Invoice Management: - inv_upload + inv_upload_entry + inv_upload_status: invoice upload/processing Finance/AP: - finance_ap_check_processing_batch + status: AP check processing Paint Schedule: - paint_plant + paint_line + paint_line_type + paint_plant_line + paint_schedule Documentation: - doc_category + doc_article + doc_article_permission_group: knowledge base Wave/EDI: - wave_process + wave_process_history: EDI processing Task Scheduler: - lts_task + lts_task_type + lts_task_schedule + lts_task_execution Total: 60+ tables, 600+ columns across all domains. All migrations applied successfully. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
22 KiB
22 KiB
Vorteq Quest Portal - Task Tracking
Reference:
docs/Vorteq_Quest_PRD_v1.0.docxfor full specifications Instructions:CLAUDE.mdfor coding conventions and patternsMark tasks:
[ ]Not started |[~]In progress |[x]Complete |[!]Blocked
Phase 1: Foundation (Est. 30-40 hrs)
F-001: Project Scaffold
- Initialize Next.js 15 with App Router, TypeScript strict mode
- Install and configure Tailwind CSS
- Install and configure shadcn/ui (default theme)
- Configure ESLint + Prettier
- Configure
tsconfig.jsonwith path aliases (@/) - Create base project structure per CLAUDE.md
- Create
.dockerignorefor build optimization - Deps: None | Est: 2 hrs | Status: ✅ Complete
F-002: Docker & Infrastructure Alignment
Dockerfilefor Next.js app (Node.js 22, multi-stage build)docker-compose.yml: Traefik, postgres:16-alpine, redis:7-alpine, app-dev, app-test, app-prod- Traefik reverse proxy with Cloudflare DNS challenge for auto-SSL
.env.examplewith all required variablesinit-databases.shfor multi-database PostgreSQL setupsetup.shfor server provisioning- Health check endpoints in Next.js app (
/api/health) - Verify
next.config.jshasoutput: 'standalone'for Docker - Deps: F-001 | Est: 1 hr (remaining) | Status: ✅ Complete
F-003: Prisma Schema - Auth Domain
auth_usertable (email, password hash, deactivated, verified, login counts, 2FA, SSO fields)auth_domaintableauth_user_typetableauth_oauth_client+auth_oauth_access_token+auth_oauth_refresh_tokenauth_password_history+auth_password_resetauth_permission_group+auth_permission_rule+ junction tableauth_permission_rule_categoryauth_security_question+auth_security_answer- Run initial migration, verify schema
- Deps: F-001 | Est: 4 hrs | Status: ✅ Complete
F-004: Prisma Schema - Quest Domain
quest_company(EpicorCustID, display name, invoicing flags)quest_user(FK to auth_user, IsSubUser, API token)quest_user_companyjunction tablequest_account_requestquest_notification+quest_user_notification_alert_readquest_email_event+quest_user_email_eventjunctionquest_email_logquest_plant+quest_inventory_type+quest_inventory_plantquest_processed_order_acknowledgement_email- Run migration, verify
- Deps: F-003 | Est: 3 hrs | Status: ✅ Complete
F-005: Prisma Schema - Remaining Domains
ship_request+ship_request_detailalloc_request+alloc_request_detail+alloc_plantinv_upload+inv_upload_entry+inv_upload_statusfinance_ap_check_processing_batch+finance_ap_check_processing_statuspaint_plant+paint_line+paint_line_type+paint_plant_line+paint_scheduledoc_article+doc_category+doc_article_permission_groupwave_process+wave_process_historylts_task+lts_task_type+lts_task_schedule+ related tables- Run migration, verify all relationships
- Deps: F-004 | Est: 4 hrs | Status: ✅ Complete
F-006: Epicor MSSQL Connection Service
src/lib/epicor.ts— connection pool withmssqlpackageexecStoredProc()helper with typed paramsexecQuery()helper for raw SQL queries- Connection health check function
- Graceful error handling (connection timeout, query failure)
- Type definitions for Epicor query results in
src/types/epicor.ts - Test connection against Epicor10Live with
portaluser - Deps: F-001 | Est: 3 hrs
F-007: Better Auth Setup
- Install and configure Better Auth
- Credentials provider: validate against
auth_usertable (bcrypt) - Session strategy with user ID, email, role, company context
- Session includes: userId, questUserId, activeCompanyId, isSubUser, permissionRules[]
- Login page at
/login - Forgot password page at
/forgot-password - Account request page at
/account-request - reCAPTCHA integration on public forms
- Deps: F-003 | Est: 4 hrs
F-008: Middleware & Guards
src/middleware.ts— redirect unauthenticated users to /login- Company context middleware: ensure active company is selected
src/lib/permissions.ts—requirePermission(rule)helper- Admin route protection (check user type)
- Sub-user detection helper (
isSubUser()) - Company selector:
/select-companypage for multi-company users - Rate limiting on auth endpoints
- Deps: F-007 | Est: 4 hrs
F-009: Base Layout & Navigation
- Root layout with sidebar navigation
- Header: company name, user menu, notification bell
- Sidebar: Dashboard, Inventory, Orders, Shipments, Coil Activity, Invoices, Requests
- Admin section in sidebar (conditional on role)
- Company switcher dropdown (admin) or display (customer)
- Responsive: collapsible sidebar on mobile
- Breadcrumb component
- Deps: F-007 | Est: 3 hrs
F-010: Data Migration Scripts
scripts/migrate-data.ts— connects to both SQL Server and PostgreSQL- Migrate
auth_user+auth_user_type+auth_domain(preserve bcrypt hashes) - Migrate
auth_permission_group+auth_permission_rule+ junction - Migrate
quest_user+quest_company+quest_user_company - Migrate
quest_plant+quest_inventory_type/plant - Migrate
quest_email_event - Migrate
ship_request+ship_request_detail(historical data) - Migrate
alloc_request+alloc_request_detail - Migrate supporting tables (notifications, docs, email events, wave, paint)
- Validation: count comparison, spot-check key records
- Handle: IDENTITY → SERIAL, datetime2 → TIMESTAMPTZ, bit → BOOLEAN, nvarchar(MAX) → TEXT
- Deps: F-005 | Est: 6 hrs
Phase 2: Core Features (Est. 80-110 hrs)
C-001: Dashboard
- Dashboard page at
/(portal)/dashboard/page.tsx - Server component: fetch top 5 orders, top 5 shipments from Epicor
- Summary cards: inventory overview, recent activity
- Notification alert banner (unread alerts)
- Quick-nav cards to major features
- Loading skeletons for async data
- Deps: F-009, F-006 | Est: 6 hrs
C-002: Inventory Summary Views
/(portal)/inventory/page.tsx— category selector/(portal)/inventory/[category]/page.tsx— summary data table- Service:
src/services/inventory.tsgetWorkInProgressSummary(custId, dbName, sub)getFinishedGoodsSummary(custId, dbName, sub)getProcessedOtherSummary(custId, dbName, sub)getUnprocessedSummary(custId, dbName)— block sub-usersgetUnprocessedRRSummary(custId, dbName)— block sub-usersgetProcessedRRSummary(custId, dbName)— block sub-users
- V6 procedures: pass
subparam (0/1 based on user) - Row count pre-fetch for detail drill-down (ALLV6 with count flag)
- Data table with sorting, filtering, export to CSV
- Click row → navigate to detail view
- Deps: F-006, F-009 | Est: 12 hrs
C-003: Inventory Detail Views
/(portal)/inventory/[category]/details/page.tsx- Query params:
part,plant,warehouse(for specific) or none (for all) - Service functions for each detail stored procedure (V6 and legacy)
- Paint code display (from Epicor Part_UD table)
- Part description with paint code lookup (
getVorPartDescriptionFromPartNumberWithPaintCode) - On-hand quantity for specific lines
- Data table with full column set
- Back navigation to summary
- Deps: C-002 | Est: 8 hrs
C-004: Order List
/(portal)/orders/page.tsx- Service:
getTop100Orders(custId)usingportal_Orders.sql - HDC/HDM exception handling (use
portal_OrdersHDCview, map CustID) - Data table: Order Number, PO, Customer Part, Vorteq Part, Dates, Qty, Status
- Click-through to order acknowledgement
- Deps: F-006, F-009 | Est: 6 hrs
C-005: Order Acknowledgement Detail + PDF
/(portal)/orders/[id]/page.tsx- Service:
getAcknowledgement(customer, poNumber?, orderNum?)usingSalesOrder.sql - Detail view with all order line information
- PDF export button (generate PDF server-side)
- Deps: C-004 | Est: 6 hrs
C-006: Shipment List
/(portal)/shipments/page.tsx- Service:
getTop100Shipments(custId, dbName)viaportal_GetShipmentsV1 - ShipToLoc formatting (replace
,with line breaks) - Data table with shipment details
- Click-through to BOL detail
- Deps: F-006, F-009 | Est: 5 hrs
C-007: BOL Detail + PDF
/(portal)/shipments/[bol]/page.tsx- Service:
getBOL(bolNum, custId)usinggetBOL.sql - Detail view with line items
- PDF export
- Deps: C-006 | Est: 4 hrs
C-008: Coil Activity - Usage Report
/(portal)/coil-activity/usage/page.tsx- Date range picker (with validation)
- Service:
getCoilActivityUsage(custId, startDate, endDate)usingportal_CoilActivityUsage.sql - Deduplication logic: only show OnHandQty for most recent DateUsed per LotNum
- Zero weights → null display
- Data table with full column set
- Deps: F-006, F-009 | Est: 6 hrs
C-009: Coil Activity - Receipts Report
/(portal)/coil-activity/receipts/page.tsx- Date range picker
- Service:
getCoilActivityReceipts(custId, startDate, endDate) - VGL customer exception (use special SQL)
- Data table with receipt columns
- Deps: F-006, F-009 | Est: 4 hrs
C-010: Coil-by-Coil Report
/(portal)/coil-activity/coil-by-coil/page.tsx- Job number search input
- Service:
getCoilByCoil(jobNum, customer)usingCoilByCoil.sql - Detail display
- Deps: F-006 | Est: 3 hrs
C-011: Job Status by Plant
/(portal)/jobs/status/page.tsx- Service:
getJobStatusByPlantByCustomer(custId, dbName)usingJobStatusByPlantByCustomer.sql - Note: requires DBNAME cross-database parameter
- Data table grouped by plant
- Deps: F-006 | Est: 3 hrs
C-012: Job Traveler + PDF
/(portal)/jobs/[jobNum]/traveler/page.tsx- Service:
getJobTraveler(jobNum)usingjobTraveler.sql - Detailed routing/operations view
- PDF export
- Deps: F-006 | Est: 4 hrs
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_detailrecords, 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_detailtables 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_entryfiltered 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_readrecord - 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_entryrecords - 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_processentries with enable/disable toggles - View
wave_process_historywith 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_resetrecord 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
LastNagDTto 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=trueandOrderAckEmailset - Record in
quest_processed_order_acknowledgement_emailto prevent duplicates - Deps: J-001, C-004 | Est: 4 hrs
J-004: Invoice Cleanup Job
- Runs daily
disc:clearoldinvoicesequivalent- 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
- Call
- YTD report: twice daily
- Call
getShippingYTD() - Generate/overwrite Excel file
- Call
- 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.cloudorportal.vorteqcoil.comas 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
- Linux server provisioned (expvtcasp01)
- Docker installed
- Docker Compose installed
- Netbird VPN configured (100.89.62.20)
I-002: Forgejo Repository
- Repository created at
forgejo.wulfconsulting.cloud/lorentz/quest-vorteq - SSH key configured (port 222)
- Git identity configured on server
- Initial infrastructure files pushed
I-003: CI/CD Pipeline
- Forgejo Actions enabled on repository
- Self-hosted runner registered (
expvtcasp01) using Docker-in-Docker - Build workflow: checkout → Docker build → push to Forgejo registry
- Deploy workflow: SSH into server → pull → restart containers
- Secrets configured (registry credentials, deploy SSH key)
I-004: Infrastructure Stack
- Traefik v3 running with Cloudflare DNS challenge
- SSL certificate issued for
traefik.vorteq.wulf.cloud - PostgreSQL 16 running with dev/test/prod databases
- Redis 7 running with separate DB numbers per environment
- Cloudflare DNS A records pointing to Netbird IP
I-005: Domain Configuration
quest.vorteq.wulf.cloud→ 100.89.62.20 (production)dev.quest.vorteq.wulf.cloud→ 100.89.62.20 (development)testing.vorteq.wulf.cloud→ 100.89.62.20 (testing)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 |