payfrit-works/api/admin/migrateToCategories.cfm
John Mizerek 634148f727 Add Categories table support, KDS station selection, and portal fixes
Categories Migration:
- Add ItemCategoryID column to Items table (api/admin/addItemCategoryColumn.cfm)
- Migration script to populate Categories from unified schema (api/admin/migrateToCategories.cfm)
- Updated items.cfm and getForBuilder.cfm to use Categories table with fallback

KDS Station Selection:
- KDS now prompts for station selection on load (Kitchen, Bar, or All Stations)
- Station filter persists in localStorage
- Updated listForKDS.cfm to filter orders by station
- Simplified KDS UI with station badge in header

Portal Improvements:
- Fixed drag-and-drop in station assignment (proper event propagation)
- Fixed Back button links to use BASE_PATH for local development
- Added console logging for debugging station assignment
- Order detail API now calculates Subtotal, Tax, Tip, Total properly

Admin Tools:
- setupBigDeansStations.cfm - Create Kitchen and Bar stations for Big Dean's

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 15:31:45 -08:00

134 lines
4.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>
/**
* Migrate Unified Schema to Categories
*
* This script:
* 1. Finds all "category" Items (ParentID=0, not templates, not collapsible)
* 2. Creates corresponding entries in Categories table
* 3. Updates child Items with the new CategoryID
*
* GET: ?BusinessID=27 (or all if not specified)
*/
response = { "OK": false, "BusinessesProcessed": [], "Errors": [] };
try {
// Get BusinessID from URL if specified
businessFilter = "";
if (structKeyExists(url, "BusinessID") && val(url.BusinessID) > 0) {
businessFilter = val(url.BusinessID);
}
// Find all businesses with items in unified schema
if (len(businessFilter)) {
qBusinesses = queryExecute("
SELECT DISTINCT ItemBusinessID as BusinessID
FROM Items
WHERE ItemBusinessID = :bid AND ItemBusinessID > 0
", { bid: businessFilter }, { datasource: "payfrit" });
} else {
qBusinesses = queryExecute("
SELECT DISTINCT ItemBusinessID as BusinessID
FROM Items
WHERE ItemBusinessID > 0
", {}, { datasource: "payfrit" });
}
for (biz in qBusinesses) {
bizId = biz.BusinessID;
bizResult = { "BusinessID": bizId, "CategoriesCreated": 0, "ItemsUpdated": 0 };
try {
// Find category-like Items (parent=0, not collapsible, has children, not in template links)
qCategoryItems = queryExecute("
SELECT DISTINCT
p.ItemID,
p.ItemName,
p.ItemSortOrder
FROM Items p
INNER JOIN Items c ON c.ItemParentItemID = p.ItemID
WHERE p.ItemBusinessID = :bizId
AND p.ItemParentItemID = 0
AND (p.ItemIsCollapsible = 0 OR p.ItemIsCollapsible IS NULL)
AND NOT EXISTS (
SELECT 1 FROM ItemTemplateLinks tl WHERE tl.TemplateItemID = p.ItemID
)
ORDER BY p.ItemSortOrder, p.ItemName
", { bizId: bizId }, { datasource: "payfrit" });
sortOrder = 0;
for (catItem in qCategoryItems) {
// Check if category already exists for this business with same name
qExisting = queryExecute("
SELECT CategoryID FROM Categories
WHERE CategoryBusinessID = :bizId AND CategoryName = :name
", { bizId: bizId, name: left(catItem.ItemName, 30) }, { datasource: "payfrit" });
if (qExisting.recordCount == 0) {
// Get next CategoryID
qMaxId = queryExecute("
SELECT COALESCE(MAX(CategoryID), 0) + 1 as nextId FROM Categories
", {}, { datasource: "payfrit" });
newCatId = qMaxId.nextId;
// Create new category with explicit ID
queryExecute("
INSERT INTO Categories
(CategoryID, CategoryBusinessID, CategoryParentCategoryID, CategoryName, CategorySortOrder, CategoryAddedOn)
VALUES (:catId, :bizId, 0, :name, :sortOrder, NOW())
", {
catId: newCatId,
bizId: bizId,
name: left(catItem.ItemName, 30),
sortOrder: sortOrder
}, { datasource: "payfrit" });
bizResult.CategoriesCreated++;
} else {
newCatId = qExisting.CategoryID;
}
// Update all children of this category Item to have the new CategoryID
queryExecute("
UPDATE Items
SET ItemCategoryID = :catId
WHERE ItemParentItemID = :parentId
AND ItemBusinessID = :bizId
", {
catId: newCatId,
parentId: catItem.ItemID,
bizId: bizId
}, { datasource: "payfrit" });
qUpdated = queryExecute("SELECT ROW_COUNT() as cnt", {}, { datasource: "payfrit" });
bizResult.ItemsUpdated += qUpdated.cnt;
sortOrder++;
}
arrayAppend(response.BusinessesProcessed, bizResult);
} catch (any bizErr) {
arrayAppend(response.Errors, {
"BusinessID": bizId,
"Error": bizErr.message
});
}
}
response["OK"] = true;
response["TotalBusinesses"] = qBusinesses.recordCount;
} catch (any e) {
response["ERROR"] = "server_error";
response["MESSAGE"] = e.message;
response["DETAIL"] = e.detail;
}
writeOutput(serializeJSON(response));
</cfscript>