payfrit-works/api/admin/copyDrinksToBigDeans.cfm
John Mizerek e757a4140b Add drink modifiers, unified schema improvements, and portal fixes
Menu System:
- Unified schema with Categories table integration
- Virtual category headers with proper parent ID remapping
- Filter out legacy category headers when using new schema
- Add drink modifier endpoints for Fountain Soda (Size/Flavor)

Admin Tools:
- addDrinkModifiers.cfm - Add size/flavor modifiers to drinks
- copyDrinksToBigDeans.cfm - Copy drink items between businesses
- debugDrinkStructure.cfm - Debug drink item hierarchy

Portal:
- Station assignment improvements with better drag-drop
- Enhanced debug task viewer

API Fixes:
- Application.cfm updated with new admin endpoint allowlist
- setLineItem.cfm formatting cleanup
- listMine.cfm task query fixes

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 20:30:58 -08:00

141 lines
5.9 KiB
Text

<cfsetting showdebugoutput="false">
<cfsetting enablecfoutputonly="true">
<cfcontent type="application/json; charset=utf-8" reset="true">
<cfheader name="Cache-Control" value="no-store">
<cfscript>
/**
* Copy drinks from In-N-Out (BusinessID 17) to Big Dean's (BusinessID 27)
*/
response = { "OK": false, "ItemsCreated": 0, "CategoryCreated": false };
try {
bigDeansBusinessId = 27;
// First, check if Big Dean's has a Beverages/Drinks category
qExistingCat = queryExecute("
SELECT CategoryID, CategoryName FROM Categories
WHERE CategoryBusinessID = :bizId AND (CategoryName LIKE '%Drink%' OR CategoryName LIKE '%Beverage%')
", { bizId: bigDeansBusinessId }, { datasource: "payfrit" });
if (qExistingCat.recordCount > 0) {
drinksCategoryId = qExistingCat.CategoryID;
response["CategoryNote"] = "Using existing category: " & qExistingCat.CategoryName;
} else {
// Create a new Beverages category for Big Dean's
qMaxCat = queryExecute("SELECT COALESCE(MAX(CategoryID), 0) + 1 as nextId FROM Categories", {}, { datasource: "payfrit" });
drinksCategoryId = qMaxCat.nextId;
qMaxSort = queryExecute("
SELECT COALESCE(MAX(CategorySortOrder), 0) + 1 as nextSort FROM Categories WHERE CategoryBusinessID = :bizId
", { bizId: bigDeansBusinessId }, { datasource: "payfrit" });
queryExecute("
INSERT INTO Categories (CategoryID, CategoryBusinessID, CategoryParentCategoryID, CategoryName, CategorySortOrder, CategoryAddedOn)
VALUES (:catId, :bizId, 0, 'Beverages', :sortOrder, NOW())
", {
catId: drinksCategoryId,
bizId: bigDeansBusinessId,
sortOrder: qMaxSort.nextSort
}, { datasource: "payfrit" });
response["CategoryCreated"] = true;
response["CategoryNote"] = "Created new category: Beverages (ID: " & drinksCategoryId & ")";
}
// Drinks to add (from In-N-Out)
drinks = [
{ name: "Fountain Soda", price: 2.10, desc: "Coca-Cola, Diet Coke, Sprite, Fanta Orange, Lemonade" },
{ name: "Bottled Water", price: 1.50, desc: "" },
{ name: "Iced Tea", price: 2.25, desc: "Freshly brewed" },
{ name: "Coffee", price: 1.95, desc: "Hot brewed coffee" },
{ name: "Hot Cocoa", price: 2.25, desc: "" },
{ name: "Milk", price: 1.25, desc: "2% milk" },
{ name: "Orange Juice", price: 2.50, desc: "Fresh squeezed" },
{ name: "Milkshake", price: 4.95, desc: "Chocolate, Vanilla, or Strawberry - made with real ice cream", requiresChild: 1 }
];
itemsCreated = 0;
for (drink in drinks) {
// Check if item already exists
qExists = queryExecute("
SELECT ItemID FROM Items
WHERE ItemBusinessID = :bizId AND ItemName = :name AND ItemCategoryID = :catId
", { bizId: bigDeansBusinessId, name: drink.name, catId: drinksCategoryId }, { datasource: "payfrit" });
if (qExists.recordCount == 0) {
// Get next ItemID
qMaxItem = queryExecute("SELECT COALESCE(MAX(ItemID), 0) + 1 as nextId FROM Items", {}, { datasource: "payfrit" });
newItemId = qMaxItem.nextId;
queryExecute("
INSERT INTO Items (
ItemID, ItemBusinessID, ItemCategoryID, ItemParentItemID,
ItemName, ItemDescription, ItemPrice, ItemIsActive,
ItemSortOrder, ItemIsCollapsible, ItemRequiresChildSelection,
ItemAddedOn
) VALUES (
:itemId, :bizId, :catId, 0,
:name, :desc, :price, 1,
:sortOrder, 0, :requiresChild,
NOW()
)
", {
itemId: newItemId,
bizId: bigDeansBusinessId,
catId: drinksCategoryId,
name: drink.name,
desc: structKeyExists(drink, "desc") ? drink.desc : "",
price: drink.price,
sortOrder: itemsCreated,
requiresChild: structKeyExists(drink, "requiresChild") ? drink.requiresChild : 0
}, { datasource: "payfrit" });
itemsCreated++;
// If milkshake, add flavor options
if (drink.name == "Milkshake") {
flavors = ["Chocolate", "Vanilla", "Strawberry"];
flavorSort = 0;
for (flavor in flavors) {
qMaxOpt = queryExecute("SELECT COALESCE(MAX(ItemID), 0) + 1 as nextId FROM Items", {}, { datasource: "payfrit" });
queryExecute("
INSERT INTO Items (
ItemID, ItemBusinessID, ItemCategoryID, ItemParentItemID,
ItemName, ItemDescription, ItemPrice, ItemIsActive,
ItemSortOrder, ItemIsCollapsible, ItemIsCheckedByDefault,
ItemAddedOn
) VALUES (
:itemId, :bizId, 0, :parentId,
:name, '', 0, 1,
:sortOrder, 0, :isDefault,
NOW()
)
", {
itemId: qMaxOpt.nextId,
bizId: bigDeansBusinessId,
parentId: newItemId,
name: flavor,
sortOrder: flavorSort,
isDefault: (flavor == "Chocolate") ? 1 : 0
}, { datasource: "payfrit" });
flavorSort++;
}
}
}
}
response["OK"] = true;
response["ItemsCreated"] = itemsCreated;
response["CategoryID"] = drinksCategoryId;
} catch (any e) {
response["ERROR"] = "server_error";
response["MESSAGE"] = e.message;
response["DETAIL"] = e.detail;
}
writeOutput(serializeJSON(response));
</cfscript>