Commit graph

384 commits

Author SHA1 Message Date
John Mizerek
ec3a15013b Add per-tab ApprovalMode override for member order approval
- open.cfm: accept optional ApprovalMode param (0=auto, 1=manual, NULL=business default)
- addOrder.cfm: check tab ApprovalMode first, fall back to business TabApprovalRequired
- getActive.cfm: return resolved ApprovalRequired in tab response

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 11:44:06 -08:00
John Mizerek
623b94cb3d Fix expireTabs cron: verify Stripe response before updating DB
The cron was marking tabs as 'captured' without checking if the Stripe
capture actually succeeded. Also, it never loaded the Stripe config
(api/config/stripe.cfm), so the API key was empty and all captures
were silently failing. Now includes the Stripe config, checks every
response status, and reverts the tab to open on capture failure.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 10:45:01 -08:00
John Mizerek
48fa6e4482 Fix missing UserID in submit.cfm order query
Tab-aware submit references qOrder.UserID but the SELECT didn't include it.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 22:53:17 -08:00
John Mizerek
9ed200d7ea Fix open tab: accept AuthAmountCents from Android client
Android sends cents, server was reading dollars only, falling back to default $150.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 21:43:52 -08:00
John Mizerek
4c0479db5c Add Open Tabs feature: tab APIs, presence tracking, shared tabs, cron, portal settings
- New api/tabs/ directory with 13 endpoints: open, close, cancel, get, getActive,
  addOrder, increaseAuth, addMember, removeMember, getPresence, approveOrder,
  rejectOrder, pendingOrders
- New api/presence/heartbeat.cfm for beacon-based user presence tracking
- New cron/expireTabs.cfm for idle tab expiry and presence cleanup
- Modified submit.cfm for tab-aware order submission (skip payment, update running total)
- Modified getOrCreateCart.cfm to auto-detect active tab and set TabID on new carts
- Modified webhook.cfm to handle tab capture events (metadata type=tab_close)
- Modified businesses/get.cfm and updateTabs.cfm with new tab config columns
- Updated portal tab settings UI with auth amounts, max members, approval toggle
- Added tab and presence endpoints to Application.cfm public allowlist

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 20:56:07 -08:00
John Mizerek
0e603b6cc9 Fix refresh button: add inline onclick and center icon
The addEventListener wasn't firing (likely cached JS). Added inline
onclick as reliable fallback and flexbox centering for the SVG icon.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-24 12:51:02 -08:00
John Mizerek
194eb4d205 Fix beacon Minor 0 not displaying in service points page
b.Minor is 0 for the first beacon which is falsy in JS.
Changed to null check so Minor: 0 displays correctly.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-24 12:47:20 -08:00
John Mizerek
57ef40f737 Add click handler for refresh button in portal
The refresh button in the top bar had no click handler attached.
Now it reloads the current page data when clicked.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-23 14:13:47 -08:00
John Mizerek
802d48f049 Fix tt_TaskTypes column names for dev database
Changed tt_TaskTypeID to ID in task type CRUD operations to match
the migrated dev database schema.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-23 14:13:19 -08:00
John Mizerek
d628f7eb50 Fix column name in listAllTypes: tt_TaskTypeID -> ID
The tt_TaskTypes table uses 'ID' not 'tt_TaskTypeID'.
This was causing "Failed to load services" in the portal.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-23 13:24:46 -08:00
John Mizerek
e8705287cc Fix JS syntax error: remove escaped backticks in addModifierOption
The escaped backticks (\`) were causing "invalid escape sequence" error,
breaking the entire script and making the Upload Files button non-functional.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-20 16:34:31 -08:00
John Mizerek
2c655a5963 Add business timezone support for menu scheduling
- Add getTimeInZone() and getDayInZone() helpers in Application.cfm
- Update items.cfm and getForBuilder.cfm to use business timezone
- Menu availability now correctly respects each business's timezone

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-20 12:09:36 -08:00
John Mizerek
9e5770f131 Add toISO8601() helper for UTC date formatting 2026-02-20 11:56:31 -08:00
John Mizerek
ea34f302ac Require TaxRate and PayfritFee to be configured - no fallbacks
Both values MUST be set per business. If not configured, the menu
API will return an error instead of silently using defaults.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-19 11:31:31 -08:00
John Mizerek
ed001fd0b0 Remove hardcoded 5% fee fallback, require Businesses.PayfritFee
If PayfritFee is not configured for a business, the payment intent
creation now errors instead of silently using 5%. This ensures fees
are always explicitly set per business.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-19 11:16:41 -08:00
John Mizerek
c17f624787 Fix Stripe webhook and add dev webhook secret
- Add SubmittedOn = COALESCE(SubmittedOn, NOW()) to webhook for KDS timer
- Add test mode webhook secret for dev.payfrit.com
- Keep live mode webhook secret for biz.payfrit.com

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-19 10:08:35 -08:00
John Mizerek
6a8ded9857 Add getPaymentConfig.cfm to public allowlist
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-18 20:25:30 -08:00
John Mizerek
bbfbbf1963 Update PaymentIntent amount if cart changed on retry
Moved fee calculation before PI check so we can compare amounts.
If existing PaymentIntent has different amount than current cart,
update it via Stripe API before returning.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-17 19:06:01 -08:00
John Mizerek
d0f0f86176 Reuse existing PaymentIntent instead of blocking on retry
When user abandons checkout and retries, retrieve the existing
PaymentIntent from Stripe. If still usable (requires_payment_method,
requires_confirmation, requires_action), return its client_secret.
If already succeeded, block with clear error. If terminal/canceled,
clear and create new one.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-17 19:01:17 -08:00
John Mizerek
29327c4a13 Add getPaymentConfig endpoint for Payment Sheet saved cards
Returns customer ID, ephemeral key, and publishable key needed for
Stripe Payment Sheet to display saved payment methods on iOS/Android.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-17 18:00:56 -08:00
John Mizerek
07c2f24d67 Add Stripe Customer creation to save payment methods
- Get user info (StripeCustomerId, email, name) when creating PaymentIntent
- Create Stripe Customer if user doesn't have one
- Add customer and setup_future_usage=off_session to PaymentIntent
- Cards are automatically saved after successful payment

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-17 17:56:13 -08:00
John Mizerek
9e2c3a8478 Fix CFML syntax error in webhook.cfm breaking all Stripe webhooks
The ## escape sequence was missing the closing # for variable interpolation,
causing 500 errors on all webhook requests. Fixed ##metaTipID# -> ###metaTipID#
and similar patterns.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-17 16:48:25 -08:00
John Mizerek
160144d40d Remove ExpectedAmountCents column reference (migration pending)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-17 14:31:30 -08:00
John Mizerek
695df9fc8e Fix createChat.cfm column name: TaskID → ID
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-17 11:22:47 -08:00
John Mizerek
fc310c35cf Fix cancel task to not cancel order, standardize OTP messages
- Cancel Task now leaves order untouched (customer can pay another way)
- Standardized SMS text to "Your Payfrit code is:" across all endpoints

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-17 11:11:37 -08:00
John Mizerek
43afe9ae8c Prevent duplicate cash tasks for same order
Check for existing active (uncompleted) cash task before creating
a new one. Prevents duplicate "Pay With Cash" tasks if order status
changes are triggered multiple times.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-17 09:41:58 -08:00
John Mizerek
7f4af8b910 Add CancelOrder option for cash tasks
When worker passes CancelOrder: true to complete.cfm:
- Skips all cash validation and financial processing
- Sets order status to 6 (cancelled)
- Completes the task normally
- Returns OrderCancelled: true in response

For when customer changes their mind about paying with cash.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-17 09:39:35 -08:00
John Mizerek
eb92042de5 Use business PayfritFee instead of hardcoded 5% in task order totals
Fixed complete.cfm, getDetails.cfm, listMine.cfm, listPending.cfm to pull
PayfritFee from Businesses table with 0.05 fallback if not set.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-17 09:20:18 -08:00
John Mizerek
0a08b1da3e Fix beacon sharding: use ServicePoints.BeaconMinor not BeaconHardware
Matches the lookup.cfm approach:
- UUID from BeaconShards
- Major from Businesses.BeaconMajor
- Minor from ServicePoints.BeaconMinor

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-16 20:10:04 -08:00
John Mizerek
957f494ba8 Get beacon info from BeaconHardware table
Looks up actual ShardUUID, Major, Minor from BeaconHardware
instead of deriving from Business/ServicePoint tables.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-16 20:06:38 -08:00
John Mizerek
dd7a4dda4a Return beacon sharding info (UUID, Major, Minor) for task completion
- UUID from BeaconShards via Business.BeaconShardID
- Major from Business.BeaconMajor
- Minor = ServicePointID

Replaces old beacon lookup via ServicePoints.BeaconID

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-16 20:02:19 -08:00
John Mizerek
06c4b99a66 Include ServicePointID when creating delivery tasks
Needed for beacon dwell auto-completion to work.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-16 19:32:37 -08:00
John Mizerek
2019b9ff43 Use proper task types for delivery/pickup tasks
- Looks up task type by name for the business instead of hardcoding ID
- Dine-in: 'Deliver to Table'
- Takeaway: 'Order Ready for Pickup'
- Delivery: 'Deliver to Address'

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-16 19:29:47 -08:00
John Mizerek
7caf4d60b0 Fix delivery task creation when other tasks exist for order
The duplicate check was preventing delivery task creation if ANY task
existed for the order (e.g., Cash or Chat tasks). Now only checks for
TaskTypeID=1 (delivery/pickup tasks) to allow proper task creation.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-16 19:24:59 -08:00
John Mizerek
aeeba3c6e5 Update about screen content
- Improved feature descriptions
- Updated main description
- Added "coming soon" note for delivery

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-16 18:36:15 -08:00
John Mizerek
01cb11dad3 fix: Cash task completion now triggers kitchen flow
When a cash task is completed, the order now goes to status 1 (submitted)
instead of directly to status 5 (complete). This allows the normal kitchen
flow to proceed: kitchen sees order → prepares → marks status 3 → delivery
task is auto-created.

Also sets PaymentStatus, PaymentCompletedOn, and SubmittedOn to match the
Stripe webhook behavior for paid orders.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-16 18:22:14 -08:00
John Mizerek
703a283d32 Enable cart recovery API with optional business filter
- getActiveCart now returns existing cart for user
- Optional BusinessID parameter to filter by specific business
- Used by Android app for cart recovery when scanning at a business

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-16 12:53:57 -08:00
John Mizerek
084e815c6c Stripe and beacon API updates
- createPaymentIntent: improved error handling
- webhook: updated payment processing
- resolve_business: minor fix

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-16 12:53:05 -08:00
John Pinkyfloyd
ec0f2dea6a Add Latitude/Longitude to businesses list response
iOS app needs lat/lng for client-side distance calculations.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-16 12:41:00 -08:00
John Pinkyfloyd
df903a9c75 Allow completing orphaned cash tasks without payment processing
Skip cash validation and processing for tasks with no linked order.
These are likely test tasks that were created before order linking.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-16 12:26:24 -08:00
John Pinkyfloyd
dc2d66b50b Add OrderTotalCents to task details for cash collection
Returns order total in cents as integer for Flutter Works app
to display exact cash amount due for cash payment tasks.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-16 12:01:46 -08:00
John Mizerek
c5614f0f50 Disable worker-rates-customer rating prompt temporarily
Rating UI not ready in Works app yet. Will re-enable when implemented.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-16 11:58:20 -08:00
John Pinkyfloyd
eebf231aad Fix column names in submitCash.cfm (PaymentAddedOn, TipAmount) 2026-02-16 11:50:57 -08:00
John Pinkyfloyd
175fdfb2b9 Add submitCash.cfm endpoint for cash payments
Creates Payment record with PaymentPaidInCash and links to order
Sets PaymentStatus = 'pending' and StatusID = 1 (submitted)
2026-02-16 11:49:06 -08:00
John Mizerek
5912784772 Create 'Pay With Cash' task when cash orders reach Final Prep
- Auto-create cash task when order status transitions to 3 (Final Prep)
  and has a pending cash payment (Payments.PaymentPaidInCash > 0)
- Task includes OrderID so Android can display OrderTotal
- Task title includes service point name when available
- Fix duplicate task check: was WHERE ID = ?, now WHERE OrderID = ?

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-16 11:27:16 -08:00
John Pinkyfloyd
c198b68ee0 Unified OTP flow - works for both login and signup 2026-02-15 17:13:18 -08:00
John Mizerek
4ae3b8b3d8 Fix receipt rounding to match Stripe charge exactly
Calculate total first without intermediate rounding, then work backwards for display values.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-15 17:11:00 -08:00
John Mizerek
e8b70ec372 Add processing fee to receipt, match actual charge
Shows: subtotal, tax, service fee, processing fee (Stripe 2.9% + $0.30), total

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-15 17:08:27 -08:00
John Mizerek
379de66e6f Use business PayfritFee instead of hardcoded 5%
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-15 17:06:26 -08:00
John Mizerek
3e1f344fc1 Fix receipt page: show service fee, fix tax calculation
- Always show service fee (was hidden from non-admin)
- Fix tax formula: /100 not /10000

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-15 17:05:01 -08:00