- 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>
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>
- 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>
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>
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>
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>
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>
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>
- 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>
- 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>
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>
- Improved feature descriptions
- Updated main description
- Added "coming soon" note for delivery
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
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>
- 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>
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>
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>
- 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>
This allows beacons to use any Eddystone-UID configuration where:
- Namespace (10 bytes) matches first 20 hex chars of shard UUID
- Instance bytes encode Major/Minor for business/service point lookup
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Tax rate: Use Zippopotam (free, no key) to get state, then lookup
from built-in state+local rate tables instead of API Ninjas
- Prices: Extract prices from Toast __OO_STATE__ MenuItem objects
when visible HTML prices are missing
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When business info step loads with a ZIP code, automatically looks up
the combined sales tax rate and pre-fills the field. User can still
edit if needed. Field gets light green background to indicate auto-fill.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Extract UUID folder path from URL instead of using getDirectoryFromPath
- Old logic was broken: listLast on path ending with / returned empty string
- This caused the code to go up one level too far
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Scan extracted ZIP for image files (jpg, png, gif, webp)
- Skip small files (<10KB, likely icons) and _files folder assets
- Send up to 3 images to Claude for business info extraction
- Merge extracted name, address, phone, hours, brandColor
- Only fills in fields not already found from HTML
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Extract directory and scan all .htm/.html files recursively
- Look for business name in title tags (skip generic titles)
- Extract street addresses with regex patterns
- Extract phone numbers
- Check __OO_STATE__ in other pages for Restaurant data
- Merge found info into toastBusiness (first found wins)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The __OO_STATE__ parsing was only extracting images, not the group names
as categories. Now extracts category names from menu.groups and maps
items to their proper categories.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Toast extraction was finding items but no h2.groupHeader categories,
leaving items ungrouped. showItemsStep() then rendered no checkboxes,
and confirmItems() filtered out all items (empty checkedIds set).
Now adds a default "Menu" category when items exist but categories is empty.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Added multiple fallback methods to extract business name:
1. Title tag with Toast-specific parsing
2. og:title and og:site_name meta tags
3. Header elements with restaurant/location classes
4. First h1 tag as last resort
Also added address and phone extraction from visible HTML.
Added summary logging of business info keys found.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Log all top-level keys in __OO_STATE__ to diagnose why Restaurant
key isn't being found
- Extract business name from HTML title tag as fallback
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Look for Restaurant: keys and extract name, location (address, city,
state, zip), phone, and brandColor for the wizard business info step.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Define basePath before Toast parsing block so image URLs can be
properly constructed for local file uploads.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Extract items from visible HTML instead of just __OO_STATE__ JSON
- Parse headerText spans for item names, price spans for prices
- Extract images from Menu_files/ src attributes
- Fall back to simpler headerText matching if block parsing fails
- Also extract images from __OO_STATE__ and match to items by name
- Fixes issue where only 116 items extracted instead of 163+
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Skip Claude AI for Toast menus - parse the embedded JSON directly.
This extracts all items, categories, and images from the structured
__OO_STATE__ data, which is faster and more complete than AI extraction.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>