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>
This commit is contained in:
John Mizerek 2026-03-11 17:06:18 -07:00
parent c6767eb2c4
commit a8257b2509
2 changed files with 20 additions and 11 deletions

View file

@ -126,7 +126,8 @@
i.IsCheckedByDefault,
i.IsInvertedGroup,
i.StationID,
parent.Name AS ItemParentName
parent.Name AS ItemParentName,
COALESCE(parent.IsInvertedGroup, 0) AS ParentIsInvertedGroup
FROM OrderLineItems oli
INNER JOIN Items i ON i.ID = oli.ItemID
LEFT JOIN Items parent ON parent.ID = i.ParentItemID
@ -149,15 +150,20 @@
"ItemParentName": qLineItems.ItemParentName,
"IsCheckedByDefault": qLineItems.IsCheckedByDefault,
"IsInvertedGroup": qLineItems.IsInvertedGroup,
"ParentIsInvertedGroup": qLineItems.ParentIsInvertedGroup,
"StationID": qLineItems.StationID,
"StatusID": val(qLineItems.StatusID)
})>
</cfloop>
<!--- For inverted modifier groups, compute removed defaults --->
<!--- The inverted group header may not be an order line item itself,
so we detect inverted groups by finding children whose parent item is inverted --->
<cfset invertedGroupsSeen = {}>
<cfloop array="#lineItems#" index="li">
<cfif li.IsInvertedGroup>
<!--- This is an inverted modifier group in the order — find defaults NOT ordered --->
<cfif li.ParentIsInvertedGroup AND NOT structKeyExists(invertedGroupsSeen, li.ParentItemID)>
<!--- First child of this inverted group — compute removed defaults once --->
<cfset invertedGroupsSeen[li.ParentItemID] = true>
<cfset qRemovedDefaults = queryTimed("
SELECT i.Name
FROM Items i
@ -170,15 +176,17 @@
)
ORDER BY i.SortOrder
", [
{ value = li.ItemID, cfsqltype = "cf_sql_integer" },
{ value = li.ParentItemID, cfsqltype = "cf_sql_integer" },
{ value = qOrders.ID, cfsqltype = "cf_sql_integer" },
{ value = li.OrderLineItemID, cfsqltype = "cf_sql_integer" }
{ value = li.ParentOrderLineItemID, cfsqltype = "cf_sql_integer" }
], { datasource = "payfrit" })>
<cfset removedNames = []>
<cfloop query="qRemovedDefaults">
<cfset arrayAppend(removedNames, qRemovedDefaults.Name)>
</cfloop>
<!--- Attach RemovedDefaults to the first child so the JS can find it --->
<cfset li["RemovedDefaults"] = removedNames>
<cfset li["IsInvertedGroupProxy"] = true>
</cfif>
</cfloop>

View file

@ -408,20 +408,21 @@ function renderAllModifiers(modifiers, allItems) {
function collectLeafModifiers(mods, depth = 0) {
mods.forEach(mod => {
// Inverted groups: show removed defaults with "NO" prefix instead of listing all selected defaults
if (mod.IsInvertedGroup || mod.ISINVERTEDGROUP) {
// Check both the item itself (if group header is in order) and proxy (first child carries the data)
const isInverted = mod.IsInvertedGroup || mod.ISINVERTEDGROUP || mod.IsInvertedGroupProxy || mod.ISINVERTEDGROUPPROXY;
if (isInverted) {
const removed = mod.RemovedDefaults || mod.REMOVEDDEFAULTS || [];
if (removed.length > 0) {
const groupName = mod.ItemParentName || mod.Name;
removed.forEach(name => {
leafModifiers.push({ mod: { Name: 'NO ' + name, ItemParentName: mod.Name }, path: [] });
leafModifiers.push({ mod: { Name: 'NO ' + name, ItemParentName: groupName }, path: [] });
});
}
return;
}
// Skip default modifiers only inside non-inverted groups
// (Inverted groups are already handled above with "NO" prefix)
// For regular groups, show all selected modifiers including defaults
// Skip default modifiers inside inverted groups — handled above with "NO" prefix
if (mod.IsCheckedByDefault && (mod.ParentIsInvertedGroup || mod.PARENTISINVERTEDGROUP)) return;
const children = allItems.filter(item => item.ParentOrderLineItemID === mod.OrderLineItemID);
if (children.length === 0) {