Replace queryExecute with queryTimed across all endpoints for perf tracking

Converts 200+ endpoint files to use queryTimed() wrapper which tracks
DB query count and execution time. Restores perf dashboard files that
were accidentally moved to _scripts/. Includes portal UI updates.
This commit is contained in:
John 2026-02-02 00:28:37 -08:00
parent f52d14bb7e
commit 16a3b7c9a3
206 changed files with 6275 additions and 5754 deletions

View file

@ -103,6 +103,8 @@ if (len(request._api_path)) {
if (findNoCase("/api/auth/verifyOTP.cfm", request._api_path)) request._api_isPublic = true;
if (findNoCase("/api/auth/loginOTP.cfm", request._api_path)) request._api_isPublic = true;
if (findNoCase("/api/auth/verifyLoginOTP.cfm", request._api_path)) request._api_isPublic = true;
if (findNoCase("/api/auth/sendLoginOTP.cfm", request._api_path)) request._api_isPublic = true;
if (findNoCase("/api/auth/verifyEmailOTP.cfm", request._api_path)) request._api_isPublic = true;
if (findNoCase("/api/auth/completeProfile.cfm", request._api_path)) request._api_isPublic = true;
if (findNoCase("/api/businesses/list.cfm", request._api_path)) request._api_isPublic = true;

View file

@ -55,7 +55,7 @@ try {
// If setting as default, clear other defaults first (for same type)
if (setAsDefault) {
queryExecute("
queryTimed("
UPDATE Addresses
SET IsDefaultDelivery = 0
WHERE UserID = :userId
@ -68,11 +68,11 @@ try {
}
// Get next AddressID
qNext = queryExecute("SELECT IFNULL(MAX(ID), 0) + 1 AS NextID FROM Addresses", {}, { datasource: "payfrit" });
qNext = queryTimed("SELECT IFNULL(MAX(ID), 0) + 1 AS NextID FROM Addresses", {}, { datasource: "payfrit" });
newAddressId = qNext.NextID;
// Insert new address
queryExecute("
queryTimed("
INSERT INTO Addresses (
ID,
UserID,
@ -117,7 +117,7 @@ try {
}, { datasource: "payfrit" });
// Get state info for response
qState = queryExecute("SELECT Abbreviation as StateAbbreviation, Name as StateName FROM tt_States WHERE ID = :stateId", {
qState = queryTimed("SELECT Abbreviation as StateAbbreviation, Name as StateName FROM tt_States WHERE ID = :stateId", {
stateId: { value: stateId, cfsqltype: "cf_sql_integer" }
}, { datasource: "payfrit" });

View file

@ -40,7 +40,7 @@ if (structKeyExists(request, "UserID") && isNumeric(request.UserID) && request.U
userToken = getHeader("X-User-Token");
if (len(userToken)) {
try {
qTok = queryExecute(
qTok = queryTimed(
"SELECT UserID FROM UserTokens WHERE Token = ? LIMIT 1",
[{ value = userToken, cfsqltype = "cf_sql_varchar" }],
{ datasource = "payfrit" }
@ -75,7 +75,7 @@ if (addressId <= 0) {
try {
// First, get the address details so we can find all matching duplicates
qAddr = queryExecute("
qAddr = queryTimed("
SELECT Line1, Line2, City, StateID, ZIPCode
FROM Addresses
WHERE ID = :addressId
@ -91,7 +91,7 @@ try {
}
// Soft-delete ALL addresses that match the same Line1, Line2, City, StateID, ZIPCode
qDelete = queryExecute("
qDelete = queryTimed("
UPDATE Addresses
SET IsDeleted = 1
WHERE UserID = :userId

View file

@ -29,7 +29,7 @@ if (structKeyExists(request, "UserID") && isNumeric(request.UserID) && request.U
userToken = getHeader("X-User-Token");
if (len(userToken)) {
try {
qTok = queryExecute(
qTok = queryTimed(
"SELECT UserID FROM UserTokens WHERE Token = ? LIMIT 1",
[{ value = userToken, cfsqltype = "cf_sql_varchar" }],
{ datasource = "payfrit" }
@ -47,7 +47,7 @@ if (userId <= 0) {
try {
// Get user's delivery addresses
qAddresses = queryExecute("
qAddresses = queryTimed("
SELECT
a.ID,
a.IsDefaultDelivery,

View file

@ -40,7 +40,7 @@ try {
}
// Verify address belongs to user
qCheck = queryExecute("
qCheck = queryTimed("
SELECT ID
FROM Addresses
WHERE ID = :addressId
@ -61,7 +61,7 @@ try {
}
// Clear all defaults for this user
queryExecute("
queryTimed("
UPDATE Addresses
SET IsDefaultDelivery = 0
WHERE UserID = :userId
@ -72,7 +72,7 @@ try {
}, { datasource: "payfrit" });
// Set this one as default
queryExecute("
queryTimed("
UPDATE Addresses
SET IsDefaultDelivery = 1
WHERE ID = :addressId

View file

@ -5,7 +5,7 @@
<!--- List US states for address forms --->
<cfscript>
try {
qStates = queryExecute("
qStates = queryTimed("
SELECT ID as StateID, Abbreviation as StateAbbreviation, Name as StateName
FROM tt_States
ORDER BY Name

View file

@ -11,7 +11,7 @@
*/
try {
qTypes = queryExecute("
qTypes = queryTimed("
SELECT tt_AddressTypeID as ID, tt_AddressType as Label
FROM tt_AddressTypes
ORDER BY tt_AddressTypeID

View file

@ -5,7 +5,7 @@
// Add IsActive column to TaskCategories table
try {
// Check if column exists
qCheck = queryExecute("
qCheck = queryTimed("
SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'payfrit'
AND TABLE_NAME = 'TaskCategories'
@ -13,7 +13,7 @@ try {
", [], { datasource: "payfrit" });
if (qCheck.recordCount == 0) {
queryExecute("
queryTimed("
ALTER TABLE TaskCategories
ADD COLUMN IsActive TINYINT(1) NOT NULL DEFAULT 1
", [], { datasource: "payfrit" });

View file

@ -19,7 +19,7 @@ response = { "OK": false };
try {
// Check if columns already exist
qCheck = queryExecute("
qCheck = queryTimed("
SELECT COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'payfrit'
@ -33,7 +33,7 @@ try {
// Add ScheduleStart if not exists
if (!listFindNoCase(existingCols, "ScheduleStart")) {
queryExecute("
queryTimed("
ALTER TABLE Categories
ADD COLUMN ScheduleStart TIME NULL
", {}, { datasource: "payfrit" });
@ -42,7 +42,7 @@ try {
// Add ScheduleEnd if not exists
if (!listFindNoCase(existingCols, "ScheduleEnd")) {
queryExecute("
queryTimed("
ALTER TABLE Categories
ADD COLUMN ScheduleEnd TIME NULL
", {}, { datasource: "payfrit" });
@ -51,7 +51,7 @@ try {
// Add ScheduleDays if not exists
if (!listFindNoCase(existingCols, "ScheduleDays")) {
queryExecute("
queryTimed("
ALTER TABLE Categories
ADD COLUMN ScheduleDays VARCHAR(20) NULL
", {}, { datasource: "payfrit" });

View file

@ -14,7 +14,7 @@ try {
bigDeansBusinessId = 27;
// Find the Fountain Soda item we created
qFountain = queryExecute("
qFountain = queryTimed("
SELECT ID, Name FROM Items
WHERE BusinessID = :bizId AND Name = 'Fountain Soda'
", { bizId: bigDeansBusinessId }, { datasource: "payfrit" });
@ -29,14 +29,14 @@ try {
response["FountainSodaID"] = fountainId;
// Update Fountain Soda to require child selection and be collapsible
queryExecute("
queryTimed("
UPDATE Items
SET RequiresChildSelection = 1, IsCollapsible = 1
WHERE ID = :itemId
", { itemId: fountainId }, { datasource: "payfrit" });
// Check if modifiers already exist
qExisting = queryExecute("
qExisting = queryTimed("
SELECT COUNT(*) as cnt FROM Items WHERE ParentItemID = :parentId
", { parentId: fountainId }, { datasource: "payfrit" });
@ -48,10 +48,10 @@ try {
}
// Add Size group
qMaxItem = queryExecute("SELECT COALESCE(MAX(ID), 0) + 1 as nextId FROM Items", {}, { datasource: "payfrit" });
qMaxItem = queryTimed("SELECT COALESCE(MAX(ID), 0) + 1 as nextId FROM Items", {}, { datasource: "payfrit" });
sizeGroupId = qMaxItem.nextId;
queryExecute("
queryTimed("
INSERT INTO Items (
ID, BusinessID, CategoryID, ParentItemID,
Name, Description, Price, IsActive,
@ -77,8 +77,8 @@ try {
sizesAdded = 0;
for (size in sizes) {
qMaxItem = queryExecute("SELECT COALESCE(MAX(ID), 0) + 1 as nextId FROM Items", {}, { datasource: "payfrit" });
queryExecute("
qMaxItem = queryTimed("SELECT COALESCE(MAX(ID), 0) + 1 as nextId FROM Items", {}, { datasource: "payfrit" });
queryTimed("
INSERT INTO Items (
ItemID, BusinessID, CategoryID, ParentItemID,
Name, Description, Price, IsActive,
@ -103,10 +103,10 @@ try {
}
// Add Type/Flavor group
qMaxItem = queryExecute("SELECT COALESCE(MAX(ID), 0) + 1 as nextId FROM Items", {}, { datasource: "payfrit" });
qMaxItem = queryTimed("SELECT COALESCE(MAX(ID), 0) + 1 as nextId FROM Items", {}, { datasource: "payfrit" });
typeGroupId = qMaxItem.nextId;
queryExecute("
queryTimed("
INSERT INTO Items (
ID, BusinessID, CategoryID, ParentItemID,
Name, Description, Price, IsActive,
@ -136,8 +136,8 @@ try {
typesAdded = 0;
for (type in types) {
qMaxItem = queryExecute("SELECT COALESCE(MAX(ID), 0) + 1 as nextId FROM Items", {}, { datasource: "payfrit" });
queryExecute("
qMaxItem = queryTimed("SELECT COALESCE(MAX(ID), 0) + 1 as nextId FROM Items", {}, { datasource: "payfrit" });
queryTimed("
INSERT INTO Items (
ItemID, BusinessID, CategoryID, ParentItemID,
Name, Description, Price, IsActive,

View file

@ -12,7 +12,7 @@ response = { "OK": false };
try {
// Check if column already exists
qCheck = queryExecute("
qCheck = queryTimed("
SELECT COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'payfrit'
@ -25,14 +25,14 @@ try {
response["MESSAGE"] = "CategoryID column already exists";
} else {
// Add the column
queryExecute("
queryTimed("
ALTER TABLE Items
ADD COLUMN CategoryID INT NULL DEFAULT 0 AFTER ParentItemID
", {}, { datasource: "payfrit" });
// Add index for performance
try {
queryExecute("
queryTimed("
CREATE INDEX idx_items_categoryid ON Items(CategoryID)
", {}, { datasource: "payfrit" });
} catch (any indexErr) {

View file

@ -5,7 +5,7 @@
<cfscript>
try {
// Check if columns already exist
checkCols = queryExecute(
checkCols = queryTimed(
"SHOW COLUMNS FROM Addresses LIKE 'Latitude'",
[],
{ datasource = "payfrit" }
@ -13,7 +13,7 @@ try {
if (checkCols.recordCount EQ 0) {
// Add the columns
queryExecute(
queryTimed(
"ALTER TABLE Addresses
ADD COLUMN Latitude DECIMAL(10,7) NULL,
ADD COLUMN Longitude DECIMAL(10,7) NULL",

View file

@ -5,7 +5,7 @@
// Add CategoryID column to tt_TaskTypes (Services) table
try {
// Check if column exists
qCheck = queryExecute("
qCheck = queryTimed("
SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'payfrit'
AND TABLE_NAME = 'tt_TaskTypes'
@ -13,7 +13,7 @@ try {
", [], { datasource: "payfrit" });
if (qCheck.recordCount == 0) {
queryExecute("
queryTimed("
ALTER TABLE tt_TaskTypes
ADD COLUMN TaskCategoryID INT NULL
", [], { datasource: "payfrit" });

View file

@ -10,7 +10,7 @@ result = { "OK": true, "STEPS": [] };
try {
// Check if columns already exist
cols = queryExecute("
cols = queryTimed("
SELECT COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'payfrit'
@ -23,7 +23,7 @@ try {
// Add SourceType if missing
if (!listFindNoCase(existingCols, "SourceType")) {
queryExecute("
queryTimed("
ALTER TABLE Tasks ADD COLUMN SourceType VARCHAR(50) NULL
", [], { datasource: "payfrit" });
arrayAppend(result.STEPS, "Added SourceType column");
@ -33,7 +33,7 @@ try {
// Add SourceID if missing
if (!listFindNoCase(existingCols, "SourceID")) {
queryExecute("
queryTimed("
ALTER TABLE Tasks ADD COLUMN SourceID INT NULL
", [], { datasource: "payfrit" });
arrayAppend(result.STEPS, "Added SourceID column");
@ -42,7 +42,7 @@ try {
}
// Verify columns now exist
verifyQuery = queryExecute("
verifyQuery = queryTimed("
SELECT COLUMN_NAME, DATA_TYPE
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'payfrit'

View file

@ -4,7 +4,7 @@
<cfscript>
// Show all beacons with their current business/service point assignments
q = queryExecute("
q = queryTimed("
SELECT
b.ID,
b.UUID,
@ -35,7 +35,7 @@ for (row in q) {
}
// Also get service points for reference
spQuery = queryExecute("
spQuery = queryTimed("
SELECT sp.ID, sp.Name AS Name, sp.BusinessID AS BusinessID, b.Name AS Name
FROM ServicePoints sp
JOIN Businesses b ON b.ID = sp.BusinessID

View file

@ -4,14 +4,14 @@
<cfscript>
// Check Big Dean's owner
q = queryExecute("
q = queryTimed("
SELECT b.ID, b.Name, b.UserID
FROM Businesses b
WHERE b.ID = 27
", {}, { datasource: "payfrit" });
// Get users
users = queryExecute("
users = queryTimed("
SELECT *
FROM Users
ORDER BY ID

View file

@ -11,7 +11,7 @@ if (!len(phone)) {
abort;
}
q = queryExecute("
q = queryTimed("
SELECT ID, FirstName, LastName, EmailAddress, ContactNumber, IsContactVerified
FROM Users
WHERE ContactNumber = :phone OR EmailAddress = :phone

View file

@ -15,7 +15,7 @@ try {
lazyDaisyID = 37;
// Unassign beacons 7, 8, 9 from any service points
queryExecute("
queryTimed("
UPDATE ServicePoints
SET BeaconID = NULL, AssignedByUserID = NULL
WHERE BeaconID IN (7, 8, 9) AND BusinessID = :bizId
@ -23,33 +23,33 @@ try {
response.steps.append("Unassigned beacons 7, 8, 9 from service points");
// Delete duplicate beacons 7, 8, 9
queryExecute("
queryTimed("
DELETE FROM Beacons
WHERE ID IN (7, 8, 9) AND BusinessID = :bizId
", { bizId: lazyDaisyID }, { datasource: "payfrit" });
response.steps.append("Deleted duplicate beacons 7, 8, 9");
// Update original beacons with names based on their service point assignments
queryExecute("
queryTimed("
UPDATE Beacons SET Name = 'Beacon - Table 1'
WHERE ID = 4 AND BusinessID = :bizId
", { bizId: lazyDaisyID }, { datasource: "payfrit" });
response.steps.append("Updated Beacon 4 name to 'Beacon - Table 1'");
queryExecute("
queryTimed("
UPDATE Beacons SET Name = 'Beacon - Table 2'
WHERE ID = 5 AND BusinessID = :bizId
", { bizId: lazyDaisyID }, { datasource: "payfrit" });
response.steps.append("Updated Beacon 5 name to 'Beacon - Table 2'");
queryExecute("
queryTimed("
UPDATE Beacons SET Name = 'Beacon - Table 3'
WHERE ID = 6 AND BusinessID = :bizId
", { bizId: lazyDaisyID }, { datasource: "payfrit" });
response.steps.append("Updated Beacon 6 name to 'Beacon - Table 3'");
// Get final status
qFinal = queryExecute("
qFinal = queryTimed("
SELECT sp.ID AS ServicePointID, sp.BeaconID, sp.BusinessID AS BusinessID,
b.Name AS BeaconName, b.UUID, sp.Name AS ServicePointName,
biz.Name AS BusinessName

View file

@ -28,7 +28,7 @@ try {
confirm = structKeyExists(url, "confirm") && url.confirm == "YES";
// Verification Step 1: Check for items without BusinessID
qNoBusinessID = queryExecute("
qNoBusinessID = queryTimed("
SELECT COUNT(*) as cnt FROM Items
WHERE BusinessID IS NULL OR BusinessID = 0
", {}, { datasource: "payfrit" });
@ -36,14 +36,14 @@ try {
response.verification["itemsWithoutBusinessID"] = qNoBusinessID.cnt;
// Verification Step 2: Check that all categories were converted
qCategories = queryExecute("
qCategories = queryTimed("
SELECT COUNT(*) as cnt FROM Categories
", {}, { datasource: "payfrit" });
response.verification["categoriesRemaining"] = qCategories.cnt;
// Verification Step 3: Check category Items exist (ParentID=0 with children)
qCategoryItems = queryExecute("
qCategoryItems = queryTimed("
SELECT COUNT(DISTINCT p.ItemID) as cnt
FROM Items p
INNER JOIN Items c ON c.ParentItemID = p.ItemID
@ -57,7 +57,7 @@ try {
response.verification["categoryItemsCreated"] = qCategoryItems.cnt;
// Verification Step 4: Check templates exist (in lt_ItemID_TemplateItemID)
qTemplates = queryExecute("
qTemplates = queryTimed("
SELECT COUNT(DISTINCT tl.TemplateItemID) as cnt
FROM lt_ItemID_TemplateItemID tl
INNER JOIN Items t ON t.ItemID = tl.TemplateItemID
@ -67,7 +67,7 @@ try {
// Verification Step 5: Find orphans at ParentID=0
// Orphan = ParentID=0, no children pointing to it, not in lt_ItemID_TemplateItemID
qOrphans = queryExecute("
qOrphans = queryTimed("
SELECT i.ID, i.Name, i.BusinessID
FROM Items i
WHERE i.ParentItemID = 0
@ -121,7 +121,7 @@ try {
// Step 1: Drop CategoryID column
try {
queryExecute("
queryTimed("
ALTER TABLE Items DROP COLUMN CategoryID
", {}, { datasource: "payfrit" });
arrayAppend(response.steps, "Dropped CategoryID column from Items");
@ -135,7 +135,7 @@ try {
// Step 2: Drop IsModifierTemplate column (now derived from lt_ItemID_TemplateItemID)
try {
queryExecute("
queryTimed("
ALTER TABLE Items DROP COLUMN IsModifierTemplate
", {}, { datasource: "payfrit" });
arrayAppend(response.steps, "Dropped IsModifierTemplate column from Items");
@ -149,7 +149,7 @@ try {
// Step 3: Drop Categories table
try {
queryExecute("
queryTimed("
DROP TABLE Categories
", {}, { datasource: "payfrit" });
arrayAppend(response.steps, "Dropped Categories table");

View file

@ -33,7 +33,7 @@ if (businessId <= 0) {
try {
// Find duplicate UserIDs for this business (keep the one with highest status or oldest)
qDupes = queryExecute("
qDupes = queryTimed("
SELECT ID, COUNT(*) as cnt, MIN(ID) as keepId
FROM Employees
WHERE BusinessID = ?
@ -44,7 +44,7 @@ try {
deleted = 0;
for (row in qDupes) {
// Delete all but the one we want to keep (the one with lowest EmployeeID)
qDel = queryExecute("
qDel = queryTimed("
DELETE FROM Employees
WHERE BusinessID = ? AND UserID = ? AND ID != ?
", [
@ -56,7 +56,7 @@ try {
}
// Get remaining employees
qRemaining = queryExecute("
qRemaining = queryTimed("
SELECT e.ID, e.UserID, u.FirstName, u.LastName
FROM Employees e
JOIN Users u ON e.UserID = u.ID

View file

@ -10,7 +10,7 @@ try {
keepBusinessID = 37;
// Unassign all beacons from service points of other businesses
queryExecute("
queryTimed("
UPDATE ServicePoints
SET BeaconID = NULL, AssignedByUserID = NULL
WHERE BusinessID != :keepID AND BeaconID IS NOT NULL
@ -18,7 +18,7 @@ try {
response.steps.append("Unassigned beacons from other businesses' service points");
// Get list of businesses to delete
qBiz = queryExecute("
qBiz = queryTimed("
SELECT ID, Name FROM Businesses WHERE ID != :keepID
", { keepID: keepBusinessID }, { datasource: "payfrit" });
@ -30,7 +30,7 @@ try {
// Delete related data first (foreign key constraints)
// Delete lt_ItemID_TemplateItemID for items from other businesses
queryExecute("
queryTimed("
DELETE itl FROM lt_ItemID_TemplateItemID itl
JOIN Items i ON i.ID = itl.ItemID
WHERE i.BusinessID != :keepID
@ -38,29 +38,29 @@ try {
response.steps.append("Deleted lt_ItemID_TemplateItemID for other businesses");
// Delete Items for other businesses
qItems = queryExecute("
qItems = queryTimed("
SELECT COUNT(*) as cnt FROM Items WHERE BusinessID != :keepID
", { keepID: keepBusinessID }, { datasource: "payfrit" });
queryExecute("
queryTimed("
DELETE FROM Items WHERE BusinessID != :keepID
", { keepID: keepBusinessID }, { datasource: "payfrit" });
response.steps.append("Deleted " & qItems.cnt & " items from other businesses");
// Delete Categories for other businesses
queryExecute("
queryTimed("
DELETE FROM Categories WHERE BusinessID != :keepID
", { keepID: keepBusinessID }, { datasource: "payfrit" });
response.steps.append("Deleted categories from other businesses");
// Delete Hours for other businesses
queryExecute("
queryTimed("
DELETE FROM Hours WHERE BusinessID != :keepID
", { keepID: keepBusinessID }, { datasource: "payfrit" });
response.steps.append("Deleted hours from other businesses");
// Delete Employees for other businesses
try {
queryExecute("
queryTimed("
DELETE FROM Employees WHERE BusinessID != :keepID
", { keepID: keepBusinessID }, { datasource: "payfrit" });
response.steps.append("Deleted employees from other businesses");
@ -70,7 +70,7 @@ try {
// Delete ServicePoints for other businesses
try {
queryExecute("
queryTimed("
DELETE FROM ServicePoints WHERE BusinessID != :keepID
", { keepID: keepBusinessID }, { datasource: "payfrit" });
response.steps.append("Deleted service points from other businesses");
@ -80,7 +80,7 @@ try {
// Delete Stations for other businesses
try {
queryExecute("
queryTimed("
DELETE FROM Stations WHERE BusinessID != :keepID
", { keepID: keepBusinessID }, { datasource: "payfrit" });
response.steps.append("Deleted stations from other businesses");
@ -90,7 +90,7 @@ try {
// Delete beacon-business mappings for other businesses
try {
queryExecute("
queryTimed("
DELETE FROM lt_BeaconsID_BusinessesID WHERE BusinessID != :keepID
", { keepID: keepBusinessID }, { datasource: "payfrit" });
response.steps.append("Deleted beacon mappings for other businesses");
@ -99,13 +99,13 @@ try {
}
// Finally delete the businesses themselves
queryExecute("
queryTimed("
DELETE FROM Businesses WHERE ID != :keepID
", { keepID: keepBusinessID }, { datasource: "payfrit" });
response.steps.append("Deleted " & arrayLen(deletedBusinesses) & " businesses");
// Get beacon status
qBeacons = queryExecute("
qBeacons = queryTimed("
SELECT sp.ID AS ServicePointID, sp.BeaconID, sp.BusinessID AS BusinessID,
b.UUID, biz.Name AS BusinessName, sp.Name AS ServicePointName
FROM ServicePoints sp

View file

@ -6,7 +6,7 @@ param name="url.itemId" default="11543";
param name="url.action" default="check"; // "check" or "deactivate"
// Check the item first
qItem = queryExecute("
qItem = queryTimed("
SELECT ID, Name, ParentItemID, IsActive, IsCollapsible
FROM Items
WHERE ID = :itemId
@ -18,7 +18,7 @@ if (qItem.recordCount == 0) {
}
// Get all children (direct only for display)
qChildren = queryExecute("
qChildren = queryTimed("
SELECT ID, Name
FROM Items
WHERE ParentItemID = :itemId
@ -46,14 +46,14 @@ result = {
if (url.action == "deactivate") {
// Deactivate children first
queryExecute("
queryTimed("
UPDATE Items
SET IsActive = 0
WHERE ParentItemID = :itemId
", { itemId: url.itemId });
// Then deactivate the parent
queryExecute("
queryTimed("
UPDATE Items
SET IsActive = 0
WHERE ItemID = :itemId

View file

@ -3,14 +3,14 @@
<cfscript>
// Delete cart orders (status 0) to reset for testing
result = queryExecute("
result = queryTimed("
DELETE FROM OrderLineItems
WHERE OrderID IN (
SELECT ID FROM Orders WHERE StatusID = 0
)
", {}, { datasource = "payfrit" });
result2 = queryExecute("
result2 = queryTimed("
DELETE FROM Orders WHERE StatusID = 0
", {}, { datasource = "payfrit" });

View file

@ -11,26 +11,26 @@ try {
for (bizID in businessIDs) {
// Delete lt_ItemID_TemplateItemID for items belonging to this business
queryExecute("
queryTimed("
DELETE itl FROM lt_ItemID_TemplateItemID itl
INNER JOIN Items i ON i.ID = itl.ItemID
WHERE i.BusinessID = :bizID
", { bizID: bizID }, { datasource: "payfrit" });
// Delete Items
queryExecute("DELETE FROM Items WHERE BusinessID = :bizID", { bizID: bizID }, { datasource: "payfrit" });
queryTimed("DELETE FROM Items WHERE BusinessID = :bizID", { bizID: bizID }, { datasource: "payfrit" });
// Delete Categories
queryExecute("DELETE FROM Categories WHERE BusinessID = :bizID", { bizID: bizID }, { datasource: "payfrit" });
queryTimed("DELETE FROM Categories WHERE BusinessID = :bizID", { bizID: bizID }, { datasource: "payfrit" });
// Delete Hours
queryExecute("DELETE FROM Hours WHERE BusinessID = :bizID", { bizID: bizID }, { datasource: "payfrit" });
queryTimed("DELETE FROM Hours WHERE BusinessID = :bizID", { bizID: bizID }, { datasource: "payfrit" });
// Delete Addresses linked to this business
queryExecute("DELETE FROM Addresses WHERE BusinessID = :bizID", { bizID: bizID }, { datasource: "payfrit" });
queryTimed("DELETE FROM Addresses WHERE BusinessID = :bizID", { bizID: bizID }, { datasource: "payfrit" });
// Delete the Business itself
queryExecute("DELETE FROM Businesses WHERE ID = :bizID", { bizID: bizID }, { datasource: "payfrit" });
queryTimed("DELETE FROM Businesses WHERE ID = :bizID", { bizID: bizID }, { datasource: "payfrit" });
response.steps.append("Deleted business " & bizID & " and all related data");
}

View file

@ -3,7 +3,7 @@
<cfscript>
// Close all open chat tasks
try {
result = queryExecute("
result = queryTimed("
UPDATE Tasks
SET CompletedOn = NOW()
WHERE TaskTypeID = 2

View file

@ -14,7 +14,7 @@ try {
bigDeansBusinessId = 27;
// First, check if Big Dean's has a Beverages/Drinks category
qExistingCat = queryExecute("
qExistingCat = queryTimed("
SELECT ID, Name FROM Categories
WHERE BusinessID = :bizId AND (Name LIKE '%Drink%' OR Name LIKE '%Beverage%')
", { bizId: bigDeansBusinessId }, { datasource: "payfrit" });
@ -24,14 +24,14 @@ try {
response["CategoryNote"] = "Using existing category: " & qExistingCat.Name;
} else {
// Create a new Beverages category for Big Dean's
qMaxCat = queryExecute("SELECT COALESCE(MAX(ID), 0) + 1 as nextId FROM Categories", {}, { datasource: "payfrit" });
qMaxCat = queryTimed("SELECT COALESCE(MAX(ID), 0) + 1 as nextId FROM Categories", {}, { datasource: "payfrit" });
drinksCategoryId = qMaxCat.nextId;
qMaxSort = queryExecute("
qMaxSort = queryTimed("
SELECT COALESCE(MAX(SortOrder), 0) + 1 as nextSort FROM Categories WHERE BusinessID = :bizId
", { bizId: bigDeansBusinessId }, { datasource: "payfrit" });
queryExecute("
queryTimed("
INSERT INTO Categories (ID, BusinessID, ParentCategoryID, Name, SortOrder, AddedOn)
VALUES (:catId, :bizId, 0, 'Beverages', :sortOrder, NOW())
", {
@ -60,17 +60,17 @@ try {
for (drink in drinks) {
// Check if item already exists
qExists = queryExecute("
qExists = queryTimed("
SELECT ID FROM Items
WHERE BusinessID = :bizId AND Name = :name AND CategoryID = :catId
", { bizId: bigDeansBusinessId, name: drink.name, catId: drinksCategoryId }, { datasource: "payfrit" });
if (qExists.recordCount == 0) {
// Get next ItemID
qMaxItem = queryExecute("SELECT COALESCE(MAX(ID), 0) + 1 as nextId FROM Items", {}, { datasource: "payfrit" });
qMaxItem = queryTimed("SELECT COALESCE(MAX(ID), 0) + 1 as nextId FROM Items", {}, { datasource: "payfrit" });
newItemId = qMaxItem.nextId;
queryExecute("
queryTimed("
INSERT INTO Items (
ID, BusinessID, CategoryID, ParentItemID,
Name, Description, Price, IsActive,
@ -100,8 +100,8 @@ try {
flavors = ["Chocolate", "Vanilla", "Strawberry"];
flavorSort = 0;
for (flavor in flavors) {
qMaxOpt = queryExecute("SELECT COALESCE(MAX(ID), 0) + 1 as nextId FROM Items", {}, { datasource: "payfrit" });
queryExecute("
qMaxOpt = queryTimed("SELECT COALESCE(MAX(ID), 0) + 1 as nextId FROM Items", {}, { datasource: "payfrit" });
queryTimed("
INSERT INTO Items (
ID, BusinessID, CategoryID, ParentItemID,
Name, Description, Price, IsActive,

View file

@ -20,11 +20,11 @@ try {
uuid = beaconUUIDs[i];
// Check if beacon exists
qB = queryExecute("SELECT ID FROM Beacons WHERE UUID = :uuid", { uuid: uuid }, { datasource: "payfrit" });
qB = queryTimed("SELECT ID FROM Beacons WHERE UUID = :uuid", { uuid: uuid }, { datasource: "payfrit" });
if (qB.recordCount == 0) {
queryExecute("INSERT INTO Beacons (UUID, BusinessID) VALUES (:uuid, :bizID)", { uuid: uuid, bizID: lazyDaisyID }, { datasource: "payfrit" });
qNew = queryExecute("SELECT LAST_INSERT_ID() as id", {}, { datasource: "payfrit" });
queryTimed("INSERT INTO Beacons (UUID, BusinessID) VALUES (:uuid, :bizID)", { uuid: uuid, bizID: lazyDaisyID }, { datasource: "payfrit" });
qNew = queryTimed("SELECT LAST_INSERT_ID() as id", {}, { datasource: "payfrit" });
beaconID = qNew.id;
response.steps.append("Created beacon " & beaconID & " with UUID: " & uuid);
} else {
@ -34,17 +34,17 @@ try {
}
// Get service point Table 1
qSP = queryExecute("
qSP = queryTimed("
SELECT ID FROM ServicePoints
WHERE BusinessID = :bizID AND Name = 'Table 1'
", { bizID: lazyDaisyID }, { datasource: "payfrit" });
if (qSP.recordCount == 0) {
queryExecute("
queryTimed("
INSERT INTO ServicePoints (BusinessID, Name)
VALUES (:bizID, 'Table 1')
", { bizID: lazyDaisyID }, { datasource: "payfrit" });
qSP = queryExecute("SELECT LAST_INSERT_ID() as id", {}, { datasource: "payfrit" });
qSP = queryTimed("SELECT LAST_INSERT_ID() as id", {}, { datasource: "payfrit" });
servicePointID = qSP.id;
response.steps.append("Created service point 'Table 1' (ID: " & servicePointID & ")");
} else {
@ -53,20 +53,20 @@ try {
}
// Assign all beacons to the Table 1 service point
qBeacons = queryExecute("SELECT ID, UUID FROM Beacons WHERE BusinessID = :bizID", { bizID: lazyDaisyID }, { datasource: "payfrit" });
qBeacons = queryTimed("SELECT ID, UUID FROM Beacons WHERE BusinessID = :bizID", { bizID: lazyDaisyID }, { datasource: "payfrit" });
for (i = 1; i <= qBeacons.recordCount; i++) {
beaconID = qBeacons.ID[i];
// Unassign this beacon from any existing service point
queryExecute("
queryTimed("
UPDATE ServicePoints SET BeaconID = NULL, AssignedByUserID = NULL
WHERE BeaconID = :beaconID
", { beaconID: beaconID }, { datasource: "payfrit" });
// Assign beacon to Table 1 service point
queryExecute("
queryTimed("
UPDATE ServicePoints SET BeaconID = :beaconID, AssignedByUserID = 1
WHERE ID = :spID AND BusinessID = :bizID
", { beaconID: beaconID, bizID: lazyDaisyID, spID: servicePointID }, { datasource: "payfrit" });
@ -74,7 +74,7 @@ try {
}
// Get final status
qFinal = queryExecute("
qFinal = queryTimed("
SELECT sp.ID AS ServicePointID, sp.BeaconID, sp.BusinessID AS BusinessID,
b.Name AS BeaconName, b.UUID, sp.Name AS ServicePointName,
biz.Name AS BusinessName

View file

@ -3,7 +3,7 @@
<cfscript>
try {
// Create ChatMessages table
queryExecute("
queryTimed("
CREATE TABLE IF NOT EXISTS ChatMessages (
ID INT AUTO_INCREMENT PRIMARY KEY,
TaskID INT NOT NULL,
@ -20,20 +20,20 @@ try {
", {}, { datasource: "payfrit" });
// Also add a "Chat" category if it doesn't exist for business 17
existing = queryExecute("
existing = queryTimed("
SELECT ID FROM TaskCategories
WHERE BusinessID = 17 AND Name = 'Chat'
", {}, { datasource: "payfrit" });
if (existing.recordCount == 0) {
queryExecute("
queryTimed("
INSERT INTO TaskCategories (BusinessID, Name, Color)
VALUES (17, 'Chat', '##2196F3')
", {}, { datasource: "payfrit" });
}
// Verify table was created
cols = queryExecute("DESCRIBE ChatMessages", {}, { datasource: "payfrit" });
cols = queryTimed("DESCRIBE ChatMessages", {}, { datasource: "payfrit" });
colNames = [];
for (c in cols) {
arrayAppend(colNames, c.Field);

View file

@ -18,7 +18,7 @@ response = { "OK": false };
try {
// Check if Menus table exists
qCheck = queryExecute("
qCheck = queryTimed("
SELECT 1 FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'payfrit'
AND TABLE_NAME = 'Menus'
@ -29,7 +29,7 @@ try {
response["MESSAGE"] = "Menus table already exists";
} else {
// Create Menus table
queryExecute("
queryTimed("
CREATE TABLE Menus (
ID INT AUTO_INCREMENT PRIMARY KEY,
BusinessID INT NOT NULL,
@ -54,7 +54,7 @@ try {
}
// Check if MenuID column exists in Categories table
qCatCol = queryExecute("
qCatCol = queryTimed("
SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'payfrit'
AND TABLE_NAME = 'Categories'
@ -63,7 +63,7 @@ try {
if (qCatCol.recordCount == 0) {
// Add MenuID column to Categories table
queryExecute("
queryTimed("
ALTER TABLE Categories
ADD COLUMN MenuID INT NULL DEFAULT NULL AFTER BusinessID,
ADD INDEX idx_categories_menu (MenuID)

View file

@ -55,18 +55,18 @@ try {
}
// Create minimal address record (just a placeholder)
queryExecute("
queryTimed("
INSERT INTO Addresses (Line1, UserID, AddressTypeID, AddedOn)
VALUES ('Parent Business - No Physical Location', :userID, 2, NOW())
", {
userID: UserID
}, { datasource = "payfrit" });
qAddr = queryExecute("SELECT LAST_INSERT_ID() as id", {}, { datasource = "payfrit" });
qAddr = queryTimed("SELECT LAST_INSERT_ID() as id", {}, { datasource = "payfrit" });
addressId = qAddr.id;
// Create parent business (no menu, no hours, just a shell)
queryExecute("
queryTimed("
INSERT INTO Businesses (Name, UserID, AddressID, ParentBusinessID, BusinessDeliveryZipCodes, AddedOn)
VALUES (:name, :userId, :addressId, NULL, '', NOW())
", {
@ -75,11 +75,11 @@ try {
addressId: addressId
}, { datasource = "payfrit" });
qBiz = queryExecute("SELECT LAST_INSERT_ID() as id", {}, { datasource = "payfrit" });
qBiz = queryTimed("SELECT LAST_INSERT_ID() as id", {}, { datasource = "payfrit" });
newBusinessID = qBiz.id;
// Link address back to business
queryExecute("
queryTimed("
UPDATE Addresses SET BusinessID = :bizId WHERE ID = :addrId
", {
bizId: newBusinessID,
@ -91,7 +91,7 @@ try {
for (childID in ChildBusinessIDs) {
childID = val(childID);
if (childID > 0) {
queryExecute("
queryTimed("
UPDATE Businesses SET ParentBusinessID = :parentId WHERE ID = :childId
", {
parentId: newBusinessID,

View file

@ -8,7 +8,7 @@ bizId = 27;
// These are the items that were deactivated by fixBigDeansCategories.cfm
deactivatedIds = [11177, 11180, 11183, 11186, 11190, 11193, 11196, 11199, 11204, 11212, 11220, 11259];
qDeactivated = queryExecute("
qDeactivated = queryTimed("
SELECT i.ID, i.Name, i.ParentItemID, i.IsActive, i.IsCollapsible,
(SELECT COUNT(*) FROM Items c WHERE c.ParentItemID = i.ID) as ChildCount,
(SELECT GROUP_CONCAT(c.Name) FROM Items c WHERE c.ParentItemID = i.ID) as Children

View file

@ -6,7 +6,7 @@
bizId = 27;
// Get all template links for Big Dean's with item names
qLinks = queryExecute("
qLinks = queryTimed("
SELECT
tl.ItemID as MenuItemID,
mi.Name as MenuName,
@ -33,7 +33,7 @@ for (row in qLinks) {
}
// Get burgers specifically (parent = 11271)
qBurgers = queryExecute("
qBurgers = queryTimed("
SELECT ID, Name FROM Items
WHERE BusinessID = :bizId AND ParentItemID = 11271 AND IsActive = 1
ORDER BY SortOrder
@ -42,7 +42,7 @@ qBurgers = queryExecute("
burgers = [];
for (row in qBurgers) {
// Get templates for this burger
qBurgerTemplates = queryExecute("
qBurgerTemplates = queryTimed("
SELECT tl.TemplateItemID, t.Name as TemplateName
FROM lt_ItemID_TemplateItemID tl
JOIN Items t ON t.ItemID = tl.TemplateItemID

View file

@ -6,7 +6,7 @@
businessID = 27;
// Run the EXACT query from getForBuilder.cfm
qCategories = queryExecute("
qCategories = queryTimed("
SELECT DISTINCT
p.ItemID as CategoryID,
p.Name as Name,
@ -31,12 +31,12 @@ for (c in qCategories) {
}
// Also check raw counts
rawCount = queryExecute("
rawCount = queryTimed("
SELECT COUNT(*) as cnt FROM Items
WHERE BusinessID = :bizId AND ParentItemID = 0 AND IsActive = 1
", { bizId: businessID });
childrenCount = queryExecute("
childrenCount = queryTimed("
SELECT COUNT(DISTINCT c.ParentItemID) as cnt
FROM Items c
INNER JOIN Items p ON p.ItemID = c.ParentItemID

View file

@ -6,7 +6,7 @@
bizId = 27;
// Get all template links for Big Dean's
qLinks = queryExecute("
qLinks = queryTimed("
SELECT
tl.ItemID as MenuItemID,
mi.Name as MenuName,
@ -36,7 +36,7 @@ for (row in qLinks) {
}
// Get all templates that exist for this business
qTemplates = queryExecute("
qTemplates = queryTimed("
SELECT ID, Name, IsActive, ParentItemID
FROM Items
WHERE BusinessID = :bizId

View file

@ -8,7 +8,7 @@ bizId = 27;
// Check the template items themselves (IDs from lt_ItemID_TemplateItemID)
templateIds = "11267, 11251, 11246, 11224, 11233, 11230, 11240, 11243, 11237, 11227";
qTemplates = queryExecute("
qTemplates = queryTimed("
SELECT ID, Name, IsCollapsible, IsActive, ParentItemID, BusinessID
FROM Items
WHERE ID IN (#templateIds#)
@ -29,7 +29,7 @@ for (row in qTemplates) {
// Also check what other templates might exist for burgers
// Look for items that are in lt_ItemID_TemplateItemID but NOT linked to burgers
qMissingTemplates = queryExecute("
qMissingTemplates = queryTimed("
SELECT DISTINCT t.ItemID, t.Name, t.IsCollapsible, t.IsActive
FROM Items t
WHERE t.BusinessID = :bizId
@ -52,7 +52,7 @@ for (row in qMissingTemplates) {
}
// What templates SHOULD burgers have? Let's see all templates used by ANY item
qAllTemplateUsage = queryExecute("
qAllTemplateUsage = queryTimed("
SELECT t.ItemID, t.Name, COUNT(tl.ItemID) as UsageCount
FROM lt_ItemID_TemplateItemID tl
JOIN Items t ON t.ItemID = tl.TemplateItemID

View file

@ -6,7 +6,7 @@
bizId = 27;
// Get the template items themselves
qTemplates = queryExecute("
qTemplates = queryTimed("
SELECT ID, Name, IsCollapsible, IsActive, ParentItemID, BusinessID
FROM Items
WHERE ID IN (11267, 11251, 11246, 11224, 11233, 11230, 11240, 11243, 11237, 11227)
@ -26,7 +26,7 @@ for (row in qTemplates) {
}
// What templates are used by burgers vs all items?
qBurgerLinks = queryExecute("
qBurgerLinks = queryTimed("
SELECT mi.ID, mi.Name, GROUP_CONCAT(t.Name ORDER BY tl.SortOrder) as Templates
FROM Items mi
JOIN lt_ItemID_TemplateItemID tl ON tl.ItemID = mi.ID
@ -48,7 +48,7 @@ for (row in qBurgerLinks) {
// Also check: are there templates that SHOULD be linked to burgers?
// (e.g., Add Cheese, etc.)
qCheeseTemplate = queryExecute("
qCheeseTemplate = queryTimed("
SELECT ID, Name, ParentItemID, IsActive
FROM Items
WHERE BusinessID = :bizId

View file

@ -25,7 +25,7 @@
<cftry>
<!--- Get raw employee records --- >
<cfset qEmployees = queryExecute("
<cfset qEmployees = queryTimed("
SELECT e.*, b.Name
FROM Employees e
INNER JOIN Businesses b ON b.ID = e.BusinessID
@ -45,7 +45,7 @@
</cfloop>
<!--- Check for duplicate businesses --- >
<cfset qDuplicates = queryExecute("
<cfset qDuplicates = queryTimed("
SELECT Name, COUNT(*) AS cnt
FROM Businesses
GROUP BY Name

View file

@ -5,7 +5,7 @@
<cfscript>
// Debug: check ChatMessages table contents
try {
qAll = queryExecute("SELECT * FROM ChatMessages ORDER BY CreatedOn DESC LIMIT 50", [], { datasource: "payfrit" });
qAll = queryTimed("SELECT * FROM ChatMessages ORDER BY CreatedOn DESC LIMIT 50", [], { datasource: "payfrit" });
messages = [];
for (row in qAll) {
@ -20,7 +20,7 @@ try {
}
// Also check schema
schema = queryExecute("DESCRIBE ChatMessages", [], { datasource: "payfrit" });
schema = queryTimed("DESCRIBE ChatMessages", [], { datasource: "payfrit" });
cols = [];
for (col in schema) {
arrayAppend(cols, { "Field": col.Field, "Type": col.Type });

View file

@ -9,7 +9,7 @@ response = { "OK": true };
try {
// Get Fountain Drinks item
qFountain = queryExecute("
qFountain = queryTimed("
SELECT ID, Name, ParentItemID, Price, IsCollapsible, RequiresChildSelection
FROM Items
WHERE BusinessID = 17 AND Name LIKE '%Fountain%'
@ -27,7 +27,7 @@ try {
};
// Get children of this item
qChildren = queryExecute("
qChildren = queryTimed("
SELECT ID, Name, ParentItemID, Price, IsCollapsible, RequiresChildSelection, IsCheckedByDefault
FROM Items
WHERE ParentItemID = :parentId
@ -45,7 +45,7 @@ try {
};
// Get grandchildren
qGrandchildren = queryExecute("
qGrandchildren = queryTimed("
SELECT ID, Name, Price, IsCheckedByDefault
FROM Items
WHERE ParentItemID = :parentId

View file

@ -13,7 +13,7 @@ try {
if (structKeyExists(data, "Phone") && len(data.Phone)) {
phone = reReplace(data.Phone, "[^0-9]", "", "all");
qUser = queryExecute("
qUser = queryTimed("
SELECT ID, FirstName, LastName, EmailAddress, ContactNumber
FROM Users
WHERE REPLACE(REPLACE(REPLACE(ContactNumber, '-', ''), '(', ''), ')', '') LIKE ?
@ -30,7 +30,7 @@ if (structKeyExists(data, "Phone") && len(data.Phone)) {
userId = qUser.ID;
qEmployees = queryExecute("
qEmployees = queryTimed("
SELECT e.ID, e.BusinessID, e.StatusID,
CAST(e.IsActive AS UNSIGNED) AS IsActive,
b.Name
@ -66,7 +66,7 @@ if (structKeyExists(data, "Phone") && len(data.Phone)) {
// Original behavior - list employees by BusinessID
businessId = structKeyExists(data, "BusinessID") ? val(data.BusinessID) : 17;
q = queryExecute("
q = queryTimed("
SELECT ID, UserID, StatusID, IsActive,
CAST(IsActive AS UNSIGNED) AS IsActiveInt
FROM Employees

View file

@ -12,7 +12,7 @@ try {
// Close all open chats action
if (structKeyExists(data, "action") && data.action == "closeAllChats") {
queryExecute("
queryTimed("
UPDATE Tasks SET CompletedOn = NOW()
WHERE TaskTypeID = 2 AND CompletedOn IS NULL
", {}, { datasource: "payfrit" });
@ -22,7 +22,7 @@ if (structKeyExists(data, "action") && data.action == "closeAllChats") {
</cfscript>
<cftry>
<cfset qTasks = queryExecute("
<cfset qTasks = queryTimed("
SELECT
t.ID,
t.BusinessID,
@ -50,7 +50,7 @@ if (structKeyExists(data, "action") && data.action == "closeAllChats") {
})>
</cfloop>
<cfset qStats = queryExecute("
<cfset qStats = queryTimed("
SELECT
COUNT(*) as Total,
SUM(CASE WHEN ClaimedByUserID > 0 AND CompletedOn IS NULL THEN 1 ELSE 0 END) as ClaimedNotCompleted,

View file

@ -3,7 +3,7 @@
<cfcontent type="application/json; charset=utf-8">
<cftry>
<cfset qAll = queryExecute("
<cfset qAll = queryTimed("
SELECT ID, ClaimedByUserID, CompletedOn, OrderID,
CASE WHEN CompletedOn IS NULL THEN 'YES_NULL' ELSE 'NOT_NULL' END AS IsNull
FROM Tasks

View file

@ -7,10 +7,10 @@
bizId = 27;
// Count total links
qCount = queryExecute("SELECT COUNT(*) as cnt FROM lt_ItemID_TemplateItemID", {}, { datasource: "payfrit" });
qCount = queryTimed("SELECT COUNT(*) as cnt FROM lt_ItemID_TemplateItemID", {}, { datasource: "payfrit" });
// Get template item IDs for this business
qTemplates = queryExecute("
qTemplates = queryTimed("
SELECT DISTINCT tl.TemplateItemID, i.Name
FROM lt_ItemID_TemplateItemID tl
JOIN Items i ON i.ID = tl.TemplateItemID
@ -23,7 +23,7 @@ for (row in qTemplates) {
}
// Get items that should be categories (ParentItemID=0, not templates)
qCategories = queryExecute("
qCategories = queryTimed("
SELECT i.ID, i.Name, i.ParentItemID, i.IsCollapsible
FROM Items i
WHERE i.BusinessID = :bizId

View file

@ -19,7 +19,7 @@ if (len(phone) == 0) {
}
// Find user by phone
qUser = queryExecute("
qUser = queryTimed("
SELECT ID, FirstName, LastName, EmailAddress, ContactNumber
FROM Users
WHERE REPLACE(REPLACE(REPLACE(ContactNumber, '-', ''), '(', ''), ')', '') LIKE ?
@ -37,7 +37,7 @@ if (qUser.recordCount == 0) {
userId = qUser.ID;
// Get all employee records for this user
qEmployees = queryExecute("
qEmployees = queryTimed("
SELECT e.ID, e.BusinessID, e.StatusID,
CAST(e.IsActive AS UNSIGNED) AS IsActive,
b.Name

View file

@ -28,7 +28,7 @@ try {
response["ERROR"] = "BusinessID required";
} else {
// Get address ID first
qBiz = queryExecute("SELECT AddressID FROM Businesses WHERE ID = :id", { id: bizID }, { datasource = "payfrit" });
qBiz = queryTimed("SELECT AddressID FROM Businesses WHERE ID = :id", { id: bizID }, { datasource = "payfrit" });
if (qBiz.recordCount == 0) {
response["ERROR"] = "Business not found";
@ -36,11 +36,11 @@ try {
addrID = qBiz.AddressID;
// Delete business
queryExecute("DELETE FROM Businesses WHERE ID = :id", { id: bizID }, { datasource = "payfrit" });
queryTimed("DELETE FROM Businesses WHERE ID = :id", { id: bizID }, { datasource = "payfrit" });
// Delete address if exists
if (val(addrID) > 0) {
queryExecute("DELETE FROM Addresses WHERE ID = :id", { id: addrID }, { datasource = "payfrit" });
queryTimed("DELETE FROM Addresses WHERE ID = :id", { id: addrID }, { datasource = "payfrit" });
}
response["OK"] = true;

View file

@ -26,7 +26,7 @@ try {
// Get all level-1 modifiers that are NOT templates
// These are the duplicates we want to delete
qOrphans = queryExecute("
qOrphans = queryTimed("
SELECT
m.ItemID,
m.Name,
@ -49,12 +49,12 @@ try {
for (orphan in qOrphans) {
try {
// Delete children of this orphan (options within the modifier group)
qDeleteChildren = queryExecute("
qDeleteChildren = queryTimed("
DELETE FROM Items WHERE ParentItemID = :orphanID
", { orphanID: orphan.ItemID }, { datasource: "payfrit" });
// Delete the orphan itself
qDeleteOrphan = queryExecute("
qDeleteOrphan = queryTimed("
DELETE FROM Items WHERE ID = :orphanID
", { orphanID: orphan.ItemID }, { datasource: "payfrit" });

View file

@ -18,7 +18,7 @@ response = { "OK": false, "deleted": 0, "orphans": [] };
try {
// Find orphans
qOrphans = queryExecute("
qOrphans = queryTimed("
SELECT i.ID, i.Name, i.BusinessID
FROM Items i
WHERE i.ParentItemID = 0
@ -43,7 +43,7 @@ try {
// Delete them by ID list
if (arrayLen(orphanIDs) > 0) {
queryExecute("
queryTimed("
DELETE FROM Items WHERE ID IN (#arrayToList(orphanIDs)#)
", {}, { datasource: "payfrit" });
}

View file

@ -3,7 +3,7 @@
<cfcontent type="application/json; charset=utf-8" reset="true">
<cfscript>
qDesc = queryExecute("SHOW COLUMNS FROM Items", {}, { datasource: "payfrit" });
qDesc = queryTimed("SHOW COLUMNS FROM Items", {}, { datasource: "payfrit" });
cols = [];
for (row in qDesc) {

View file

@ -17,7 +17,7 @@ try {
}
// Get table structure
cols = queryExecute("DESCRIBE #tableName#", {}, { datasource: "payfrit" });
cols = queryTimed("DESCRIBE #tableName#", {}, { datasource: "payfrit" });
columns = [];
for (c in cols) {
@ -31,7 +31,7 @@ try {
}
// Get sample data
sampleData = queryExecute("SELECT * FROM #tableName# LIMIT 5", {}, { datasource: "payfrit" });
sampleData = queryTimed("SELECT * FROM #tableName# LIMIT 5", {}, { datasource: "payfrit" });
samples = [];
for (row in sampleData) {

View file

@ -37,7 +37,7 @@ try {
// Step 1: Add BusinessID column if it doesn't exist
try {
if (!dryRun) {
queryExecute("
queryTimed("
ALTER TABLE Items ADD COLUMN BusinessID INT DEFAULT 0 AFTER ItemID
", {}, { datasource: "payfrit" });
}
@ -53,7 +53,7 @@ try {
// Step 2: Add index on BusinessID
try {
if (!dryRun) {
queryExecute("
queryTimed("
CREATE INDEX idx_item_business ON Items (BusinessID)
", {}, { datasource: "payfrit" });
}
@ -69,7 +69,7 @@ try {
// Step 3: Drop foreign key constraint on CategoryID if it exists
try {
if (!dryRun) {
queryExecute("
queryTimed("
ALTER TABLE Items DROP FOREIGN KEY Items_ibfk_1
", {}, { datasource: "payfrit" });
}
@ -83,7 +83,7 @@ try {
}
// Step 4: Get all Categories
qCategories = queryExecute("
qCategories = queryTimed("
SELECT ID, BusinessID, Name
FROM Categories
ORDER BY BusinessID, Name
@ -104,7 +104,7 @@ try {
if (!dryRun) {
// Create new Item for this category (ParentID=0, no template flag needed)
// Note: CategoryID set to 0 temporarily until we drop that column
queryExecute("
queryTimed("
INSERT INTO Items (
BusinessID,
CategoryID,
@ -136,7 +136,7 @@ try {
}, { datasource: "payfrit" });
// Get the new Item ID
qNewItem = queryExecute("
qNewItem = queryTimed("
SELECT ID FROM Items
WHERE BusinessID = :businessID
AND Name = :categoryName
@ -154,7 +154,7 @@ try {
// Update menu items in this category:
// - Set ParentItemID = newItemID (for top-level items only)
// - Set BusinessID = businessID (for all items)
queryExecute("
queryTimed("
UPDATE Items
SET BusinessID = :businessID,
ParentItemID = :newItemID
@ -167,7 +167,7 @@ try {
}, { datasource: "payfrit" });
// Set BusinessID on ALL items in this category (including nested)
queryExecute("
queryTimed("
UPDATE Items
SET BusinessID = :businessID
WHERE CategoryID = :categoryID
@ -178,7 +178,7 @@ try {
}, { datasource: "payfrit" });
// Count how many were updated
qCount = queryExecute("
qCount = queryTimed("
SELECT COUNT(*) as cnt FROM Items
WHERE ParentItemID = :newItemID
", { newItemID: newItemID }, { datasource: "payfrit" });
@ -186,7 +186,7 @@ try {
migration["itemsUpdated"] = qCount.cnt;
} else {
// Dry run - count what would be updated
qCount = queryExecute("
qCount = queryTimed("
SELECT COUNT(*) as cnt FROM Items
WHERE CategoryID = :categoryID
AND ParentItemID = 0
@ -201,7 +201,7 @@ try {
// Step 5: Set BusinessID for templates (items in lt_ItemID_TemplateItemID)
// Templates get their BusinessID from the items they're linked to
if (!dryRun) {
queryExecute("
queryTimed("
UPDATE Items t
INNER JOIN lt_ItemID_TemplateItemID tl ON tl.TemplateItemID = t.ItemID
INNER JOIN Items i ON i.ID = tl.ItemID
@ -213,7 +213,7 @@ try {
arrayAppend(response.steps, "Set BusinessID on templates from linked items");
// Set BusinessID on template children (options)
queryExecute("
queryTimed("
UPDATE Items c
INNER JOIN Items t ON t.ItemID = c.ParentItemID
SET c.BusinessID = t.BusinessID
@ -224,7 +224,7 @@ try {
arrayAppend(response.steps, "Set BusinessID on template children");
// Make sure templates have ParentID=0 (they live at top level)
queryExecute("
queryTimed("
UPDATE Items t
INNER JOIN lt_ItemID_TemplateItemID tl ON tl.TemplateItemID = t.ItemID
SET t.ParentItemID = 0

View file

@ -13,20 +13,20 @@ fakeCategories = [11177, 11180, 11183, 11186, 11190, 11193, 11196, 11199, 11204,
// Deactivate these items (or we could delete them, but deactivate is safer)
for (itemId in fakeCategories) {
queryExecute("
queryTimed("
UPDATE Items SET IsActive = 0 WHERE ItemID = :itemId AND BusinessID = :bizId
", { itemId: itemId, bizId: bizId }, { datasource: "payfrit" });
}
// Also deactivate their children (modifier options that belong to these fake parents)
for (itemId in fakeCategories) {
queryExecute("
queryTimed("
UPDATE Items SET IsActive = 0 WHERE ParentItemID = :itemId AND BusinessID = :bizId
", { itemId: itemId, bizId: bizId }, { datasource: "payfrit" });
}
// Now verify what categories remain
qCategories = queryExecute("
qCategories = queryTimed("
SELECT i.ID, i.Name
FROM Items i
WHERE i.BusinessID = :bizId

View file

@ -20,7 +20,7 @@ burgerIds = [11286, 11287, 11288, 11289, 11290]; // Big Dean's, Single w/Cheese,
actions = [];
// First, let's see what templates already exist and are active for burgers
qExistingLinks = queryExecute("
qExistingLinks = queryTimed("
SELECT tl.ItemID as MenuItemID, tl.TemplateItemID, t.Name as TemplateName
FROM lt_ItemID_TemplateItemID tl
JOIN Items t ON t.ItemID = tl.TemplateItemID
@ -33,21 +33,21 @@ for (row in qExistingLinks) {
// Reactivate template 11196 (Extras with Add Cheese)
if (!dryRun) {
queryExecute("UPDATE Items SET IsActive = 1 WHERE ItemID = 11196", {}, { datasource: "payfrit" });
queryExecute("UPDATE Items SET IsActive = 1 WHERE ParentItemID = 11196", {}, { datasource: "payfrit" });
queryTimed("UPDATE Items SET IsActive = 1 WHERE ItemID = 11196", {}, { datasource: "payfrit" });
queryTimed("UPDATE Items SET IsActive = 1 WHERE ParentItemID = 11196", {}, { datasource: "payfrit" });
}
arrayAppend(actions, { action: dryRun ? "WOULD_REACTIVATE" : "REACTIVATED", itemID: 11196, name: "Extras (Add Cheese, Add Onions)" });
// Link template 11196 to all burgers
for (burgerId in burgerIds) {
// Check if link already exists
qCheck = queryExecute("
qCheck = queryTimed("
SELECT COUNT(*) as cnt FROM lt_ItemID_TemplateItemID WHERE ItemID = :burgerId AND TemplateItemID = 11196
", { burgerId: burgerId }, { datasource: "payfrit" });
if (qCheck.cnt EQ 0) {
if (!dryRun) {
queryExecute("
queryTimed("
INSERT INTO lt_ItemID_TemplateItemID (ItemID, TemplateItemID, SortOrder)
VALUES (:burgerId, 11196, 2)
", { burgerId: burgerId }, { datasource: "payfrit" });
@ -58,7 +58,7 @@ for (burgerId in burgerIds) {
// Verify the result
if (!dryRun) {
qVerify = queryExecute("
qVerify = queryTimed("
SELECT mi.ID, mi.Name, GROUP_CONCAT(t.Name ORDER BY tl.SortOrder) as Templates
FROM Items mi
LEFT JOIN lt_ItemID_TemplateItemID tl ON tl.ItemID = mi.ID

View file

@ -2,21 +2,21 @@
<cfcontent type="application/json" reset="true">
<cfscript>
// One-time fix: remove # prefix from BrandColor
qBefore = queryExecute("
qBefore = queryTimed("
SELECT ID, BrandColor
FROM Businesses
WHERE BrandColor LIKE :pattern
", { pattern: { value: "##%", cfsqltype: "cf_sql_varchar" } }, { datasource: "payfrit" });
if (qBefore.recordCount > 0) {
queryExecute("
queryTimed("
UPDATE Businesses
SET BrandColor = SUBSTRING(BrandColor, 2)
WHERE BrandColor LIKE :pattern
", { pattern: { value: "##%", cfsqltype: "cf_sql_varchar" } }, { datasource: "payfrit" });
}
qAfter = queryExecute("
qAfter = queryTimed("
SELECT ID, BrandColor
FROM Businesses
WHERE BrandColor IS NOT NULL AND LENGTH(BrandColor) > 0

View file

@ -6,7 +6,7 @@
// Update them to use new category ID 25 (new Service Point)
try {
// First check how many tasks are affected
qCount = queryExecute("
qCount = queryTimed("
SELECT COUNT(*) as cnt FROM Tasks WHERE TaskCategoryID = 4
", [], { datasource: "payfrit" });
@ -14,7 +14,7 @@ try {
if (affectedCount > 0) {
// Update them to the new category
queryExecute("
queryTimed("
UPDATE Tasks SET TaskCategoryID = 25 WHERE TaskCategoryID = 4
", [], { datasource: "payfrit" });

View file

@ -44,7 +44,7 @@ try {
categoryID = 46; // Fries and Shakes
// Step 1: Create "Choose Flavor" modifier group under Shake
queryExecute("
queryTimed("
INSERT INTO Items (
CategoryID,
Name,
@ -80,7 +80,7 @@ try {
}, { datasource: "payfrit" });
// Get the new Choose Flavor ID
qNewGroup = queryExecute("
qNewGroup = queryTimed("
SELECT ID FROM Items
WHERE Name = 'Choose Flavor'
AND ParentItemID = :shakeItemID
@ -92,7 +92,7 @@ try {
arrayAppend(response.steps, "Created 'Choose Flavor' group with ID: " & chooseFlavorID);
// Step 2: Re-parent the three flavors under Choose Flavor
queryExecute("
queryTimed("
UPDATE Items
SET ParentItemID = :chooseFlavorID,
IsModifierTemplate = 0,
@ -108,14 +108,14 @@ try {
arrayAppend(response.steps, "Re-parented Chocolate, Strawberry, Vanilla under Choose Flavor");
// Step 3: Set Vanilla as default (common choice)
queryExecute("
queryTimed("
UPDATE Items SET IsCheckedByDefault = 1 WHERE ItemID = :vanillaID
", { vanillaID: vanillaID }, { datasource: "payfrit" });
arrayAppend(response.steps, "Set Vanilla as default flavor");
// Step 4: Remove old template links for the flavors
queryExecute("
queryTimed("
DELETE FROM lt_ItemID_TemplateItemID
WHERE TemplateItemID IN (:chocolateID, :strawberryID, :vanillaID)
", {
@ -127,7 +127,7 @@ try {
arrayAppend(response.steps, "Removed old template links for flavor items");
// Step 5: Create lt_ItemID_TemplateItemID for Shake -> Choose Flavor
queryExecute("
queryTimed("
INSERT INTO lt_ItemID_TemplateItemID (ItemID, TemplateItemID, SortOrder)
VALUES (:shakeItemID, :chooseFlavorID, 0)
ON DUPLICATE KEY UPDATE SortOrder = 0
@ -139,7 +139,7 @@ try {
arrayAppend(response.steps, "Created template link: Shake -> Choose Flavor");
// Step 6: Set RequiresChildSelection on shake
queryExecute("
queryTimed("
UPDATE Items
SET RequiresChildSelection = 1
WHERE ItemID = :shakeItemID

View file

@ -28,7 +28,7 @@ try {
if (childID <= 0) {
response["ERROR"] = "ChildBusinessID required";
} else {
queryExecute("
queryTimed("
UPDATE Businesses SET ParentBusinessID = :parentId WHERE ID = :childId
", {
parentId: { value = parentID > 0 ? parentID : javaCast("null", ""), cfsqltype = "cf_sql_integer", null = parentID == 0 },

View file

@ -5,7 +5,7 @@
<cfscript>
try {
// List all tables
tables = queryExecute("SHOW TABLES", {}, { datasource: "payfrit" });
tables = queryTimed("SHOW TABLES", {}, { datasource: "payfrit" });
tableList = [];
for (t in tables) {

View file

@ -25,7 +25,7 @@ try {
businessID = 17; // In and Out Burger
// Step 1: Get all parent items (burgers, combos, etc.)
qParentItems = queryExecute("
qParentItems = queryTimed("
SELECT i.ID, i.Name
FROM Items i
INNER JOIN Categories c ON c.ID = i.CategoryID
@ -38,7 +38,7 @@ try {
arrayAppend(response.steps, "Found " & qParentItems.recordCount & " parent items");
// Step 2: Get all direct children (level 1 modifiers) of parent items
qModifiers = queryExecute("
qModifiers = queryTimed("
SELECT
m.ItemID,
m.Name,
@ -90,7 +90,7 @@ try {
templateItemID = templateItem.ItemID;
// Mark as template
queryExecute("
queryTimed("
UPDATE Items SET IsModifierTemplate = 1 WHERE ItemID = :itemID
", { itemID: templateItemID }, { datasource: "payfrit" });
@ -110,7 +110,7 @@ try {
// Insert link (ignore duplicates)
try {
queryExecute("
queryTimed("
INSERT INTO lt_ItemID_TemplateItemID (ItemID, TemplateItemID, SortOrder)
VALUES (:itemID, :templateID, :sortOrder)
ON DUPLICATE KEY UPDATE SortOrder = :sortOrder
@ -142,12 +142,12 @@ try {
} else {
// Single instance - still mark as template for consistency
singleItem = instances[1];
queryExecute("
queryTimed("
UPDATE Items SET IsModifierTemplate = 1 WHERE ItemID = :itemID
", { itemID: singleItem.ItemID }, { datasource: "payfrit" });
// Create link
queryExecute("
queryTimed("
INSERT INTO lt_ItemID_TemplateItemID (ItemID, TemplateItemID, SortOrder)
VALUES (:itemID, :templateID, :sortOrder)
ON DUPLICATE KEY UPDATE SortOrder = :sortOrder

View file

@ -26,13 +26,13 @@ try {
// Find all businesses with items in unified schema
if (len(businessFilter)) {
qBusinesses = queryExecute("
qBusinesses = queryTimed("
SELECT DISTINCT BusinessID as BusinessID
FROM Items
WHERE BusinessID = :bid AND BusinessID > 0
", { bid: businessFilter }, { datasource: "payfrit" });
} else {
qBusinesses = queryExecute("
qBusinesses = queryTimed("
SELECT DISTINCT BusinessID as BusinessID
FROM Items
WHERE BusinessID > 0
@ -45,7 +45,7 @@ try {
try {
// Find category-like Items (parent=0, not collapsible, has children, not in template links)
qCategoryItems = queryExecute("
qCategoryItems = queryTimed("
SELECT DISTINCT
p.ID,
p.Name,
@ -64,20 +64,20 @@ try {
sortOrder = 0;
for (catItem in qCategoryItems) {
// Check if category already exists for this business with same name
qExisting = queryExecute("
qExisting = queryTimed("
SELECT ID FROM Categories
WHERE BusinessID = :bizId AND Name = :name
", { bizId: bizId, name: left(catItem.Name, 30) }, { datasource: "payfrit" });
if (qExisting.recordCount == 0) {
// Get next CategoryID
qMaxId = queryExecute("
qMaxId = queryTimed("
SELECT COALESCE(MAX(ID), 0) + 1 as nextId FROM Categories
", {}, { datasource: "payfrit" });
newCatId = qMaxId.nextId;
// Create new category with explicit ID
queryExecute("
queryTimed("
INSERT INTO Categories
(ID, BusinessID, ParentCategoryID, Name, SortOrder, AddedOn)
VALUES (:catId, :bizId, 0, :name, :sortOrder, NOW())
@ -94,7 +94,7 @@ try {
}
// Update all children of this category Item to have the new CategoryID
queryExecute("
queryTimed("
UPDATE Items
SET CategoryID = :catId
WHERE ParentItemID = :parentId
@ -105,7 +105,7 @@ try {
bizId: bizId
}, { datasource: "payfrit" });
qUpdated = queryExecute("SELECT ROW_COUNT() as cnt", {}, { datasource: "payfrit" });
qUpdated = queryTimed("SELECT ROW_COUNT() as cnt", {}, { datasource: "payfrit" });
bizResult.ItemsUpdated += qUpdated.cnt;
sortOrder++;

View file

@ -11,7 +11,7 @@ businessId = 27; // Big Dean's
// Modifiers are children of menu items or modifier templates
// Get category IDs (NOT modifier templates)
categoryIds = queryExecute("
categoryIds = queryTimed("
SELECT ID
FROM Items
WHERE BusinessID = :bizId
@ -26,7 +26,7 @@ for (cat in categoryIds) {
// Now get actual menu items (direct children of categories)
// Exclude items that are template options (their parent is a collapsible modifier group)
items = queryExecute("
items = queryTimed("
SELECT i.ID, i.Name
FROM Items i
WHERE i.BusinessID = :bizId
@ -97,7 +97,7 @@ for (item in items) {
newPrice = randRange(15, 23) - 0.01; // $14.99 - $22.99
}
queryExecute("
queryTimed("
UPDATE Items
SET Price = :price
WHERE ItemID = :itemId
@ -112,7 +112,7 @@ for (item in items) {
// Update modifier prices (children of menu items, NOT direct children of categories)
// Modifiers are items whose parent is NOT a category (i.e., parent is a menu item or modifier group)
modifiers = queryExecute("
modifiers = queryTimed("
SELECT ID, Name
FROM Items
WHERE BusinessID = :bizId
@ -148,7 +148,7 @@ for (mod in modifiers) {
}
}
queryExecute("
queryTimed("
UPDATE Items
SET Price = :price
WHERE ItemID = :itemId
@ -156,7 +156,7 @@ for (mod in modifiers) {
}
// Reset category prices to $0 (shouldn't have prices for reporting)
queryExecute("
queryTimed("
UPDATE Items
SET Price = 0
WHERE BusinessID = :bizId
@ -164,7 +164,7 @@ queryExecute("
", { bizId: businessId }, { datasource: "payfrit" });
// Reset modifier group prices to $0 (only options have prices)
queryExecute("
queryTimed("
UPDATE Items
SET Price = 0
WHERE BusinessID = :bizId

View file

@ -10,36 +10,36 @@
<cftry>
<!--- Disable foreign key checks temporarily --->
<cfset queryExecute("SET FOREIGN_KEY_CHECKS = 0", [], { datasource = "payfrit" })>
<cfset queryTimed("SET FOREIGN_KEY_CHECKS = 0", [], { datasource = "payfrit" })>
<!--- Clear Tasks --->
<cfset queryExecute("DELETE FROM Tasks", [], { datasource = "payfrit" })>
<cfset queryTimed("DELETE FROM Tasks", [], { datasource = "payfrit" })>
<!--- Clear Payments --->
<cftry>
<cfset queryExecute("DELETE FROM Payments", [], { datasource = "payfrit" })>
<cfset queryTimed("DELETE FROM Payments", [], { datasource = "payfrit" })>
<cfcatch></cfcatch>
</cftry>
<!--- Clear OrderLineItemModifiers if exists --->
<cftry>
<cfset queryExecute("DELETE FROM OrderLineItemModifiers", [], { datasource = "payfrit" })>
<cfset queryTimed("DELETE FROM OrderLineItemModifiers", [], { datasource = "payfrit" })>
<cfcatch></cfcatch>
</cftry>
<!--- Clear OrderLineItems --->
<cfset queryExecute("DELETE FROM OrderLineItems", [], { datasource = "payfrit" })>
<cfset queryTimed("DELETE FROM OrderLineItems", [], { datasource = "payfrit" })>
<!--- Clear Orders --->
<cfset queryExecute("DELETE FROM Orders", [], { datasource = "payfrit" })>
<cfset queryTimed("DELETE FROM Orders", [], { datasource = "payfrit" })>
<!--- Re-enable foreign key checks --->
<cfset queryExecute("SET FOREIGN_KEY_CHECKS = 1", [], { datasource = "payfrit" })>
<cfset queryTimed("SET FOREIGN_KEY_CHECKS = 1", [], { datasource = "payfrit" })>
<!--- Reset auto-increment counters --->
<cfset queryExecute("ALTER TABLE Tasks AUTO_INCREMENT = 1", [], { datasource = "payfrit" })>
<cfset queryExecute("ALTER TABLE Orders AUTO_INCREMENT = 1", [], { datasource = "payfrit" })>
<cfset queryExecute("ALTER TABLE OrderLineItems AUTO_INCREMENT = 1", [], { datasource = "payfrit" })>
<cfset queryTimed("ALTER TABLE Tasks AUTO_INCREMENT = 1", [], { datasource = "payfrit" })>
<cfset queryTimed("ALTER TABLE Orders AUTO_INCREMENT = 1", [], { datasource = "payfrit" })>
<cfset queryTimed("ALTER TABLE OrderLineItems AUTO_INCREMENT = 1", [], { datasource = "payfrit" })>
<cfset apiAbort({
"OK": true,

View file

@ -20,7 +20,7 @@ if (businessId <= 0 || userId <= 0) {
try {
// Update employee record
queryExecute("
queryTimed("
UPDATE Employees
SET IsActive = ?
WHERE BusinessID = ? AND UserID = ?
@ -31,7 +31,7 @@ try {
], { datasource: "payfrit" });
// Get updated record
q = queryExecute("
q = queryTimed("
SELECT e.ID, e.BusinessID, e.UserID, e.StatusID,
CAST(e.IsActive AS UNSIGNED) AS IsActive,
b.Name, u.FirstName, u.LastName

View file

@ -6,7 +6,7 @@
response = { "OK": false };
try {
queryExecute("
queryTimed("
UPDATE Businesses SET HeaderImageExtension = 'jpg' WHERE ID = 37
", {}, { datasource: "payfrit" });

View file

@ -13,7 +13,7 @@ try {
lazyDaisyID = 37;
// Get all service points for Lazy Daisy
qServicePoints = queryExecute("
qServicePoints = queryTimed("
SELECT ID, Name AS Name
FROM ServicePoints
WHERE BusinessID = :bizID AND IsActive = 1
@ -28,7 +28,7 @@ try {
beaconName = "Beacon - " & sp.Name;
// Check if beacon already exists for this business with this name
qExisting = queryExecute("
qExisting = queryTimed("
SELECT ID FROM Beacons
WHERE BusinessID = :bizId AND Name = :name
", { bizId: lazyDaisyID, name: beaconName }, { datasource: "payfrit" });
@ -37,7 +37,7 @@ try {
// Generate a unique UUID for this beacon (32 hex chars, no dashes)
beaconUUID = "PAYFRIT00037" & numberFormat(sp.ID, "0000000000000000000");
queryExecute("
queryTimed("
INSERT INTO Beacons (BusinessID, Name, UUID, IsActive)
VALUES (:bizId, :name, :uuid, 1)
", {
@ -46,11 +46,11 @@ try {
uuid: beaconUUID
}, { datasource: "payfrit" });
qNewBeacon = queryExecute("SELECT LAST_INSERT_ID() as id", {}, { datasource: "payfrit" });
qNewBeacon = queryTimed("SELECT LAST_INSERT_ID() as id", {}, { datasource: "payfrit" });
newBeaconId = qNewBeacon.id;
// Assign beacon directly to service point
queryExecute("
queryTimed("
UPDATE ServicePoints
SET BeaconID = :beaconId, AssignedByUserID = 1
WHERE ID = :spId AND BusinessID = :bizId
@ -68,7 +68,7 @@ try {
}
// Get final status
qFinal = queryExecute("
qFinal = queryTimed("
SELECT sp.ID AS ServicePointID, sp.BeaconID, sp.BusinessID AS BusinessID,
b.Name AS BeaconName, b.UUID, sp.Name AS ServicePointName,
biz.Name AS BusinessName

View file

@ -13,18 +13,18 @@ try {
// Hours: Mon-Thu: 11am-10pm, Fri-Sat: 11am-11pm, Sun: 11am-10pm
// Get California StateID
qState = queryExecute("SELECT ID FROM tt_States WHERE Abbreviation = 'CA' LIMIT 1");
qState = queryTimed("SELECT ID FROM tt_States WHERE Abbreviation = 'CA' LIMIT 1");
stateId = qState.recordCount > 0 ? qState.ID : 5; // Default to 5 if not found
// Check if Big Dean's already has an address
existingAddr = queryExecute("
existingAddr = queryTimed("
SELECT ID FROM Addresses
WHERE BusinessID = :bizId AND UserID = 0
", { bizId: businessId });
if (existingAddr.recordCount == 0) {
// Insert new address
queryExecute("
queryTimed("
INSERT INTO Addresses (UserID, BusinessID, AddressTypeID, Line1, City, StateID, ZIPCode, IsDeleted, AddedOn)
VALUES (0, :bizId, '2', :line1, :city, :stateId, :zip, 0, NOW())
", {
@ -37,7 +37,7 @@ try {
response["ADDRESS_ACTION"] = "inserted";
} else {
// Update existing address
queryExecute("
queryTimed("
UPDATE Addresses
SET Line1 = :line1, City = :city, StateID = :stateId, ZIPCode = :zip
WHERE BusinessID = :bizId AND UserID = 0
@ -52,7 +52,7 @@ try {
}
// Check existing hours for this business
existingHours = queryExecute("
existingHours = queryTimed("
SELECT COUNT(*) as cnt FROM Hours WHERE BusinessID = :bizId
", { bizId: businessId });
@ -64,39 +64,39 @@ try {
// Sun: 11am-10pm (day 1)
// Sunday (1): 11am-10pm
queryExecute("INSERT INTO Hours (BusinessID, DayID, OpenTime, ClosingTime) VALUES (:bizId, 1, '11:00:00', '22:00:00')", { bizId: businessId });
queryTimed("INSERT INTO Hours (BusinessID, DayID, OpenTime, ClosingTime) VALUES (:bizId, 1, '11:00:00', '22:00:00')", { bizId: businessId });
// Monday (2): 11am-10pm
queryExecute("INSERT INTO Hours (BusinessID, DayID, OpenTime, ClosingTime) VALUES (:bizId, 2, '11:00:00', '22:00:00')", { bizId: businessId });
queryTimed("INSERT INTO Hours (BusinessID, DayID, OpenTime, ClosingTime) VALUES (:bizId, 2, '11:00:00', '22:00:00')", { bizId: businessId });
// Tuesday (3): 11am-10pm
queryExecute("INSERT INTO Hours (BusinessID, DayID, OpenTime, ClosingTime) VALUES (:bizId, 3, '11:00:00', '22:00:00')", { bizId: businessId });
queryTimed("INSERT INTO Hours (BusinessID, DayID, OpenTime, ClosingTime) VALUES (:bizId, 3, '11:00:00', '22:00:00')", { bizId: businessId });
// Wednesday (4): 11am-10pm
queryExecute("INSERT INTO Hours (BusinessID, DayID, OpenTime, ClosingTime) VALUES (:bizId, 4, '11:00:00', '22:00:00')", { bizId: businessId });
queryTimed("INSERT INTO Hours (BusinessID, DayID, OpenTime, ClosingTime) VALUES (:bizId, 4, '11:00:00', '22:00:00')", { bizId: businessId });
// Thursday (5): 11am-10pm
queryExecute("INSERT INTO Hours (BusinessID, DayID, OpenTime, ClosingTime) VALUES (:bizId, 5, '11:00:00', '22:00:00')", { bizId: businessId });
queryTimed("INSERT INTO Hours (BusinessID, DayID, OpenTime, ClosingTime) VALUES (:bizId, 5, '11:00:00', '22:00:00')", { bizId: businessId });
// Friday (6): 11am-11pm
queryExecute("INSERT INTO Hours (BusinessID, DayID, OpenTime, ClosingTime) VALUES (:bizId, 6, '11:00:00', '23:00:00')", { bizId: businessId });
queryTimed("INSERT INTO Hours (BusinessID, DayID, OpenTime, ClosingTime) VALUES (:bizId, 6, '11:00:00', '23:00:00')", { bizId: businessId });
// Saturday (7): 11am-11pm
queryExecute("INSERT INTO Hours (BusinessID, DayID, OpenTime, ClosingTime) VALUES (:bizId, 7, '11:00:00', '23:00:00')", { bizId: businessId });
queryTimed("INSERT INTO Hours (BusinessID, DayID, OpenTime, ClosingTime) VALUES (:bizId, 7, '11:00:00', '23:00:00')", { bizId: businessId });
response["HOURS_ACTION"] = "inserted 7 days";
} else {
// Update existing hours
// Mon-Thu: 11am-10pm
queryExecute("UPDATE Hours SET OpenTime = '11:00:00', ClosingTime = '22:00:00' WHERE BusinessID = :bizId AND DayID IN (1, 2, 3, 4, 5)", { bizId: businessId });
queryTimed("UPDATE Hours SET OpenTime = '11:00:00', ClosingTime = '22:00:00' WHERE BusinessID = :bizId AND DayID IN (1, 2, 3, 4, 5)", { bizId: businessId });
// Fri-Sat: 11am-11pm
queryExecute("UPDATE Hours SET OpenTime = '11:00:00', ClosingTime = '23:00:00' WHERE BusinessID = :bizId AND DayID IN (6, 7)", { bizId: businessId });
queryTimed("UPDATE Hours SET OpenTime = '11:00:00', ClosingTime = '23:00:00' WHERE BusinessID = :bizId AND DayID IN (6, 7)", { bizId: businessId });
response["HOURS_ACTION"] = "updated";
}
// Update phone on Businesses table (if column exists)
try {
queryExecute("UPDATE Businesses SET Phone = :phone WHERE ID = :bizId", {
queryTimed("UPDATE Businesses SET Phone = :phone WHERE ID = :bizId", {
phone: "(310) 393-2666",
bizId: businessId
});
@ -106,14 +106,14 @@ try {
}
// Verify the data
address = queryExecute("
address = queryTimed("
SELECT a.*, s.Abbreviation
FROM Addresses a
LEFT JOIN tt_States s ON s.ID = a.StateID
WHERE a.BusinessID = :bizId AND a.UserID = 0
", { bizId: businessId });
hours = queryExecute("
hours = queryTimed("
SELECT h.*, d.Name AS DayName
FROM Hours h
JOIN tt_Days d ON d.ID = h.DayID

View file

@ -8,19 +8,19 @@ response = { "OK": false };
try {
// Check if Big Dean's already has stations
existing = queryExecute("
existing = queryTimed("
SELECT COUNT(*) as cnt FROM Stations WHERE BusinessID = :bizId
", { bizId: businessId });
if (existing.cnt == 0) {
// Insert Kitchen station
queryExecute("
queryTimed("
INSERT INTO Stations (BusinessID, Name, Color, SortOrder, IsActive)
VALUES (:bizId, 'Kitchen', :color1, 1, 1)
", { bizId: businessId, color1: "##FF5722" });
// Insert Bar station
queryExecute("
queryTimed("
INSERT INTO Stations (BusinessID, Name, Color, SortOrder, IsActive)
VALUES (:bizId, 'Bar', :color2, 2, 1)
", { bizId: businessId, color2: "##2196F3" });
@ -31,7 +31,7 @@ try {
}
// Get current stations
stations = queryExecute("
stations = queryTimed("
SELECT ID, Name, Color, SortOrder
FROM Stations
WHERE BusinessID = :bizId AND IsActive = 1

View file

@ -9,21 +9,21 @@ try {
lazyDaisyID = 37;
// Get all beacons
qBeacons = queryExecute("SELECT ID, UUID FROM Beacons", {}, { datasource: "payfrit" });
qBeacons = queryTimed("SELECT ID, UUID FROM Beacons", {}, { datasource: "payfrit" });
response.steps.append("Found " & qBeacons.recordCount & " beacons");
// Create service point for Table 1 if it doesn't exist
qSP = queryExecute("
qSP = queryTimed("
SELECT ID FROM ServicePoints
WHERE BusinessID = :bizID AND Name = 'Table 1'
", { bizID: lazyDaisyID }, { datasource: "payfrit" });
if (qSP.recordCount == 0) {
queryExecute("
queryTimed("
INSERT INTO ServicePoints (BusinessID, Name)
VALUES (:bizID, 'Table 1')
", { bizID: lazyDaisyID }, { datasource: "payfrit" });
qSP = queryExecute("SELECT LAST_INSERT_ID() as id", {}, { datasource: "payfrit" });
qSP = queryTimed("SELECT LAST_INSERT_ID() as id", {}, { datasource: "payfrit" });
servicePointID = qSP.id;
response.steps.append("Created service point 'Table 1' (ID: " & servicePointID & ")");
} else {
@ -36,13 +36,13 @@ try {
beaconID = qBeacons.ID[i];
// Unassign this beacon from any other service point first
queryExecute("
queryTimed("
UPDATE ServicePoints SET BeaconID = NULL, AssignedByUserID = NULL
WHERE BeaconID = :beaconID
", { beaconID: beaconID }, { datasource: "payfrit" });
// Assign beacon to Table 1 service point
queryExecute("
queryTimed("
UPDATE ServicePoints SET BeaconID = :beaconID, AssignedByUserID = 1
WHERE ID = :spID AND BusinessID = :bizID
", { beaconID: beaconID, bizID: lazyDaisyID, spID: servicePointID }, { datasource: "payfrit" });
@ -50,7 +50,7 @@ try {
}
// Get final status
qFinal = queryExecute("
qFinal = queryTimed("
SELECT sp.ID AS ServicePointID, sp.BeaconID, sp.BusinessID AS BusinessID,
b.Name AS BeaconName, b.UUID, sp.Name AS ServicePointName,
biz.Name AS BusinessName

View file

@ -20,7 +20,7 @@ response = { "OK": false, "steps": [] };
try {
// Step 1: Add IsModifierTemplate column if it doesn't exist
try {
queryExecute("
queryTimed("
ALTER TABLE Items ADD COLUMN IsModifierTemplate TINYINT(1) DEFAULT 0
", {}, { datasource: "payfrit" });
arrayAppend(response.steps, "Added IsModifierTemplate column");
@ -34,7 +34,7 @@ try {
// Step 2: Create lt_ItemID_TemplateItemID table if it doesn't exist
try {
queryExecute("
queryTimed("
CREATE TABLE IF NOT EXISTS lt_ItemID_TemplateItemID (
ID INT AUTO_INCREMENT PRIMARY KEY,
ItemID INT NOT NULL,

View file

@ -10,7 +10,7 @@
<cftry>
<!--- Create Stations table if it doesn't exist --->
<cfset queryExecute("
<cfset queryTimed("
CREATE TABLE IF NOT EXISTS Stations (
ID INT AUTO_INCREMENT PRIMARY KEY,
BusinessID INT NOT NULL,
@ -25,7 +25,7 @@
<!--- Add StationID column to Items table if it doesn't exist --->
<cftry>
<cfset queryExecute("
<cfset queryTimed("
ALTER TABLE Items ADD COLUMN StationID INT DEFAULT NULL
", [], { datasource = "payfrit" })>
<cfset stationColumnAdded = true>
@ -38,7 +38,7 @@
<!--- Add foreign key if column was just added --->
<cfif stationColumnAdded>
<cftry>
<cfset queryExecute("
<cfset queryTimed("
ALTER TABLE Items ADD FOREIGN KEY (StationID) REFERENCES Stations(ID)
", [], { datasource = "payfrit" })>
<cfcatch></cfcatch>
@ -46,12 +46,12 @@
</cfif>
<!--- Create some default stations for business 1 (In and Out Burger) if none exist --->
<cfset qCheck = queryExecute("
<cfset qCheck = queryTimed("
SELECT COUNT(*) AS cnt FROM Stations WHERE BusinessID = 1
", [], { datasource = "payfrit" })>
<cfif qCheck.cnt EQ 0>
<cfset queryExecute("
<cfset queryTimed("
INSERT INTO Stations (BusinessID, Name, Color, SortOrder) VALUES
(1, 'Grill', '##FF5722', 1),
(1, 'Fry', '##FFC107', 2),

View file

@ -9,27 +9,27 @@ fromBiz = 17; // In-N-Out
toBiz = 27; // Big Dean's
// Remove mapping for source business
queryExecute("
queryTimed("
DELETE FROM lt_BeaconsID_BusinessesID
WHERE BusinessID = :fromBiz
", { fromBiz: fromBiz }, { datasource: "payfrit" });
// Add mapping for target business (for beacons owned by source)
queryExecute("
queryTimed("
INSERT INTO lt_BeaconsID_BusinessesID (BeaconID, BusinessID)
SELECT ID, :toBiz FROM Beacons WHERE BusinessID = :fromBiz
ON DUPLICATE KEY UPDATE ID = ID
", { toBiz: toBiz, fromBiz: fromBiz }, { datasource: "payfrit" });
// Clear ServicePoints.BeaconID for source business (no longer valid)
queryExecute("
queryTimed("
UPDATE ServicePoints
SET BeaconID = NULL, AssignedByUserID = NULL
WHERE BusinessID = :fromBiz AND BeaconID IS NOT NULL
", { fromBiz: fromBiz }, { datasource: "payfrit" });
// Get current state
q = queryExecute("
q = queryTimed("
SELECT sp.ID AS ServicePointID, sp.BeaconID, sp.BusinessID AS BusinessID,
b.Name AS BeaconName, biz.Name AS BusinessName,
sp.Name AS ServicePointName

View file

@ -4,7 +4,7 @@
<cfset result = {}>
<cftry>
<cfset queryExecute(
<cfset queryTimed(
"
INSERT INTO Tasks (
BusinessID,
@ -22,7 +22,7 @@
{ datasource = "payfrit" }
)>
<cfset qCount = queryExecute("SELECT COUNT(*) AS cnt FROM Tasks", [], { datasource = "payfrit" })>
<cfset qCount = queryTimed("SELECT COUNT(*) AS cnt FROM Tasks", [], { datasource = "payfrit" })>
<cfset result = {
"OK": true,

View file

@ -1,7 +1,7 @@
<cfsetting showdebugoutput="false">
<cfcontent type="application/json; charset=utf-8" reset="true">
<cfscript>
qTask = queryExecute("
qTask = queryTimed("
SELECT ID, TaskTypeID, ClaimedByUserID, CompletedOn
FROM Tasks
WHERE ID = 57

View file

@ -9,27 +9,27 @@ oldBusinessId = 37; // previous mapping
newBusinessId = 17;
// Remove old mapping
queryExecute("
queryTimed("
DELETE FROM lt_BeaconsID_BusinessesID
WHERE BeaconID = :beaconId AND BusinessID = :oldBizId
", { beaconId: beaconId, oldBizId: oldBusinessId }, { datasource: "payfrit" });
// Add new mapping
queryExecute("
queryTimed("
INSERT INTO lt_BeaconsID_BusinessesID (BeaconID, BusinessID)
VALUES (:beaconId, :newBizId)
ON DUPLICATE KEY UPDATE ID = ID
", { beaconId: beaconId, newBizId: newBusinessId }, { datasource: "payfrit" });
// Clear ServicePoints.BeaconID for old business where this beacon was assigned
queryExecute("
queryTimed("
UPDATE ServicePoints
SET BeaconID = NULL, AssignedByUserID = NULL
WHERE BeaconID = :beaconId AND BusinessID = :oldBizId
", { beaconId: beaconId, oldBizId: oldBusinessId }, { datasource: "payfrit" });
// Get current state
q = queryExecute("
q = queryTimed("
SELECT
b.ID AS BeaconID,
b.UUID,

View file

@ -12,7 +12,7 @@ hours = "Mon-Thu: 11am-10pm, Fri-Sat: 11am-11pm, Sun: 11am-10pm";
try {
// Update phone and hours on Businesses table
queryExecute("
queryTimed("
UPDATE Businesses
SET Phone = :phone,
Hours = :hours
@ -24,14 +24,14 @@ try {
}, { datasource: "payfrit" });
// Update or insert address in Addresses table
qAddr = queryExecute("
qAddr = queryTimed("
SELECT ID FROM Addresses
WHERE BusinessID = :bizId AND IsDeleted = 0
LIMIT 1
", { bizId: businessId }, { datasource: "payfrit" });
if (qAddr.recordCount > 0) {
queryExecute("
queryTimed("
UPDATE Addresses
SET Line1 = :line1, City = :city, ZIPCode = :zip
WHERE ID = :addrId
@ -42,7 +42,7 @@ try {
addrId: qAddr.ID
}, { datasource: "payfrit" });
} else {
queryExecute("
queryTimed("
INSERT INTO Addresses (BusinessID, UserID, AddressTypeID, Line1, City, ZIPCode, AddedOn)
VALUES (:bizId, 0, 'business', :line1, :city, :zip, NOW())
", {
@ -54,7 +54,7 @@ try {
}
// Get updated record
updated = queryExecute("
updated = queryTimed("
SELECT ID, Name, Phone, Hours
FROM Businesses
WHERE ID = :bizId

View file

@ -0,0 +1,313 @@
<cfsetting showdebugoutput="false">
<cfsetting enablecfoutputonly="false">
<cfscript>
// Localhost-only protection
remoteAddr = cgi.REMOTE_ADDR;
if (remoteAddr != "127.0.0.1" && remoteAddr != "::1" && remoteAddr != "0:0:0:0:0:0:0:1" && remoteAddr != "10.10.0.2") {
writeOutput("Forbidden"); abort;
}
</cfscript>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>API Performance Dashboard</title>
<style>
* { box-sizing: border-box; margin: 0; padding: 0; }
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif; background: #0f1117; color: #e1e4e8; padding: 20px; }
h1 { font-size: 22px; font-weight: 600; margin-bottom: 16px; color: #fff; }
.controls { display: flex; gap: 10px; margin-bottom: 20px; align-items: center; flex-wrap: wrap; }
.controls label { font-size: 13px; color: #8b949e; }
.controls select, .controls input { background: #1c1f26; border: 1px solid #30363d; color: #e1e4e8; padding: 6px 10px; border-radius: 6px; font-size: 13px; }
.controls button { background: #238636; color: #fff; border: none; padding: 6px 16px; border-radius: 6px; font-size: 13px; cursor: pointer; font-weight: 500; }
.controls button:hover { background: #2ea043; }
.controls button.secondary { background: #30363d; }
.controls button.secondary:hover { background: #3d444d; }
.summary-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 12px; margin-bottom: 24px; }
.card { background: #1c1f26; border: 1px solid #30363d; border-radius: 8px; padding: 16px; }
.card .label { font-size: 11px; color: #8b949e; text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 4px; }
.card .value { font-size: 28px; font-weight: 700; color: #fff; }
.card .unit { font-size: 13px; color: #8b949e; font-weight: 400; }
.card .sub { font-size: 13px; color: #8b949e; font-weight: 400; }
.section { margin-bottom: 28px; }
.section h2 { font-size: 15px; font-weight: 600; margin-bottom: 10px; color: #c9d1d9; display: flex; align-items: center; gap: 8px; }
.section h2 .badge { background: #30363d; padding: 2px 8px; border-radius: 10px; font-size: 11px; font-weight: 500; color: #8b949e; }
table { width: 100%; border-collapse: collapse; font-size: 13px; }
thead th { text-align: left; padding: 8px 12px; border-bottom: 1px solid #30363d; color: #8b949e; font-weight: 500; font-size: 11px; text-transform: uppercase; letter-spacing: 0.5px; white-space: nowrap; }
thead th.num { text-align: right; }
tbody td { padding: 8px 12px; border-bottom: 1px solid #1c1f26; }
tbody td.num { text-align: right; font-variant-numeric: tabular-nums; }
tbody tr:hover { background: #1c1f26; }
tbody td.endpoint { font-family: 'SF Mono', 'Fira Code', monospace; font-size: 12px; color: #58a6ff; }
.bar-cell { position: relative; }
.bar-bg { position: absolute; left: 0; top: 2px; bottom: 2px; border-radius: 3px; opacity: 0.15; }
.bar-db { background: #f0883e; }
.bar-app { background: #58a6ff; }
.bar-wrap { display: flex; height: 18px; border-radius: 3px; overflow: hidden; min-width: 80px; }
.bar-seg-db { background: #f0883e; height: 100%; }
.bar-seg-app { background: #58a6ff; height: 100%; }
.legend { display: flex; gap: 16px; font-size: 11px; color: #8b949e; margin-bottom: 12px; }
.legend span { display: flex; align-items: center; gap: 4px; }
.legend .dot { width: 10px; height: 10px; border-radius: 2px; }
.legend .dot.db { background: #f0883e; }
.legend .dot.app { background: #58a6ff; }
.status { padding: 8px 12px; background: #1c1f26; border-radius: 6px; font-size: 12px; color: #8b949e; margin-bottom: 16px; }
.status.error { border: 1px solid #da3633; color: #f85149; }
.status.loading { border: 1px solid #30363d; }
.tag { display: inline-block; padding: 1px 6px; border-radius: 4px; font-size: 11px; font-weight: 500; }
.tag.fast { background: #23863620; color: #3fb950; }
.tag.ok { background: #d29b0020; color: #d29922; }
.tag.slow { background: #da363320; color: #f85149; }
.auto-refresh { display: flex; align-items: center; gap: 6px; margin-left: auto; }
.auto-refresh input[type=checkbox] { accent-color: #238636; }
.timestamp { font-size: 11px; color: #484f58; }
</style>
</head>
<body>
<h1>API Performance Dashboard</h1>
<div class="controls">
<label>Time range:
<select id="hours">
<option value="1">Last 1 hour</option>
<option value="6">Last 6 hours</option>
<option value="24" selected>Last 24 hours</option>
<option value="72">Last 3 days</option>
<option value="168">Last 7 days</option>
<option value="720">Last 30 days</option>
</select>
</label>
<label>Rows:
<input type="number" id="limit" value="20" min="5" max="100" style="width:60px">
</label>
<button onclick="loadAll()">Refresh</button>
<div class="auto-refresh">
<input type="checkbox" id="autoRefresh">
<label for="autoRefresh" style="font-size:12px;color:#8b949e;cursor:pointer">Auto-refresh 30s</label>
</div>
<span class="timestamp" id="lastUpdated"></span>
</div>
<div id="status" class="status loading">Loading...</div>
<div id="summarySection" class="section" style="display:none">
<div class="summary-cards" id="summaryCards"></div>
</div>
<div class="legend">
<span><span class="dot db"></span> DB time</span>
<span><span class="dot app"></span> App time</span>
</div>
<div id="countSection" class="section" style="display:none">
<h2>Top Endpoints by Volume <span class="badge" id="countBadge"></span></h2>
<div style="overflow-x:auto"><table id="countTable"><thead></thead><tbody></tbody></table></div>
</div>
<div id="latencySection" class="section" style="display:none">
<h2>Top Endpoints by Latency <span class="badge" id="latencyBadge"></span></h2>
<div style="overflow-x:auto"><table id="latencyTable"><thead></thead><tbody></tbody></table></div>
</div>
<div id="slowSection" class="section" style="display:none">
<h2>Slowest Individual Requests <span class="badge" id="slowBadge"></span></h2>
<div style="overflow-x:auto"><table id="slowTable"><thead></thead><tbody></tbody></table></div>
</div>
<script>
const API = 'perf.cfm';
let refreshTimer = null;
function qs(s) { return document.querySelector(s); }
function fmt(n) { return n == null ? '-' : Number(n).toLocaleString(); }
function fmtDate(s) {
if (!s || s === 'none') return 'none';
var d = new Date(s.replace(' ', 'T'));
if (isNaN(d)) return s;
var mo = d.getMonth() + 1, dy = d.getDate(), yr = String(d.getFullYear()).slice(-2);
var h = d.getHours(), mi = String(d.getMinutes()).padStart(2, '0'), ap = h >= 12 ? 'p' : 'a';
h = h % 12 || 12;
return { date: mo + '/' + dy + '/' + yr, time: h + ':' + mi + ap };
}
function fmtMs(n) {
if (n == null) return '-';
n = Number(n);
if (n < 100) return '<span class="tag fast">' + n + 'ms</span>';
if (n < 500) return '<span class="tag ok">' + n + 'ms</span>';
return '<span class="tag slow">' + n + 'ms</span>';
}
function fmtBytes(n) {
if (!n) return '-';
n = Number(n);
if (n < 1024) return n + ' B';
if (n < 1048576) return (n / 1024).toFixed(1) + ' KB';
return (n / 1048576).toFixed(1) + ' MB';
}
function pct(part, total) { return total > 0 ? Math.round(part / total * 100) : 0; }
function timeBar(dbMs, appMs) {
var total = (dbMs || 0) + (appMs || 0);
if (total === 0) return '';
var dbPct = pct(dbMs, total);
var appPct = 100 - dbPct;
return '<div class="bar-wrap" title="DB: ' + dbMs + 'ms / App: ' + appMs + 'ms">'
+ '<div class="bar-seg-db" style="width:' + dbPct + '%"></div>'
+ '<div class="bar-seg-app" style="width:' + appPct + '%"></div>'
+ '</div>';
}
function endpointName(ep) {
return ep.replace(/^\/api\//, '');
}
async function fetchView(view) {
var h = qs('#hours').value;
var l = qs('#limit').value;
var r = await fetch(API + '?view=' + view + '&hours=' + h + '&limit=' + l);
return r.json();
}
async function loadAll() {
qs('#status').className = 'status loading';
qs('#status').textContent = 'Loading...';
qs('#status').style.display = '';
try {
var [summary, count, latency, slow] = await Promise.all([
fetchView('summary'), fetchView('count'), fetchView('latency'), fetchView('slow')
]);
if (!summary.OK) throw new Error(summary.MESSAGE || summary.ERROR);
qs('#status').style.display = 'none';
// Summary cards
var s = summary.DATA;
qs('#summaryCards').innerHTML =
card('Total Requests', fmt(s.TotalRequests), '') +
card('Unique Endpoints', fmt(s.UniqueEndpoints), '') +
card('Avg Latency', s.OverallAvgMs || 0, 'ms') +
card('Max Latency', s.OverallMaxMs || 0, 'ms') +
card('Avg DB Time', s.OverallAvgDbMs || 0, 'ms') +
card('Avg App Time', s.OverallAvgAppMs || 0, 'ms') +
card('Avg Queries', s.OverallAvgQueries || 0, '/req') +
cardDate('Data Since', fmtDate(s.FirstLog));
qs('#summarySection').style.display = '';
// Count table
renderCountTable(count.DATA || []);
// Latency table
renderLatencyTable(latency.DATA || []);
// Slow table
renderSlowTable(slow.DATA || []);
qs('#lastUpdated').textContent = 'Updated ' + new Date().toLocaleTimeString();
} catch (e) {
qs('#status').className = 'status error';
qs('#status').textContent = 'Error: ' + e.message;
qs('#status').style.display = '';
}
}
function card(label, value, unit) {
return '<div class="card"><div class="label">' + label + '</div><div class="value">' + value + ' <span class="unit">' + unit + '</span></div></div>';
}
function cardDate(label, dt) {
if (!dt || !dt.date) return card(label, 'none', '');
return '<div class="card"><div class="label">' + label + '</div><div class="value">' + dt.date + '</div><div class="sub">' + dt.time + '</div></div>';
}
function renderCountTable(data) {
if (!data.length) { qs('#countSection').style.display = 'none'; return; }
qs('#countBadge').textContent = data.length + ' endpoints';
var maxCalls = Math.max(...data.map(r => r.Calls));
var html = '<thead><tr><th>Endpoint</th><th class="num">Calls</th><th class="num">Avg</th><th class="num">DB</th><th class="num">App</th><th>DB / App Split</th><th class="num">Max</th><th class="num">Queries</th><th class="num">Avg Size</th></tr></thead><tbody>';
data.forEach(function(r) {
html += '<tr>'
+ '<td class="endpoint">' + endpointName(r.Endpoint) + '</td>'
+ '<td class="num">' + fmt(r.Calls) + '</td>'
+ '<td class="num">' + fmtMs(r.AvgMs) + '</td>'
+ '<td class="num">' + fmt(r.AvgDbMs) + 'ms</td>'
+ '<td class="num">' + fmt(r.AvgAppMs) + 'ms</td>'
+ '<td>' + timeBar(r.AvgDbMs, r.AvgAppMs) + '</td>'
+ '<td class="num">' + fmtMs(r.MaxMs) + '</td>'
+ '<td class="num">' + r.AvgQueries + '</td>'
+ '<td class="num">' + fmtBytes(r.AvgBytes) + '</td>'
+ '</tr>';
});
html += '</tbody>';
qs('#countTable').innerHTML = html;
qs('#countSection').style.display = '';
}
function renderLatencyTable(data) {
if (!data.length) { qs('#latencySection').style.display = 'none'; return; }
qs('#latencyBadge').textContent = data.length + ' endpoints';
var html = '<thead><tr><th>Endpoint</th><th class="num">Calls</th><th class="num">Avg</th><th class="num">DB</th><th class="num">App</th><th>DB / App Split</th><th class="num">Max</th><th class="num">Queries</th></tr></thead><tbody>';
data.forEach(function(r) {
html += '<tr>'
+ '<td class="endpoint">' + endpointName(r.Endpoint) + '</td>'
+ '<td class="num">' + fmt(r.Calls) + '</td>'
+ '<td class="num">' + fmtMs(r.AvgMs) + '</td>'
+ '<td class="num">' + fmt(r.AvgDbMs) + 'ms</td>'
+ '<td class="num">' + fmt(r.AvgAppMs) + 'ms</td>'
+ '<td>' + timeBar(r.AvgDbMs, r.AvgAppMs) + '</td>'
+ '<td class="num">' + fmtMs(r.MaxMs) + '</td>'
+ '<td class="num">' + r.AvgQueries + '</td>'
+ '</tr>';
});
html += '</tbody>';
qs('#latencyTable').innerHTML = html;
qs('#latencySection').style.display = '';
}
function renderSlowTable(data) {
if (!data.length) { qs('#slowSection').style.display = 'none'; return; }
qs('#slowBadge').textContent = data.length + ' requests';
var html = '<thead><tr><th>Endpoint</th><th class="num">Total</th><th class="num">DB</th><th class="num">App</th><th>DB / App Split</th><th class="num">Queries</th><th class="num">Size</th><th class="num">Biz</th><th>When</th></tr></thead><tbody>';
data.forEach(function(r) {
html += '<tr>'
+ '<td class="endpoint">' + endpointName(r.Endpoint) + '</td>'
+ '<td class="num">' + fmtMs(r.TotalMs) + '</td>'
+ '<td class="num">' + fmt(r.DbMs) + 'ms</td>'
+ '<td class="num">' + fmt(r.AppMs) + 'ms</td>'
+ '<td>' + timeBar(r.DbMs, r.AppMs) + '</td>'
+ '<td class="num">' + r.QueryCount + '</td>'
+ '<td class="num">' + fmtBytes(r.ResponseBytes) + '</td>'
+ '<td class="num">' + (r.BusinessID || '-') + '</td>'
+ '<td style="font-size:11px;color:#8b949e;white-space:nowrap">' + (r.LoggedAt || '') + '</td>'
+ '</tr>';
});
html += '</tbody>';
qs('#slowTable').innerHTML = html;
qs('#slowSection').style.display = '';
}
// Auto-refresh
qs('#autoRefresh').addEventListener('change', function() {
if (this.checked) {
refreshTimer = setInterval(loadAll, 30000);
} else {
clearInterval(refreshTimer);
refreshTimer = null;
}
});
// Load on page open
loadAll();
</script>
</body>
</html>

179
api/admin/perf.cfm Normal file
View file

@ -0,0 +1,179 @@
<cfsetting showdebugoutput="false">
<cfsetting enablecfoutputonly="true">
<cfcontent type="application/json; charset=utf-8" reset="true">
<cfheader name="Cache-Control" value="no-store">
<cfscript>
function apiAbort(payload) {
writeOutput(serializeJSON(payload));
abort;
}
// Localhost-only protection
remoteAddr = cgi.REMOTE_ADDR;
if (remoteAddr != "127.0.0.1" && remoteAddr != "::1" && remoteAddr != "0:0:0:0:0:0:0:1" && remoteAddr != "10.10.0.2") {
apiAbort({ "OK": false, "ERROR": "forbidden" });
}
try {
// Parse parameters
view = structKeyExists(url, "view") ? lcase(url.view) : "count";
hours = structKeyExists(url, "hours") ? val(url.hours) : 24;
if (hours <= 0 || hours > 720) hours = 24;
limitRows = structKeyExists(url, "limit") ? val(url.limit) : 20;
if (limitRows <= 0 || limitRows > 100) limitRows = 20;
// Flush any buffered metrics first
flushPerfBuffer();
response = { "OK": true, "VIEW": view, "HOURS": hours };
if (view == "count") {
// Top endpoints by call count
q = queryExecute("
SELECT
Endpoint,
COUNT(*) as Calls,
ROUND(AVG(TotalMs)) as AvgMs,
ROUND(AVG(DbMs)) as AvgDbMs,
ROUND(AVG(AppMs)) as AvgAppMs,
MAX(TotalMs) as MaxMs,
ROUND(AVG(QueryCount), 1) as AvgQueries,
ROUND(AVG(ResponseBytes)) as AvgBytes
FROM ApiPerfLogs
WHERE LoggedAt > DATE_SUB(NOW(), INTERVAL :hours HOUR)
GROUP BY Endpoint
ORDER BY Calls DESC
LIMIT :lim
", {
hours: { value: hours, cfsqltype: "cf_sql_integer" },
lim: { value: limitRows, cfsqltype: "cf_sql_integer" }
}, { datasource: "payfrit" });
rows = [];
for (row in q) {
arrayAppend(rows, {
"Endpoint": row.Endpoint,
"Calls": row.Calls,
"AvgMs": row.AvgMs,
"AvgDbMs": row.AvgDbMs,
"AvgAppMs": row.AvgAppMs,
"MaxMs": row.MaxMs,
"AvgQueries": row.AvgQueries,
"AvgBytes": row.AvgBytes
});
}
response["DATA"] = rows;
} else if (view == "latency") {
// Top endpoints by average latency
q = queryExecute("
SELECT
Endpoint,
COUNT(*) as Calls,
ROUND(AVG(TotalMs)) as AvgMs,
ROUND(AVG(DbMs)) as AvgDbMs,
ROUND(AVG(AppMs)) as AvgAppMs,
MAX(TotalMs) as MaxMs,
ROUND(AVG(QueryCount), 1) as AvgQueries
FROM ApiPerfLogs
WHERE LoggedAt > DATE_SUB(NOW(), INTERVAL :hours HOUR)
GROUP BY Endpoint
HAVING Calls >= 3
ORDER BY AvgMs DESC
LIMIT :lim
", {
hours: { value: hours, cfsqltype: "cf_sql_integer" },
lim: { value: limitRows, cfsqltype: "cf_sql_integer" }
}, { datasource: "payfrit" });
rows = [];
for (row in q) {
arrayAppend(rows, {
"Endpoint": row.Endpoint,
"Calls": row.Calls,
"AvgMs": row.AvgMs,
"AvgDbMs": row.AvgDbMs,
"AvgAppMs": row.AvgAppMs,
"MaxMs": row.MaxMs,
"AvgQueries": row.AvgQueries
});
}
response["DATA"] = rows;
} else if (view == "slow") {
// Slowest individual requests
q = queryExecute("
SELECT Endpoint, TotalMs, DbMs, AppMs, QueryCount, ResponseBytes,
BusinessID, UserID, LoggedAt
FROM ApiPerfLogs
WHERE LoggedAt > DATE_SUB(NOW(), INTERVAL :hours HOUR)
ORDER BY TotalMs DESC
LIMIT :lim
", {
hours: { value: hours, cfsqltype: "cf_sql_integer" },
lim: { value: limitRows, cfsqltype: "cf_sql_integer" }
}, { datasource: "payfrit" });
rows = [];
for (row in q) {
arrayAppend(rows, {
"Endpoint": row.Endpoint,
"TotalMs": row.TotalMs,
"DbMs": row.DbMs,
"AppMs": row.AppMs,
"QueryCount": row.QueryCount,
"ResponseBytes": row.ResponseBytes,
"BusinessID": row.BusinessID,
"UserID": row.UserID,
"LoggedAt": dateTimeFormat(row.LoggedAt, "yyyy-mm-dd HH:nn:ss")
});
}
response["DATA"] = rows;
} else if (view == "summary") {
// Overall summary stats
q = queryExecute("
SELECT
COUNT(*) as TotalRequests,
COUNT(DISTINCT Endpoint) as UniqueEndpoints,
ROUND(AVG(TotalMs)) as OverallAvgMs,
MAX(TotalMs) as OverallMaxMs,
ROUND(AVG(DbMs)) as OverallAvgDbMs,
ROUND(AVG(AppMs)) as OverallAvgAppMs,
ROUND(AVG(QueryCount), 1) as OverallAvgQueries,
MIN(LoggedAt) as FirstLog,
MAX(LoggedAt) as LastLog
FROM ApiPerfLogs
WHERE LoggedAt > DATE_SUB(NOW(), INTERVAL :hours HOUR)
", {
hours: { value: hours, cfsqltype: "cf_sql_integer" }
}, { datasource: "payfrit" });
response["DATA"] = {
"TotalRequests": q.TotalRequests,
"UniqueEndpoints": q.UniqueEndpoints,
"OverallAvgMs": q.OverallAvgMs,
"OverallMaxMs": q.OverallMaxMs,
"OverallAvgDbMs": q.OverallAvgDbMs,
"OverallAvgAppMs": q.OverallAvgAppMs,
"OverallAvgQueries": q.OverallAvgQueries,
"FirstLog": isDate(q.FirstLog) ? dateTimeFormat(q.FirstLog, "yyyy-mm-dd HH:nn:ss") : "",
"LastLog": isDate(q.LastLog) ? dateTimeFormat(q.LastLog, "yyyy-mm-dd HH:nn:ss") : ""
};
} else {
apiAbort({ "OK": false, "ERROR": "invalid_view", "MESSAGE": "Use ?view=count|latency|slow|summary" });
}
apiAbort(response);
} catch (any e) {
apiAbort({
"OK": false,
"ERROR": "server_error",
"MESSAGE": e.message,
"DETAIL": e.detail
});
}
</cfscript>

View file

@ -5,7 +5,7 @@
// Add TaskTypeID column to QuickTaskTemplates table if it doesn't exist
try {
// Check if column exists
qCheck = queryExecute("
qCheck = queryTimed("
SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'payfrit'
AND TABLE_NAME = 'QuickTaskTemplates'
@ -13,7 +13,7 @@ try {
", [], { datasource: "payfrit" });
if (qCheck.recordCount == 0) {
queryExecute("
queryTimed("
ALTER TABLE QuickTaskTemplates
ADD COLUMN TaskTypeID INT NULL AFTER TaskCategoryID
", [], { datasource: "payfrit" });

View file

@ -6,7 +6,7 @@
// One-time cleanup: delete test tasks and reset
try {
// Delete tasks 30, 31, 32 (test tasks with bad data)
queryExecute("DELETE FROM Tasks WHERE ID IN (30, 31, 32)", [], { datasource: "payfrit" });
queryTimed("DELETE FROM Tasks WHERE ID IN (30, 31, 32)", [], { datasource: "payfrit" });
writeOutput(serializeJSON({
"OK": true,

View file

@ -48,7 +48,7 @@ try {
}
// Get template details
qTemplate = queryExecute("
qTemplate = queryTimed("
SELECT
Title as Title,
Details as Details,
@ -67,7 +67,7 @@ try {
}
// Create the task (ClaimedByUserID=0 means unclaimed/pending)
queryExecute("
queryTimed("
INSERT INTO Tasks (
BusinessID, CategoryID, TaskTypeID,
Title, Details, CreatedOn, ClaimedByUserID
@ -83,7 +83,7 @@ try {
details: { value: qTemplate.Details, cfsqltype: "cf_sql_longvarchar", null: isNull(qTemplate.Details) }
}, { datasource: "payfrit" });
qNew = queryExecute("SELECT LAST_INSERT_ID() as newID", [], { datasource: "payfrit" });
qNew = queryTimed("SELECT LAST_INSERT_ID() as newID", [], { datasource: "payfrit" });
apiAbort({
"OK": true,

View file

@ -4,7 +4,7 @@
<cfscript>
try {
q = queryExecute("
q = queryTimed("
SELECT ID, Title, Details, TaskCategoryID, ClaimedByUserID, CompletedOn, CreatedOn
FROM Tasks
WHERE BusinessID = 47

View file

@ -48,7 +48,7 @@ try {
}
// Verify template exists and belongs to this business
qCheck = queryExecute("
qCheck = queryTimed("
SELECT ID FROM QuickTaskTemplates
WHERE ID = :id AND BusinessID = :businessID
", {
@ -61,7 +61,7 @@ try {
}
// Soft delete by setting IsActive to 0
queryExecute("
queryTimed("
UPDATE QuickTaskTemplates SET IsActive = 0
WHERE ID = :id
", {

View file

@ -43,7 +43,7 @@ try {
}
// Get quick task templates for this business
q = queryExecute("
q = queryTimed("
SELECT
qt.ID,
qt.Name as Name,

View file

@ -5,7 +5,7 @@
<cfscript>
try {
// Delete all Quick Task templates for business 1
queryExecute("DELETE FROM QuickTaskTemplates WHERE BusinessID = 1", [], { datasource: "payfrit" });
queryTimed("DELETE FROM QuickTaskTemplates WHERE BusinessID = 1", [], { datasource: "payfrit" });
writeOutput(serializeJSON({
"OK": true,

View file

@ -68,7 +68,7 @@ try {
if (templateID > 0) {
// UPDATE existing template
qCheck = queryExecute("
qCheck = queryTimed("
SELECT ID FROM QuickTaskTemplates
WHERE ID = :id AND BusinessID = :businessID
", {
@ -80,7 +80,7 @@ try {
apiAbort({ "OK": false, "ERROR": "not_found", "MESSAGE": "Template not found" });
}
queryExecute("
queryTimed("
UPDATE QuickTaskTemplates SET
Name = :name,
Title = :title,
@ -108,7 +108,7 @@ try {
} else {
// INSERT new template
// Get next sort order
qSort = queryExecute("
qSort = queryTimed("
SELECT COALESCE(MAX(SortOrder), 0) + 1 as nextSort
FROM QuickTaskTemplates WHERE BusinessID = :businessID
", {
@ -117,7 +117,7 @@ try {
nextSort = qSort.nextSort;
queryExecute("
queryTimed("
INSERT INTO QuickTaskTemplates (
BusinessID, Name, Title,
Details, TaskCategoryID,
@ -136,7 +136,7 @@ try {
sortOrder: { value: nextSort, cfsqltype: "cf_sql_integer" }
}, { datasource: "payfrit" });
qNew = queryExecute("SELECT LAST_INSERT_ID() as newID", [], { datasource: "payfrit" });
qNew = queryTimed("SELECT LAST_INSERT_ID() as newID", [], { datasource: "payfrit" });
apiAbort({
"OK": true,

View file

@ -13,7 +13,7 @@ function apiAbort(required struct payload) {
try {
// Create QuickTaskTemplates table
queryExecute("
queryTimed("
CREATE TABLE IF NOT EXISTS QuickTaskTemplates (
ID INT AUTO_INCREMENT PRIMARY KEY,
BusinessID INT NOT NULL,

View file

@ -48,7 +48,7 @@ try {
}
// Verify exists and belongs to business
qCheck = queryExecute("
qCheck = queryTimed("
SELECT ID FROM ScheduledTaskDefinitions
WHERE ID = :id AND BusinessID = :businessID
", {
@ -61,7 +61,7 @@ try {
}
// Hard delete the definition
queryExecute("
queryTimed("
DELETE FROM ScheduledTaskDefinitions WHERE ID = :id
", {
id: { value: taskID, cfsqltype: "cf_sql_integer" }

View file

@ -43,7 +43,7 @@ try {
}
// Get scheduled task definitions for this business
q = queryExecute("
q = queryTimed("
SELECT
st.ID,
st.Name as Name,

View file

@ -49,7 +49,7 @@ try {
}
// Get scheduled task definition
qDef = queryExecute("
qDef = queryTimed("
SELECT
Title as Title,
Details as Details,
@ -66,7 +66,7 @@ try {
}
// Create the task (ClaimedByUserID=0 means unclaimed/pending)
queryExecute("
queryTimed("
INSERT INTO Tasks (
BusinessID, CategoryID, TaskTypeID,
Title, Details, CreatedOn, ClaimedByUserID
@ -82,7 +82,7 @@ try {
details: { value: qDef.Details, cfsqltype: "cf_sql_longvarchar", null: isNull(qDef.Details) }
}, { datasource: "payfrit" });
qNew = queryExecute("SELECT LAST_INSERT_ID() as newID", [], { datasource: "payfrit" });
qNew = queryTimed("SELECT LAST_INSERT_ID() as newID", [], { datasource: "payfrit" });
apiAbort({
"OK": true,

View file

@ -65,7 +65,7 @@ function calculateNextRun(required string cronExpression) {
try {
// Find all active scheduled tasks that are due
dueTasks = queryExecute("
dueTasks = queryTimed("
SELECT
ID AS ScheduledTaskID,
BusinessID as BusinessID,
@ -84,7 +84,7 @@ try {
for (task in dueTasks) {
// Create the actual task (ClaimedByUserID=0 means unclaimed/pending)
queryExecute("
queryTimed("
INSERT INTO Tasks (
BusinessID, CategoryID, TaskTypeID,
Title, Details, CreatedOn, ClaimedByUserID
@ -100,7 +100,7 @@ try {
details: { value: task.Details, cfsqltype: "cf_sql_longvarchar", null: isNull(task.Details) }
}, { datasource: "payfrit" });
qNew = queryExecute("SELECT LAST_INSERT_ID() as newID", [], { datasource: "payfrit" });
qNew = queryTimed("SELECT LAST_INSERT_ID() as newID", [], { datasource: "payfrit" });
// Calculate next run based on schedule type
if (task.ScheduleType == "interval_after_completion" && !isNull(task.IntervalMinutes) && task.IntervalMinutes > 0) {
@ -115,7 +115,7 @@ try {
nextRun = calculateNextRun(task.CronExpression);
}
queryExecute("
queryTimed("
UPDATE ScheduledTaskDefinitions SET
LastRunOn = NOW(),
NextRunOn = :nextRun

View file

@ -156,7 +156,7 @@ try {
if (taskID > 0) {
// UPDATE existing
qCheck = queryExecute("
qCheck = queryTimed("
SELECT ID FROM ScheduledTaskDefinitions
WHERE ID = :id AND BusinessID = :businessID
", {
@ -168,7 +168,7 @@ try {
apiAbort({ "OK": false, "ERROR": "not_found", "MESSAGE": "Scheduled task not found" });
}
queryExecute("
queryTimed("
UPDATE ScheduledTaskDefinitions SET
Name = :name,
Title = :title,
@ -202,7 +202,7 @@ try {
} else {
// INSERT new
queryExecute("
queryTimed("
INSERT INTO ScheduledTaskDefinitions (
BusinessID, Name, Title,
Details, TaskCategoryID,
@ -224,11 +224,11 @@ try {
nextRun: { value: nextRunOn, cfsqltype: "cf_sql_timestamp" }
}, { datasource: "payfrit" });
qNew = queryExecute("SELECT LAST_INSERT_ID() as newID", [], { datasource: "payfrit" });
qNew = queryTimed("SELECT LAST_INSERT_ID() as newID", [], { datasource: "payfrit" });
newScheduledTaskID = qNew.newID;
// Create the first task immediately
queryExecute("
queryTimed("
INSERT INTO Tasks (
BusinessID, CategoryID, TaskTypeID,
Title, Details, CreatedOn, ClaimedByUserID
@ -244,7 +244,7 @@ try {
details: { value: taskDetails, cfsqltype: "cf_sql_longvarchar", null: !len(taskDetails) }
}, { datasource: "payfrit" });
qTask = queryExecute("SELECT LAST_INSERT_ID() as taskID", [], { datasource: "payfrit" });
qTask = queryTimed("SELECT LAST_INSERT_ID() as taskID", [], { datasource: "payfrit" });
// Now set the NEXT run time (not the immediate one we just created)
if (scheduleType == "interval" || scheduleType == "interval_after_completion") {
@ -260,7 +260,7 @@ try {
actualNextRun = calculateNextRun(cronExpression);
}
queryExecute("
queryTimed("
UPDATE ScheduledTaskDefinitions
SET LastRunOn = NOW(),
NextRunOn = :nextRun

View file

@ -13,7 +13,7 @@ function apiAbort(required struct payload) {
try {
// Create ScheduledTaskDefinitions table
queryExecute("
queryTimed("
CREATE TABLE IF NOT EXISTS ScheduledTaskDefinitions (
ID INT AUTO_INCREMENT PRIMARY KEY,
BusinessID INT NOT NULL,
@ -37,7 +37,7 @@ try {
// Add new columns if they don't exist (for existing tables)
try {
queryExecute("
queryTimed("
ALTER TABLE ScheduledTaskDefinitions
ADD COLUMN ScheduleType VARCHAR(20) DEFAULT 'cron' AFTER CronExpression
", [], { datasource: "payfrit" });
@ -46,7 +46,7 @@ try {
}
try {
queryExecute("
queryTimed("
ALTER TABLE ScheduledTaskDefinitions
ADD COLUMN IntervalMinutes INT NULL AFTER ScheduleType
", [], { datasource: "payfrit" });

View file

@ -98,7 +98,7 @@ try {
}
// Verify exists and get cron expression and schedule type
qCheck = queryExecute("
qCheck = queryTimed("
SELECT ID, CronExpression as CronExpression,
COALESCE(ScheduleType, 'cron') as ScheduleType,
IntervalMinutes as IntervalMinutes
@ -128,7 +128,7 @@ try {
// Update status
if (isActive) {
queryExecute("
queryTimed("
UPDATE ScheduledTaskDefinitions SET
IsActive = :isActive,
NextRunOn = :nextRun
@ -139,7 +139,7 @@ try {
id: { value: taskID, cfsqltype: "cf_sql_integer" }
}, { datasource: "payfrit" });
} else {
queryExecute("
queryTimed("
UPDATE ScheduledTaskDefinitions SET IsActive = :isActive
WHERE ID = :id
", {

View file

@ -50,7 +50,7 @@ if (structKeyExists(request, "UserID") && isNumeric(request.UserID) && request.U
if (len(userToken)) {
try {
qTok = queryExecute(
qTok = queryTimed(
"SELECT UserID FROM UserTokens WHERE Token = ? LIMIT 1",
[ { value = userToken, cfsqltype = "cf_sql_varchar" } ],
{ datasource = "payfrit" }

View file

@ -70,7 +70,7 @@ try {
}
// Check if email is already used by another verified account
qEmailCheck = queryExecute("
qEmailCheck = queryTimed("
SELECT ID FROM Users
WHERE EmailAddress = :email
AND IsEmailVerified = 1
@ -86,13 +86,13 @@ try {
}
// Get current user UUID for email confirmation link
qUser = queryExecute("
qUser = queryTimed("
SELECT UUID FROM Users WHERE ID = :userId
", { userId: { value: userId, cfsqltype: "cf_sql_integer" } }, { datasource: "payfrit" });
// Update user profile AND mark account as verified/active
// This completes the signup process
queryExecute("
queryTimed("
UPDATE Users
SET FirstName = :firstName,
LastName = :lastName,

View file

@ -53,7 +53,7 @@ if (!len(username) || !len(password)) {
}
try {
q = queryExecute(
q = queryTimed(
"
SELECT ID, FirstName
FROM Users
@ -81,7 +81,7 @@ try {
token = replace(createUUID(), "-", "", "all");
queryExecute(
queryTimed(
"INSERT INTO UserTokens (UserID, Token) VALUES (?, ?)",
[
{ value = q.ID, cfsqltype = "cf_sql_integer" },

View file

@ -52,7 +52,7 @@ try {
}
// Find verified account with this phone
qUser = queryExecute("
qUser = queryTimed("
SELECT ID, UUID
FROM Users
WHERE ContactNumber = :phone
@ -68,7 +68,7 @@ try {
userUUID = qUser.UUID;
if (!len(trim(userUUID))) {
userUUID = replace(createUUID(), "-", "", "all");
queryExecute("
queryTimed("
UPDATE Users SET UUID = :uuid WHERE ID = :userId
", {
uuid: { value: userUUID, cfsqltype: "cf_sql_varchar" },
@ -82,7 +82,7 @@ try {
&& structKeyExists(application, "MAGIC_OTP_CODE") && len(application.MAGIC_OTP_CODE)) {
otp = application.MAGIC_OTP_CODE;
}
queryExecute("
queryTimed("
UPDATE Users
SET MobileVerifyCode = :otp
WHERE ID = :userId

View file

@ -38,7 +38,7 @@ if (structKeyExists(request, "UserID") && isNumeric(request.UserID) && request.U
userToken = getHeader("X-User-Token");
if (len(userToken)) {
try {
qTok = queryExecute(
qTok = queryTimed(
"SELECT UserID FROM UserTokens WHERE Token = ? LIMIT 1",
[ { value = userToken, cfsqltype = "cf_sql_varchar" } ],
{ datasource = "payfrit" }
@ -57,7 +57,7 @@ if (userId <= 0) {
// Handle GET - return profile
if (cgi.REQUEST_METHOD == "GET") {
try {
qUser = queryExecute("
qUser = queryTimed("
SELECT
ID,
FirstName,
@ -124,14 +124,14 @@ if (cgi.REQUEST_METHOD == "POST") {
}
// Execute update
queryExecute("
queryTimed("
UPDATE Users
SET #arrayToList(updates, ', ')#
WHERE ID = :userId
", params);
// Return updated profile
qUser = queryExecute("
qUser = queryTimed("
SELECT
ID,
FirstName,

View file

@ -37,7 +37,7 @@ genericResponse = { "OK": true, "MESSAGE": "If an account exists, a code has bee
try {
// Look up user by email
qUser = queryExecute("
qUser = queryTimed("
SELECT ID, FirstName
FROM Users
WHERE EmailAddress = :email
@ -56,7 +56,7 @@ try {
userId = qUser.ID;
// Rate limit: max 3 codes per user in last 10 minutes
qRateCheck = queryExecute("
qRateCheck = queryTimed("
SELECT COUNT(*) AS cnt
FROM OTPCodes
WHERE UserID = :userId
@ -81,7 +81,7 @@ try {
}
// Store in DB with 10-minute expiry
queryExecute("
queryTimed("
INSERT INTO OTPCodes (UserID, Code, ExpiresAt)
VALUES (:userId, :code, DATE_ADD(NOW(), INTERVAL 10 MINUTE))
", {

View file

@ -56,7 +56,7 @@ try {
// Check if phone already has a COMPLETE account (verified AND has profile info)
// An account is only "complete" if they have a first name (meaning they finished signup)
qExisting = queryExecute("
qExisting = queryTimed("
SELECT ID, UUID, FirstName
FROM Users
WHERE ContactNumber = :phone
@ -72,7 +72,7 @@ try {
// Check for incomplete account with this phone (verified but no profile, OR unverified)
// These accounts can be reused for signup
qIncomplete = queryExecute("
qIncomplete = queryTimed("
SELECT ID, UUID
FROM Users
WHERE ContactNumber = :phone
@ -90,7 +90,7 @@ try {
if (qIncomplete.recordCount > 0) {
// Update existing incomplete record with new OTP and reset for re-registration
userUUID = qIncomplete.UUID;
queryExecute("
queryTimed("
UPDATE Users
SET MobileVerifyCode = :otp,
IsContactVerified = 0,
@ -103,7 +103,7 @@ try {
} else {
// Create new user record
userUUID = replace(createUUID(), "-", "", "all");
queryExecute("
queryTimed("
INSERT INTO Users (
ContactNumber,
UUID,

View file

@ -32,7 +32,7 @@ try {
}
// Look up the token
qToken = queryExecute("
qToken = queryTimed("
SELECT ut.UserID, u.FirstName, u.LastName
FROM UserTokens ut
JOIN Users u ON u.ID = ut.UserID
@ -47,7 +47,7 @@ try {
userID = qToken.UserID;
// Determine if user is a worker (has any active employment)
qWorker = queryExecute("
qWorker = queryTimed("
SELECT COUNT(*) as cnt
FROM Employees
WHERE UserID = :userID AND IsActive = 1

Some files were not shown because too many files have changed in this diff Show more