Commit graph

103 commits

Author SHA1 Message Date
John Pinkyfloyd
ca0b99b1c5 Fix attachDebug array initialization in setLineItem
Initialize request.attachDebug if not exists before appending

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-20 14:47:25 -07:00
John Mizerek
28c0de9f09 Remove IsInvertedGroup feature from all APIs, KDS, and portal
Feature cancelled — modifier wording handles the use case instead.
Removes IsInvertedGroup from SELECTs, JSON responses, RemovedDefaults
computation, and KDS/portal display logic. DB column left in place.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 17:53:09 -07:00
John Mizerek
75de1ab999 Revert "Fix inverted modifier groups auto-adding unchecked defaults"
This reverts commit 8440888024.
2026-03-11 17:31:09 -07:00
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
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
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 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
John Pinkyfloyd
5e01bcd989 Add error handling to inverted group check 2026-03-08 23:10:48 -07:00
John Pinkyfloyd
503754e248 Keep deselected inverted defaults in cart with Quantity=0
For inverted groups, when user deselects a default item, keep it in cart
with Quantity=0 instead of deleting. This allows cart to display "NO X".

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-08 23:05:44 -07:00
John Pinkyfloyd
f57d249fee Add ParentIsInvertedGroup to cart line items
Child items need to know if their parent group is inverted for proper
display logic (showing "NO X" instead of listing selected items).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-08 23:00:49 -07:00
John Pinkyfloyd
bae4293055 Add IsInvertedGroup to cart line items API response
Required for inverted modifier display (showing "NO X" for removed defaults
instead of listing all selected items).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-08 22:58:54 -07:00
John Pinkyfloyd
446addd66d Fix inverted modifier not removing from cart
When deselecting a modifier (IsSelected=false), Quantity was incorrectly
set to 1 instead of 0, preventing the removal logic from working.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-08 21:24:56 -07:00
John Mizerek
717d60d6e6 Add IsInvertedGroup support for modifier groups
When enabled on a modifier group, KDS and cart only show removed
defaults (e.g., "NO Mustard") instead of listing all selected items.
Useful for groups where all options are checked by default.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 18:14:19 -07:00
John Mizerek
6cdbff129f Add takeaway/pickup order support
- getOrCreateCart: only require ServicePointID for dine-in (OrderTypeID=1)
- get.cfm + items.cfm: return OrderTypes from Businesses table
- saveOrderTypes.cfm: new endpoint to save business order type config
- KDS: add PICKUP/DELIVERY badges on order cards
- Portal: add Order Types toggle card in settings (Dine-In always on, Takeaway toggle)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 10:45:06 -07:00
John Pinkyfloyd
b9755a1e72 Add role-aware cash routing and backend improvements
Staff cash goes to worker payout ledger, admin/manager cash deletes
pending payout and reverses withholding. Add RoleID to myBusinesses
response. Various order and webhook improvements.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 20:04:46 -08:00
John Mizerek
d822fcad5a feat: per-station item completion on KDS
Each station can mark their items done independently. When all
stations are done, the order auto-promotes to Ready (status 3)
and delivery/pickup tasks are created automatically.

- New markStationDone.cfm endpoint for per-station completion
- Extract task creation into shared _createOrderTasks.cfm include
- Add line item StatusID to listForKDS.cfm response
- KDS shows per-station "Mark Station Done" button when filtered
- Done items display with strikethrough and checkmark
- Manager view retains full manual control (no station selected)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 19:19:25 -08:00
John Mizerek
576c90fffd Fix DISTINCT ORDER BY error in KDS station-filtered query
MySQL rejects ORDER BY o.SubmittedOn when SELECT DISTINCT has
DATE_FORMAT(o.SubmittedOn) AS SubmittedOn. Use the alias instead.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 17:30:44 -08:00
John Mizerek
94b5bbbce1 KDS: per-station line item filtering with expand toggle
Backend returns all line items for every order (removes station
filter from sub-query). Frontend filters by station, showing only
relevant items by default. An expand toggle reveals other stations'
items dimmed at 35% opacity for full order context.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 15:30:59 -08:00
John Mizerek
c65cd8242b Round balance amounts to cents before applying
Prevents sub-cent precision (e.g. $0.883125) from accumulating in
BalanceApplied and payment records. All balance math now rounds to
nearest cent first.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 14:32:54 -08:00
John Mizerek
c580e6ec78 Auto-apply user balance on cash and card orders
Balance from cash change now silently reduces the amount owed on the
next order. For cash: deducted immediately in submitCash, reduces cash
the worker needs to collect (or skips cash task entirely if fully
covered). For card: reduces the Stripe PaymentIntent amount, deducted
in webhook on successful payment. Receipt shows "Balance applied" line.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 14:16:21 -08:00
John Mizerek
96c2ed3fc1 Fix cash payment fee: use real Payfrit platform fee, not 2.25% cash handling fee
submitCash.cfm: Calculate platform fee from subtotal * PayfritFee,
store in Orders.PlatformFee and Payments.PaymentPayfritsCut on submission.

complete.cfm: Replace bogus 2.25% cash transaction fee with the real
platform fee (customer fee + business fee = 2 × PayfritFee × subtotal).
Credit full Payfrit revenue to User 0. Record business fee in
PaymentPayfritNetworkFees.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 12:59:22 -08:00
John Mizerek
cb7e3b7fc6 fix: include PaymentFromCreditCard in cash payment INSERT
PaymentFromCreditCard column is NOT NULL with no default value,
causing INSERT to fail silently. Set to 0 for cash payments.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 12:44:53 -08:00
John Mizerek
8adac1a242 Fix submitCash.cfm for legacy Payments table columns
Payments table still uses old prefixed names (PaymentID as PK, no UUID
column, no PaymentTip column, required PaymentReceivedByUserID). Updated
INSERT to match actual production schema.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 11:29:40 -08:00
John Mizerek
61949586f5 Fix mismatched cfif/cftry tags in updateStatus.cfm
Extra </cfif> at line 243 had no matching opener. Was hidden by
Lucee's template cache until the Tomcat restart exposed it.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 13:01:49 -08:00
John Mizerek
4e0c2ee1bf Remove timezone conversion hacks — MySQL now runs in UTC
All servers (db, dev, biz) migrated to UTC:
- MySQL default-time-zone changed from America/Los_Angeles to +00:00
- All existing datetime data converted from Pacific to UTC
- JVM timezone set to UTC on dev and biz servers
- OS timezone set to UTC on all three servers

Removed CONVERT_TZ hack from listForKDS.cfm — data is natively UTC.
Simplified toISO8601() — no dateConvert needed since data is already UTC.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 12:37:30 -08:00
John Mizerek
4b35c27f75 Fix KDS timestamps: CONVERT_TZ from MySQL local time to UTC
MySQL is in America/Los_Angeles, not UTC. Use CONVERT_TZ to properly
convert to UTC before appending the Z suffix.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 12:20:39 -08:00
John Mizerek
4dfdd6ee8b Fix KDS UTC timestamps: format in SQL to bypass Lucee timezone shift
dateTimeFormat() converts to JVM local time before formatting, so
appending 'Z' was wrong. Use DATE_FORMAT in SQL instead since the DB
values are already UTC.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 12:18:37 -08:00
John Mizerek
453188d63f Fix KDS elapsed time by tagging SubmittedOn as UTC
DB stores timestamps in UTC but the API returned them without timezone
info, causing JS to parse them as local time. Append 'Z' suffix so
new Date() correctly interprets them as UTC.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 12:14:47 -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
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
9e5770f131 Add toISO8601() helper for UTC date formatting 2026-02-20 11:56:31 -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
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
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 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
a2be30b952 Add UUID to getDetail.cfm response for receipt link
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-09 18:54:02 -08:00
John Pinkyfloyd
d2985e193a Fix submit.cfm: remove ServicePoints join that was causing column name errors 2026-02-09 16:32:00 -08:00