This repository has been archived on 2026-03-21. You can view files and clone it, but cannot push or open issues or pull requests.
payfrit-biz/CLAUDE.md
John Mizerek e21a7f7266 Remove DeliveryMultiplier from Businesses query (column no longer exists)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 11:11:34 -08:00

220 lines
10 KiB
Markdown

# Payfrit Business Platform
Main CFML/JS repository: API + Portal + KDS + HUD + Receipt. Git repo on Forgejo; local clone at `C:\dev\payfrit-biz`.
## Build & Deploy
```bash
# Deploy: SCP to /tmp on dev, then sudo cp to biz.payfrit.com/ path
ssh dev.payfrit.com
# Canonical source of truth on dev:
# /opt/lucee/tomcat/webapps/ROOT/biz.payfrit.com/
# No local Lucee — all development happens on the dev server
```
**Dev symlinks** on dev server: `/api`, `/portal`, `/config`, `/cron` are all symlinks to `biz.payfrit.com/`. **Always edit under `biz.payfrit.com/` — never the root symlinks directly.**
## Project Structure
```
payfrit-biz/
├── Application.cfm # Root app config: sessions (30min), datasource, layout wrapper
├── index.cfm # Legacy entry point, mode-based routing
├── onrequestend.cfm # Footer/cleanup
├── register.cfm # Account registration
├── confirm_email.cfm # Email verification
├── confirm_mobile.cfm # Mobile verification
├── reset.cfm # Password reset
├── show_order.cfm # Order detail (redirects to /receipt/)
├── privacy.html # Privacy policy
├── api/ # REST API (~135 endpoints, 23 domains)
│ ├── Application.cfm # Token auth gate (X-User-Token, X-Business-ID headers)
│ ├── config/
│ │ ├── stripe.cfm # Stripe API keys
│ │ └── environment.cfm # Dev vs prod settings
│ ├── addresses/ # CRUD delivery addresses (add, delete, list, setDefault, states, types)
│ ├── admin/ # Admin utilities
│ │ ├── _scripts/ # One-off migration scripts (git-ignored)
│ │ ├── quickTasks/ # Task type/category management
│ │ └── scheduledTasks/ # Cron coordination
│ ├── app/ # App info (about.cfm)
│ ├── assignments/ # Employee assignments (delete, list, save)
│ ├── auth/ # Authentication (login, loginOTP, sendOTP, verifyOTP, profile, avatar)
│ ├── beacons/ # Beacon management (CRUD, lookup, reassign)
│ ├── businesses/ # Business profiles (get, list, update, hours, hiring, brandColor)
│ ├── chat/ # Order chat (send, get, markRead, close)
│ ├── debug/ # Debug endpoints (localhost-protected)
│ ├── dev/ # Dev tools (seedData, timeTravel)
│ ├── import/ # Menu import (crimson_menu.cfm)
│ ├── menu/ # Menu management (items, categories, menus, builder, photos)
│ ├── orders/ # Order lifecycle (cart, submit, status, KDS list, history)
│ ├── portal/ # Portal-specific (team, stats, settings, searchUser)
│ ├── ratings/ # Customer ratings (create, list, submit)
│ ├── servicepoints/ # Service point CRUD
│ ├── setup/ # Business onboarding wizard (analyze, import, save)
│ ├── stations/ # Kitchen stations (list)
│ ├── stripe/ # Payments (createPaymentIntent, onboard, status, webhook)
│ ├── tasks/ # Task system (accept, complete, create, list, types, categories)
│ ├── users/ # User search
│ └── workers/ # Worker system (account, onboarding, tier, ledger, earlyUnlock)
├── portal/ # Business management SPA
│ ├── index.html # Main dashboard
│ ├── login.html # Portal login
│ ├── signup.html # Business registration
│ ├── menu-builder.html # Interactive menu builder
│ ├── setup-wizard.html # Onboarding wizard
│ ├── station-assignment.html # Station management
│ ├── quick-tasks.html # Quick task interface
│ ├── portal.js # Core JS (~169KB, vanilla JS, no framework)
│ └── portal.css # Portal styles (~22KB)
├── kds/ # Kitchen Display System
│ ├── index.html # Full-screen kitchen display
│ ├── admin.html # KDS admin
│ ├── debug.html # Debug tools
│ └── kds.js # KDS logic (~17KB, 5-second polling)
├── hud/ # Task HUD (Heads Up Display)
│ ├── index.html # Full-screen task bars
│ └── hud.js # HUD logic (~12KB, 60s target times)
├── receipt/ # Public receipt page (isolated app)
│ ├── Application.cfm # Minimal config (no parent layout)
│ └── index.cfm # Order receipt by UUID
├── admin/ # Admin tools
│ ├── beacons.cfm # Beacon management
│ ├── beacon_servicepoint.cfm # Beacon-SP mapping
│ ├── email_users.cfm # Bulk email
│ ├── god_mode.cfm # Super-admin panel
│ └── servicepoints.cfm # Service point management
├── library/cfc/ # ColdFusion components
│ ├── businessMaster.cfc # Business data abstraction
│ └── twilio.cfc # SMS integration
├── includes/ # Shared includes
│ ├── menu.cfm # Menu rendering
│ └── track_visitors.cfm # Analytics
├── uploads/ # User-generated content
│ ├── categories/ # Category images
│ ├── headers/ # Business header images
│ ├── items/ # Menu item photos
│ ├── logos/ # Business logos
│ └── users/ # User profile images
├── cron/
│ └── expireStaleChats.cfm # Cleanup old chats
├── css/ # Bootstrap 5.3.0 + custom
├── js/ # jQuery 1.11/2.1, Bootstrap JS
├── fonts/ # Glyphicons
├── images/ # Logo assets
├── cfpayment/ # Payment gateway library
└── twilio/ # Twilio SMS
```
## Key Files
| File | Purpose |
|------|---------|
| `api/Application.cfm` | Token auth, public endpoint allowlist, perf tracking, datasource config |
| `Application.cfm` | Root session management (30min timeout), layout wrapper, business/twilio objects |
| `portal/portal.js` | Main portal SPA logic (169KB, vanilla JS, Fetch API) |
| `kds/kds.js` | Kitchen display polling & order status management |
| `hud/hud.js` | Task visualization with time tracking & beacon alerts |
## API Authentication
- **Header**: `X-User-Token` (64-char hex, SHA-256 based)
- **Business Context**: `X-Business-ID` header
- **Token Table**: `UserTokens` (Token, UserID)
- **Public Endpoints**: ~50+ whitelisted in `api/Application.cfm` (no token required)
- **OTP Flow**: sendOTP → verifyOTP → token issued
- **Magic OTP**: `123456` bypass for App Store review
## Environment Detection
```
Localhost (127.0.0.1):
wwwrootprefix = /biz.payfrit.com/
image_display_prefix = http://127.0.0.1:8888/biz.payfrit.com/uploads/
uploads_dir = C:\lucee\tomcat\webapps\ROOT\biz.payfrit.com\uploads\
Production:
wwwrootprefix = /
image_display_prefix = https://biz.payfrit.com/uploads/
uploads_dir = /var/www/biz.payfrit.com/uploads/
```
## Tech Stack
- **Backend**: CFML (Lucee), Application.cfm (not .cfc)
- **Portal/KDS/HUD**: Vanilla JavaScript (no framework)
- **Root pages**: jQuery 1.12.4 (CDN) + Bootstrap 5.3.0 (CDN)
- **Payments**: Stripe (webhook at `/api/stripe/webhook.cfm`)
- **SMS**: Twilio via `twilio.cfc`
- **Database**: `payfrit` datasource
## Database
- **Production**: `payfrit` on db.payfrit.com (still uses OLD prefixed column names)
- **Development**: `payfrit_dev` on db.payfrit.com (migrated to clean names)
**Dev DB uses clean, unprefixed names.** PKs are always `ID`. FKs reference their parent table (e.g., `BusinessID`, `UserID`). No table-name prefixes on columns.
Key tables (dev schema):
| Table | PK | Key Columns |
|-------|----|-------------|
| Businesses | `ID` | `Name`, `UserID`, `Phone`, `BrandColor`, `TaxRate`, `OrderTypes`, `StripeAccountID`, `ParentBusinessID` |
| Users | `ID` | `FirstName`, `LastName`, `ContactNumber`, `EmailAddress`, `StripeCustomerId`, `UUID` |
| Orders | `ID` | `UUID`, `UserID`, `BusinessID`, `StatusID`, `OrderTypeID`, `ServicePointID`, `PaymentStatus` |
| Items | `ID` | `BusinessID`, `Name`, `Price`, `CategoryID`, `ParentItemID`, `IsActive`, `SortOrder`, `ImageExtension` |
| Categories | `ID` | `BusinessID`, `MenuID`, `ParentCategoryID`, `Name`, `OrderTypes`, `SortOrder` |
| OrderLineItems | `ID` | `ParentOrderLineItemID`, `OrderID`, `ItemID`, `StatusID`, `Price`, `Quantity`, `Remark` |
| Tasks | `ID` | `BusinessID`, `TaskTypeID`, `Title`, `Details`, `ClaimedByUserID`, `OrderID` |
| ServicePoints | `ID` | `BusinessID`, `Name`, `TypeID`, `Code`, `SortOrder`, `IsActive`, `BeaconID` |
| Beacons | `ID` | `BusinessID`, `UUID`, `Name`, `IsActive` |
| Menus | `ID` | `BusinessID`, `Name`, `IsActive` |
## Order Status Flow
1. **Cart** (StatusID 1) → 2. **Submitted** (2) → 3. **Preparing** (3) → 4. **Ready** (4) → 5. **Completed** (5)
## Receipt Page
- **URL**: `/receipt/index.cfm?UUID={orderUuid}`
- Separate `Application.cfm` — bypasses root layout
- Public (no auth) — secured by v4 UUID unguessability
- No internal data exposed (no platform fees, commissions, Stripe IDs)
## Performance Tracking
API requests track:
- `request._perf_start` (getTickCount)
- `request._perf_queryCount`
- `request._perf_queryTimeMs`
## Git Configuration
**Ignored**: `config/claude.json`, `*.tmp`, `*.bak`, `api/admin/_scripts/`
## Common Tasks
### Add new API endpoint
1. Create `.cfm` file in appropriate `api/` subdirectory
2. Public endpoints: add to allowlist in `api/Application.cfm`
3. Authenticated endpoints work automatically via `X-User-Token`
### Add new portal page
1. Create HTML file in `portal/`
2. Add routing/navigation in `portal.js`
### KDS customization
- Refresh interval: `config.refreshInterval` in `kds.js`
- Station filtering via URL params