Commit graph

522 commits

Author SHA1 Message Date
John Mizerek
8440888024 Fix inverted modifier groups auto-adding unchecked defaults
attachDefaultChildren now detects IsInvertedGroup=1 on parent items
and skips auto-adding defaults. The Android client explicitly sends
only the modifiers the user kept checked, so auto-adding was
re-inserting items the user had unchecked (e.g., Mustard).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 17:15:25 -07:00
John Mizerek
a8257b2509 Fix inverted modifier groups in KDS
The inverted group header item isn't always an order line item itself,
so RemovedDefaults was never computed. Now detects inverted groups
via children's ParentIsInvertedGroup flag and attaches RemovedDefaults
to the first child as a proxy. KDS JS handles both patterns.

Also skips showing default modifiers from inverted groups since those
are represented by "NO removed-item" instead.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 17:06:18 -07:00
John Mizerek
c6767eb2c4 KDS: show all selected modifiers including defaults
Was filtering out IsCheckedByDefault modifiers, which hid all
toppings/options on orders where the customer kept the defaults
(e.g. Bay Cities sandwiches). Inverted groups still handled
separately with "NO" prefix for removed defaults.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 16:57:17 -07:00
John Mizerek
6c41dedd5d Bump business list limit from 20 to 50
23 businesses were being cut to 20 when sorted alphabetically (no location),
hiding Win~Dow Venice and other names near end of alphabet.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 14:32:52 -07:00
John Mizerek
5328fda65b Add DINE-IN badge to KDS order cards for consistency
Pickup and Delivery had colored badges but Dine-In did not. Added
blue DINE-IN badge matching the existing badge style.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 13:39:23 -07:00
John Mizerek
800471f249 KDS: show items with no station assignment in every station filter
Items with NULL StationID now appear in all station views instead of
being hidden when a specific station is selected.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 12:19:52 -07:00
John Mizerek
d80d4bd4c4 Reset KDS station filter on business change, add default Kitchen station
KDS was keeping the station filter from a previous business in
localStorage, causing orders to be hidden when switching businesses.
Now tracks businessId and resets station selection on change.

New businesses also get a default "Kitchen" station so the KDS works
out of the box.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 12:17:51 -07:00
John Mizerek
c79a750a50 Show full order total on receipt, payment method below
Grand total now always shows the actual order amount. Balance and
payment method shown as informational lines underneath instead of
subtracting balance from the total.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 12:08:18 -07:00
John Mizerek
acdb28a0d0 Fix receipt for balance-only payments and add tip display
Receipt was treating balance-only orders as card payments, adding
Stripe processing fees that inflated the total. Now checks
PaymentFromCreditCard to determine if card fees apply. Also adds
tip line and includes TipAmount in total calculation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 12:05:42 -07:00
John Mizerek
15e76c7170 Fix timezone display: append Z suffix to UTC dates in API responses
JS new Date() was parsing dates without Z as local time, showing UTC
values as-is. Adding Z suffix tells JS the dates are UTC so it converts
to the user's local timezone automatically.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 11:59:43 -07:00
John Mizerek
214c65adb2 Fix receipt page: Payments PK is PaymentID not ID
Payments table still uses old prefixed column names.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 11:51:25 -07:00
John Mizerek
bc52a0242f Fix saveOrderTypes: add X-Business-ID header for auth
Application.cfm requires request.BusinessID from session or header.
The fetch was only sending it in the POST body which the auth layer
doesn't read.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 20:28:17 -07:00
John Mizerek
b57cef8838 Guard saveOrderTypes against missing businessId
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 20:11:54 -07:00
John Mizerek
30e192e738 Fix saveOrderTypes: wrong method name and onchange firing during load
- showToast → toast (correct method name) across all settings methods
- Clear onchange before setting .checked to prevent save during load

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 20:07:44 -07:00
John Mizerek
d947685bbc Bump portal.js cache version to v14
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 19:52:51 -07:00
John Mizerek
87eb5fa1f0 Fix takeaway/pickup toggle not saving in Firefox
Wire onchange listener via JS instead of inline attribute,
matching the hiring toggle pattern. The zero-sized hidden
checkbox wasn't firing inline onchange reliably.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 18:07:54 -07:00
John Mizerek
dfe2313ec5 Add eyedropper color picker to brand color modal
Uses the native EyeDropper API (Chrome/Edge) to pick colors from
anywhere on screen. Button only shows in supported browsers.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 17:29:42 -07:00
John Mizerek
eda2ce2db4 Fix DoorDash GraphQL: remove unused variable declarations
shouldFetchPresetCarousels and shouldFetchStoreLiteData were declared
in the query signature but not used in the body, causing 400 errors.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 13:17:00 -07:00
John Mizerek
59dfd602cf Use production GraphQL query for DoorDash modifier extraction
The minimal query was rejected by DoorDash's schema validation.
Replaced with production-matching query including OptionListFragment,
OptionFragment, and NestedExtrasFragment.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 13:14:11 -07:00
John Mizerek
2cf5039c0f DoorDash modifiers: direct GraphQL API calls instead of clicking
Instead of clicking each menu item (broken by virtual scrolling),
extract item IDs from embedded JSON and make direct fetch() calls
to the itemPage GraphQL endpoint. 5 concurrent requests per batch.
Much faster and 100% reliable - no DOM interaction needed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 13:11:03 -07:00
John Mizerek
f5974a5fa2 Improve DoorDash modifier extraction: pass item names to Playwright
- Pass extracted item names via temp JSON file so Playwright knows exactly
  what to click instead of guessing from DOM selectors (7 → 171 items)
- Use TreeWalker for exact text matching and aggressive scrolling
- Better price parsing: handle cents (int), dollars (string), displayPrice
- Improved modal dismissal with overlay click fallback

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 13:02:27 -07:00
John Mizerek
b14f26ed47 Add DoorDash modifier extraction via stealth Playwright
- New doordash-modifiers.js: stealth Playwright script that clicks each
  menu item on a DoorDash page, captures itemPage GraphQL responses,
  and extracts optionLists (modifier groups with options and prices)
- Wire modifier extraction into DoorDash fast-path in analyzeMenuUrl.cfm:
  after parsing items/categories, runs modifier script and maps results
- Improved business info extraction: address, phone, and hours now use
  position-based parsing of StoreHeaderAddress, StoreHeaderPhoneNumber,
  and StoreOperationHoursRange embedded data (fixes intermittent missing info)
- Add playwright-extra and stealth plugin to package.json

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 12:58:00 -07:00
John Mizerek
8be3a3d802 Fix DoorDash image extraction: MenuPageItem uses imageUrl not imgUrl
StorePageCarouselItem uses imgUrl, but MenuPageItem uses imageUrl.
This gives ~540 item images instead of 26.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 12:32:01 -07:00
John Mizerek
a830a0820a Fix DoorDash parser: use find() loops instead of listToArray
listToArray treats delimiter as individual chars, not a string.
Rewritten to use position-based find() traversal for proper
multi-character delimiter splitting.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 12:23:21 -07:00
John Mizerek
33040c9cd3 Rewrite DoorDash fast-path: use MenuPageItemList for full menu
- Extract items from MenuPageItemList (171 items) instead of StorePageCarouselItem (54)
- Categories already mapped to items via MenuPageItemList sections
- Cross-reference images from carousel entries by item name
- No need for Claude category assignment - data already structured

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 12:02:04 -07:00
John Mizerek
67e2079550 Add DoorDash/order.online fast-path parser
Extract menu data directly from embedded JSON in DoorDash HTML:
- Categories from MenuBookCategory entries
- Items with names, descriptions, prices, and image URLs from StorePageCarouselItem
- Business info from page title and StoreHeaderAddress
- Uses Claude to assign items to categories
- Upgrades image URLs to 600px for better quality

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 11:44:24 -07:00
John Mizerek
dd2a508680 Add playwright scripts to git
Previously only lived on servers at /opt/playwright/. Now tracked in repo.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 11:22:34 -07:00
John Mizerek
f58d567fb4 Fix DoorDash image import: scroll page in Playwright to trigger lazy-loaded images
- Update render.js on dev server to scroll page before capturing images
- Increase Playwright wait from 4s to 5s and timeout from 90s to 120s
- Upsize DoorDash CDN thumbnails from 150px to 600px when downloading

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 11:20:10 -07:00
John Mizerek
9a28091601 Handle struct types in item category and modifiers during merge
Claude sometimes returns category or modifiers as objects instead
of strings. Added isSimpleValue checks to prevent cast errors.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 21:04:34 -07:00
John Mizerek
d8a308a03e Increase Claude API timeout from 120s to 300s for image analysis
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 20:58:15 -07:00
John Mizerek
93a2738ae1 Increase max_tokens from 8192 to 16384 for menu image analysis
Claude response was being truncated mid-JSON for larger menus,
causing parse errors. The Lazy Daisy menu needed >8192 tokens.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 20:46:54 -07:00
John Mizerek
c6c189b0fa Save raw Claude response to file and dump char codes for debugging
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 20:41:27 -07:00
John Mizerek
607c62051e Show JSON content around failure position for debugging
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 20:38:36 -07:00
John Mizerek
7d23cb5487 Fix JSON parsing in analyzeMenuImages for PDF menu imports
The PDF upload goes to analyzeMenuImages.cfm (not analyzeMenuUrl.cfm).
Added control character cleaning, smart quote replacement, and Jackson
fallback parser with error handling.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 19:45:21 -07:00
John Mizerek
8ac6800d47 Use Jackson parser via file for Claude JSON response
Lucee's deserializeJSON fails on certain Claude outputs and the error
bypasses inner cftry/cfcatch. Parse via Jackson from file instead.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 19:37:42 -07:00
John Mizerek
a5c0d55aa8 Fix JSON error handler and save raw Claude response for debugging
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 19:32:50 -07:00
John Mizerek
1ca958d11f Add debug char dump around JSON parse failure position
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 19:28:26 -07:00
John Mizerek
945ab6a919 Add RequiresServicePoint flag to task types API
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 16:50:02 -07:00
John Mizerek
4240fe76cc Harden JSON parsing for Claude API responses
- Add smart quote/dash replacement for PDF-sourced text
- Add Jackson fallback parser for when Lucee's deserializeJSON fails
- Strengthen prompt to request properly escaped JSON
- Clean control characters more selectively

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 13:31:03 -07:00
John Mizerek
d288b2b71c Add JSON parse error debug logging in saveWizard
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 13:15:19 -07:00
John Mizerek
fc358b53c7 Strip control characters from JSON body in saveWizard
Lucee's deserializeJSON chokes on control characters in description
fields that JSON.stringify escapes but Lucee can't parse.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 13:11:31 -07:00
John Pinkyfloyd
639d789da1 Add debug info to cart and setLineItem
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-09 10:30:02 -07:00
John Pinkyfloyd
6af7e22b03 Fix debug array initialization
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-09 10:20:02 -07:00
John Pinkyfloyd
120930db4c Add debug logging for deselect flow
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-09 10:11:54 -07:00
John Pinkyfloyd
65f236268c Fix attachDefaultChildren to recurse through modifier groups
Default-checked items nested inside modifier groups were not being found
because the function only looked one level deep. Now it recurses through
all child items to find defaults at any depth.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-09 10:04:14 -07:00
John Pinkyfloyd
0451c604e6 Fix CFML scoping error - remove var keyword outside function
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-09 10:00:18 -07:00
John Pinkyfloyd
50307efa8d Fix cart item lookup to use orderLineItemId directly
- Add IsDeleted=0 filter to existing item search query
- Add support for OrderLineItemID parameter for direct item targeting
- Fixes duplicate items being created on quantity increment
- Fixes item deletion not working due to finding wrong/deleted records

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-09 09:25:20 -07:00
John Pinkyfloyd
fc9bbd78be Only keep Quantity=0 for modifiers, not root items 2026-03-09 09:13:55 -07:00
John Pinkyfloyd
029279658d Keep default-checked items with Quantity=0 when deselected
For inverted display: when user deselects a default-checked item, keep it
in cart with Quantity=0 instead of deleting. Cart displays "NO X" for these.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-09 09:11:15 -07:00
John Pinkyfloyd
6ffc77fcaf Revert inverted deselect logic - back to simple delete 2026-03-09 07:34:39 -07:00