Quote to Cash — Development Workflow Map
Build Progress
Built
Partial
Planned
Updated: July 20, 2026 (Session 33)

✅ Checklist to Beta

Everything needed to run a real load end-to-end — quote → invoice → QuickBooks. Check items off as they're completed.

Beta Progress 0 / 0 complete

✅ Architecture Decisions — Locked (Session 27)

Detention rate: Per-customer field (detention_rate_per_hr) on customer record, system default fallback. Add to customer file.
Invoice net terms: Per-customer field (net_terms) on customer record, default Net 30. Add to customer file.
QBO Service items: One item per accessorial type + gl_account field on accessorial_types table + freight GL account as a system setting.
Driver assignment: Dispatcher enters driver name + cell in HPL order panel → Dispatch Driver button sends SMS directly. No self-dispatch, no HPDRIVE/MC# challenge. (Session 31 decision.)
QBO billing entity: TBD — confirm before Phase 5 begins.
Payment sync: Cash applied in QBO; HPL updated manually for beta so customer credit can be managed. credit_limit + outstanding_balance fields on customers table. Webhook post-beta.
Phase 1
Bug Fixes + Status Wiring
Waiting
Session 27. Every status transition fires automatically; core bugs fixed. Required before anything else is testable.
Fix Appointments sub-tab showing blank — add one line to opStopTab(): if(_op.stops[stop-1]) _op.stops[stop-1].activeSubTab = name; 1-line fix
index.html
Wire status auto-advance: Quote sent → sent, Driver dispatched → dispatched, CDL verified → verified, ARRIVED shipper → at_shipper, DONE at shipper → in_transit, ARRIVED consignee → at_consignee, BOL submitted → delivered code
sms-webhook.js + others
Make Service Prefs tab editable — dispatcher can change tracing requirement and notification contacts after sign.html is submitted code
index.html
Add location directory name to rate-con.html — currently shows "City, ST" only; should show "Monroe Distribution Center, Monroe, LA" code
rate-con.html + validate-rate-con.js
Surface source email body in Documents tab — email_body column exists on orders, just needs to render as a collapsible card code
index.html
Phase 2
Driver Assignment (Session C)
Waiting
Sessions 28–29. Nothing ships past rate_con_signed without a way to assign a driver. Covers dispatcher entry of driver name/cell, dispatch SMS, CDL/door photo capture, and chasing cron. SMS auth challenge (self-dispatch) removed Session 31 — dispatcher flow only.
Build assign-driver.html — dispatcher-facing page to enter driver name + cell; sets status = 'awaiting_driver'; sends dispatch SMS to driver code
new file
Add SQL columns: assign_driver_token, last_driver_chase_at on orders table SQL
Supabase
Persistent carrier dispatch link — sent with rate con; shows load status, driver assignment form, SMS instructions; re-sendable from order panel code
new carrier-dispatch.html
Driver SMS auth challenge — driver texts load# → system replies with MC# prompt → driver texts MC# → match = authenticated removed — Session 31: self-dispatch eliminated; dispatcher enters cell directly, sms_state set on dispatch
sms-webhook.js
Driver chasing cron — identifies loads stuck in awaiting_driver; sends chaser messages to carrier dispatch on schedule code
api/driver-chase-cron.js + vercel.json
Dispatch gate — block driver assignment if rate_con_signed_at is null; show warning or hard block code
index.html
Phase 3
Delivery Close
Waiting
Session 29. Load reaches delivered status with BOL in the system. Required before invoice can be generated.
BOL photo storage — driver-checkin.html already captures the photo; wire upload to Supabase Storage (carrier-docs bucket) + write bol_upload_url to order code
driver-checkin.html
Wire status → delivered trigger — fires in sms-webhook.js when sms_state = 'completed' (or BOL confirmed); writes load_events row code
sms-webhook.js
Delivered visual state on load board — delivered badge, collapse active-load controls, move to "Completed" filter code
index.html
Phase 4
Invoice Generation
Waiting
Sessions 30–31. One-click invoice PDF generated from the order, emailed to customer, tracked in the load board. Requires Phase 3 complete. Decide open questions before starting.
Create invoices table — id, order_id, invoice_number (HPL-INV-XXXX), customer_id, status (draft/sent/paid/void), freight_charge, accessorial_lines (jsonb), detention_charge, total_amount, invoice_date, due_date, paid_at, invoice_pdf_url, qbo_invoice_id, qbo_synced_at SQL
Supabase
Detention charge auto-calc — pull detention_start_shipper/consignee from order; compute billable hours (>2hr free); apply rate from [source — decide before building] code
api/generate-invoice.js
Build api/generate-invoice.js — uses pdf-lib (already installed); pulls customer, freight charge, accessorials, detention, order details; generates PDF; uploads to Supabase Storage; writes invoice_pdf_url code
new file
Invoice number sequence — auto-increment HPL-INV-XXXX; Postgres sequence or MAX+1 on insert SQL code
Supabase + generate-invoice.js
Build api/send-invoice.js — sends PDF as email attachment via Graph API; writes status = 'sent' and customer_communications row code
new file
Invoice tab / card in order panel — shows status badge (Draft / Sent / Paid), Generate Invoice button, Preview link, Send to Customer button, detention override field, Mark Paid button code
index.html
Phase 5
QuickBooks Online Integration
Waiting
HPL generates invoices and pushes them to QuickBooks Online. QBO is the book of record. OAuth connection, customer sync, and invoice push with line items. ~2 sessions to complete.
Create QBO app at developer.intuit.com → get Client ID + Client Secret; set redirect URI to https://loadboard.cptms.com/api/qbo-callback David
Intuit Dev Portal
Add Vercel env vars: QBO_CLIENT_ID, QBO_CLIENT_SECRET, QBO_REDIRECT_URI, QBO_REALM_ID David
Vercel dashboard
In QBO create Service items: Freight, Detention, plus one per accessorial type. Map to correct income accounts. Confirm net payment terms and which QBO entity receives invoices. David
QuickBooks Online
OAuth flow — api/qbo-auth.js, api/qbo-callback.js, api/_qbo-client.js (token refresh helper), qbo_tokens table, "Connect to QuickBooks" setup page code
~1 session
Invoice sync — api/qbo-sync-customer.js (find or create customer), api/qbo-push-invoice.js (post invoice with line items on send), sync status badge in order panel invoice tab (✅ Synced / ⚠ Not synced / ❌ Failed + Retry) code
~1 session
End-to-end test: quote → sign → rate con → driver → delivered → invoice sent → appears in QBO ✅ Beta test
Full E2E
Post-Beta
After Launch — Don't Block Beta On These
Deferred
These are real gaps but will not block a beta test. Do them after the first real load runs through to QBO.
QBO payment sync — when "Mark Paid" clicked in HPL, push a Payment record to QBO closing the invoice code
Post-beta
Carrier remittance — generate carrier payment record PDF + email to carrier dispatch; create Bill in QBO against carrier as Vendor code
Post-beta
Payment receipt recording — invoices.paid_at, amount, payment method; status → closed; closed loads filter on board code
Post-beta
Multi-order email split UI — for emails that contain multiple loads; beta uses single-order emails or manual entry code
Post-beta
Detention ack checkbox on sign.html before signature (legal exposure — do soon after beta) code
Post-beta
Driver GPS proximity check — cross-check driver GPS against shipper address on ARRIVED code
Post-beta
Step 1 — SQL foundation — Create tables: document_capture_types, order_documents, document_capture_requests, document_type_role_notifications. Add OS&D role to roles table. Add interested_party to order_contacts constraint. Seed 8 built-in types (CDL front/back, door, trailer, seal, BOL, scale ticket, OS&D) all with active=false. SQL — David runs
Stage 1–2 · PLAN_DOCUMENT_MANAGEMENT.md
Step 2 — Intake stamp utility (build first — evergreen)api/_stamp-image.js: takes image buffer, doc type label, order/carrier ref, server timestamp; burns small header into top-right corner; returns stamped buffer. Wire into storePhoto() immediately so every upload from this point forward is stamped automatically — CDL, door, and all future types. Two flavors: order docs (HPL-1234 · CDL Front · [date/time]) and carrier onboarding docs ([Carrier Name] · Received [date/time]). code
Stage 8 (moved first) · evergreen from day one
Step 3 — Document types API + Files & Master Data UIGET /api/document-capture-types endpoint. Files & Master Data UI: table of types with add/edit modal (label, slug, category, color mode, resolution, quality, barcode decode, AI extract, active toggle, role notifications, external notification, invoice inclusion). New types addable from UI with zero code changes. code
Stages 3–4
Step 4 — Config-driven driver capture + POST /api/capture-documentdriver-checkin.html reads type config from API dynamically (no hardcoded type logic). jscanify guided camera capture — auto-fires when document stable ~1 sec. Color/grayscale/BW applied per config. POST /api/capture-document receives image, stamps it, stores in order_documents, fires notifications (Relay DM to roles + email to order contacts). code
Stages 5–6
Step 5 — Order panel Documents tab + dispatcher capture request — Documents tab in order panel: grid of received docs (thumbnail, type, timestamp, captured-by). "Request Document" button → pick type → add verbiage → sends SMS link to driver (POST /api/send-doc-request). Dispatcher manual upload path for docs arriving by email or from customer. Include-with-invoice toggle per doc. code
Stage 7
Step 6 — POD generation — At delivery driver opens single-use link; receiver signs with finger; optional receiver photo (consent disclosure shown). Server composites: stamped BOL at 75% + fixed delivery stamp block at bottom (driver name, arrival time, departure time, detention amount, receiver name, digital signature, GPS coords). Stored as pod_url. Attaches to invoice automatically. Raw original and stamped working copy stored separately for dispute protection. code
Stage 9
Step 7 — Retire old hardcoded URL columns — Remove scattered URL columns from orders table (bol_upload_url, door_photo_url, seal_photo_url, etc.) after full E2E test of new system passes on a real load. SQL + code
Stage 10 — last, after full E2E test
⚡ Third-Party Services & APIs
What every connected service does — Happy Path Logistics
Section 1
Foundation — The Backbone
Everything else depends on these three
Supabase
The filing cabinet. Cloud PostgreSQL database that stores everything: customers, carriers, orders, quotes, drivers, SMS logs, documents, user accounts. Also handles file storage (carrier docs, PDFs) and user logins. Free tier
Where to manage
supabase.com → project rfdpkmugikooelpprlak
Vercel
The web host. Serves both websites and runs all server-side code (API functions that send email, call Claude, send SMS). Also runs scheduled background jobs every 5–15 minutes. Holds all secret API keys securely so they never appear in browser code. ~$20/mo
Where to manage
vercel.com — projects: happypath-quotes, happypath-loadboard
GitHub
Version control + auto-deploy. Stores all source code with full change history. When code is pushed to GitHub, Vercel automatically picks it up and publishes the update live within ~10 seconds. Two repos: happypath-quotes and happypath-loadboard. Free
Where to manage
github.com/DHaidle
Section 2
Email — Microsoft Graph API
Reads and sends email from your Outlook inbox
What it does
Reads unread Outlook emails and shows them as cards in the Rate Request column. Sends all outbound emails: quotes, customer onboarding links, carrier packets, auto-replies for unknown senders.
Two parts
Azure AD — the gatekeeper; proves the app is allowed to access your inbox. Microsoft Graph — the actual API that reads and sends messages once permission is confirmed.
How login works
You log in via "Sign in with Microsoft" once. Microsoft issues a token the system refreshes automatically — you stay connected for weeks.
Cost
Included with your Microsoft 365 subscription. Manage at portal.azure.com → App Registrations.
Section 3
AI — Anthropic Claude API
Extracts structured data from documents and photos
What it reads
Bill of Lading PDFs · Carrier insurance certificates (COI) · W-9 forms · Operating authority letters · Business cards · Driver license photos · Truck door photos for DOT number verification
How it works
Given a document or photo, Claude answers specific questions: "What is the pickup ZIP?" or "What is the EIN on this W-9?" and returns a structured answer the system can use automatically.
Model used
Claude Haiku — the fast, cost-efficient version. A typical document extraction takes 2–5 seconds and costs less than half a cent.
Cost
~$5–20/mo Pay per use. Manage at console.anthropic.com.
Section 4
SMS Messaging — Twilio
Two-way text messaging with drivers (switched from Telnyx May 29, 2026)
What it does
Provides a phone number and handles all SMS traffic between Happy Path and drivers. When a driver texts ARRIVED, Twilio receives it and calls the webhook at loadboard.drehco.com/api/sms-webhook (moved from quotes in the June 3 migration). When the system sends a check-in, Twilio delivers it to the driver's phone.
Phone number
+1 (844) 820-5813 — toll-free number. Account SID: AC94a5e153a77641a4f9547f73c1b039d7. Manage at console.twilio.com.
Toll-free verification
Submitted May 29, 2026. Status: Pending (3–7 business days). Outbound SMS is blocked until approved — inbound (driver → system) works now. Consent URL: loadboard.drehco.com/carrier-onboarding.html (drivers opt in via Broker-Carrier Agreement).
Trial account
$13.35 remaining credit. Can only send to Verified Caller IDs until verification approved. David's cell (+1 630 561 3608) is verified for testing.
Why switched from Telnyx
Telnyx compliance pages (privacy.html, terms.html, sms-optin.html) were taken down to avoid public-facing pages before launch. Twilio was set up with the same toll-free verification requirement but cleaner trial experience for testing inbound flow.
Cost
~$15/mo paid Trial: $15.50 credit. ~$0.0079/SMS in + out. Upgrade when toll-free verified and ready to go live.
Section 5
Address & Routing — Four Free Services
Each handles a specific address task — all free
SmartyStreets
USPS address checker. Standardizes addresses, verifies they exist, fills ZIP+4, flags residential vs. commercial, returns precise GPS coordinates. Powers the 📍 Verify button on all address fields. Free (250/mo)
Nominatim
Free geocoding backup. OpenStreetMap's service — converts addresses/ZIPs to GPS coordinates. Used in mileage calculation and as a fallback when SmartyStreets has no result. No key required. Free
OSRM
Driving distance calculator. Given two GPS coordinates, returns actual road miles and estimated travel time. Powers the miles field on every order's rate section. No key required. Free
Zippopotam.us
ZIP code directory. Takes a 5-digit ZIP and returns city, state, and time zone. Powers the city/state auto-fill on every ZIP field in the platform. No key required. Free
Section 6
Carrier Verification — FMCSA QCMobile API
Official US government database of licensed trucking companies
What it is
The Federal Motor Carrier Safety Administration's public API. Every licensed US carrier has a DOT/MC number registered here. The API lets the system look up any carrier instantly.
What it returns
Legal name, address, authority status (active/inactive), safety rating, insurance on file, out-of-service orders, BASIC safety scores, cargo classes, authority history.
Where you see it
Carrier onboarding auto-fill on MC/DOT lookup. Carrier panel FMCSA profile card. The standalone FMCSA Lookup tool at loadboard.drehco.com/fmcsa-lookup.html.
Cost
Free US government public data. No account needed.
Section 7
Monitoring — Better Stack
Smoke detector for the background jobs
What it does
The cron watchdog pings a Better Stack URL every 5 minutes after running successfully. If the ping stops arriving, Better Stack emails an alert. This catches Vercel outages or code errors before they silently fail for hours.
What it monitors
The watchdog job itself (dead man's switch). The watchdog in turn checks all other crons internally and sends SMS alerts via Twilio for missed or errored jobs.
Cost
Free tier Manage at uptime.betterstack.com.
Section 8
DNS & Domain
Two separate services — easy to confuse, important to know
Wild West Domains
Domain registrar. Holds the legal registration of drehco.com and renews it annually (~$15/yr). Does NOT manage DNS records — that's Netlify's job now.
Netlify DNS
DNS manager. Controls all DNS records: where email goes (MX → Microsoft 365), where web traffic goes (CNAME → Vercel), anti-spam settings (SPF). All DNS changes must be made here, not in Wild West.
⚠️ History
Netlify became DNS manager in May 2026 when it was connected for compliance pages. The MX records weren't carried over, causing a 16-hour email outage. Lesson: changing nameservers wipes all records unless manually re-added.
Where to manage
app.netlify.com → Teams → david-dx8vbgo → DNS → drehco.com
Section 9
Planned — Not Yet Connected
Designed but not yet built
DAT RateView
Freight market rate data — suggests competitive rates by lane when quoting. Customer provides their own DAT subscription. Integration not yet built.
QuickBooks Online
Auto-generate customer invoices and carrier payment bills when a load closes. Eliminates manual QuickBooks entry. Architecture designed, not yet built.