Normalize database column and table names across entire codebase
Update all SQL queries, query result references, and ColdFusion code to match
the renamed database schema. Tables use plural CamelCase, PKs are all `ID`,
column prefixes stripped (e.g. BusinessName→Name, UserFirstName→FirstName).
Key changes:
- Strip table-name prefixes from all column references (Businesses, Users,
Addresses, Hours, Menus, Categories, Items, Stations, Orders,
OrderLineItems, Tasks, TaskCategories, TaskRatings, QuickTaskTemplates,
ScheduledTaskDefinitions, ChatMessages, Beacons, ServicePoints, Employees,
VisitorTrackings, ApiPerfLogs, tt_States, tt_Days, tt_AddressTypes,
tt_OrderTypes, tt_TaskTypes)
- Rename PK references from {TableName}ID to ID in all queries
- Rewrite 7 admin beacon files to use ServicePoints.BeaconID instead of
dropped lt_Beacon_Businesses_ServicePoints link table
- Rewrite beacon assignment files (list, save, delete) for new schema
- Fix FK references incorrectly changed to ID (OrderLineItems.OrderID,
Categories.MenuID, Tasks.CategoryID, ServicePoints.BeaconID)
- Update Addresses: AddressLat→Latitude, AddressLng→Longitude
- Update Users: UserPassword→Password, UserIsEmailVerified→IsEmailVerified,
UserIsActive→IsActive, UserBalance→Balance, etc.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
dc9db32b58
commit
1210249f54
240 changed files with 6644 additions and 5542 deletions
|
|
@ -24,9 +24,9 @@
|
|||
<cfif request.UserID NEQ 0>
|
||||
|
||||
<cfquery name="check_user" datasource="#application.datasource#">
|
||||
SELECT UserFirstName, UserBalance, UserImageExtension
|
||||
SELECT FirstName, Balance, ImageExtension
|
||||
FROM Users
|
||||
WHERE UserID = #request.UserID#
|
||||
WHERE ID = #request.UserID#
|
||||
</cfquery>
|
||||
|
||||
</cfif>
|
||||
|
|
@ -320,8 +320,8 @@
|
|||
<cfif find("logout.cfm", request.cgiPath) EQ 0>
|
||||
|
||||
<cfif request.UserID NEQ 0>
|
||||
<cfif check_user.UserImageExtension gt ""><img src="#application.image_display_prefix#users/thumbs/#request.UserID#.#check_user.UserImageExtension#" border="0" alt=""><br></cfif>
|
||||
Hi, <cfif check_user.UserFirstName gt "">#check_user.UserFirstName#<br>#dollarformat(check_user.UserBalance)#<cfelse>Payfrit User</cfif><br>
|
||||
<cfif check_user.ImageExtension gt ""><img src="#application.image_display_prefix#users/thumbs/#request.UserID#.#check_user.ImageExtension#" border="0" alt=""><br></cfif>
|
||||
Hi, <cfif check_user.FirstName gt "">#check_user.FirstName#<br>#dollarformat(check_user.Balance)#<cfelse>Payfrit User</cfif><br>
|
||||
<cfelse>
|
||||
|
||||
<form action="#application.wwwrootprefix#index.cfm" method="post" name="login_form" id="login_form">
|
||||
|
|
|
|||
14
_process.cfm
14
_process.cfm
|
|
@ -116,13 +116,13 @@
|
|||
<cfset cart_total = 0>
|
||||
|
||||
<CFQUERY name="get_queued_food" datasource="#application.datasource#" dbtype="ODBC">
|
||||
SELECT A.CartID, A.AddedOn, A.Quantity, A.SpecialRemark, B.BusinessName, B.UserID, C.ItemName, A.Price, D.UserFirstName, D.LaerFirstName, D.Balance
|
||||
SELECT A.CartID, A.AddedOn, A.Quantity, A.SpecialRemark, B.Name, B.UserID, C.Name, A.Price, D.FirstName, D.LaerFirstName, D.Balance
|
||||
FROM dbo.Business_CartMaster A, dbo.BusinessMaster B, dbo.Business_ItemMaster C, Users D
|
||||
WHERE A.UserID = D.UserID
|
||||
AND
|
||||
A.ItemID = C.ItemID
|
||||
AND
|
||||
B.BusinessID = C.BusinessID
|
||||
B.ID = C.BusinessID
|
||||
AND
|
||||
C.BusinessID = #form.bizid#
|
||||
AND
|
||||
|
|
@ -170,11 +170,11 @@
|
|||
</CFQUERY>
|
||||
|
||||
<CFQUERY name="get_last_inserted" datasource="#application.datasource#" dbtype="ODBC">
|
||||
SELECT TOP 1 O.OrderID, M.UserID as person_to_pay_for_orderID, U.Balance
|
||||
SELECT TOP 1 O.ID, M.UserID as person_to_pay_for_orderID, U.Balance
|
||||
FROM dbo.Business_OrderMaster O, dbo.BusinessMaster M, Users U
|
||||
WHERE O.BusinessID = M.BusinessID
|
||||
AND
|
||||
M.UserID = U.UserID
|
||||
M.UserID = U.ID
|
||||
ORDER BY O.AddedOn DESC
|
||||
</CFQUERY>
|
||||
|
||||
|
|
@ -185,7 +185,7 @@
|
|||
)
|
||||
VALUES
|
||||
(
|
||||
#get_last_inserted.OrderID#,
|
||||
#get_last_inserted.ID#,
|
||||
#get_queued_food.CartID#
|
||||
)
|
||||
</CFQUERY>
|
||||
|
|
@ -268,7 +268,7 @@
|
|||
<CFQUERY name="get_user_104_balance" datasource="#application.datasource#" dbtype="ODBC">
|
||||
SELECT balance
|
||||
FROM Users
|
||||
WHERE UserID = 104
|
||||
WHERE ID = 104
|
||||
</CFQUERY>
|
||||
|
||||
<CFQUERY name="transfer_fees_to_UserID_104" datasource="#application.datasource#" dbtype="ODBC">
|
||||
|
|
@ -346,7 +346,7 @@
|
|||
<CFQUERY name="get_user_104_balance" datasource="#application.datasource#" dbtype="ODBC">
|
||||
SELECT balance
|
||||
FROM Users
|
||||
WHERE UserID = 104
|
||||
WHERE ID = 104
|
||||
</CFQUERY>
|
||||
|
||||
<CFQUERY name="transfer_fees_to_UserID_104" datasource="#application.datasource#" dbtype="ODBC">
|
||||
|
|
|
|||
|
|
@ -164,8 +164,8 @@ async function refreshAssignments(){
|
|||
const tr = document.createElement("tr");
|
||||
tr.innerHTML = `
|
||||
<td>${a.lt_Beacon_Businesses_ServicePointID}</td>
|
||||
<td>${escapeHtml((a.BeaconName || "") + " (ID " + a.BeaconID + ")")}</td>
|
||||
<td>${escapeHtml((a.ServicePointName || "") + " (ID " + a.ServicePointID + ")")}</td>
|
||||
<td>${escapeHtml((a.Name || "") + " (ID " + a.BeaconID + ")")}</td>
|
||||
<td>${escapeHtml((a.Name || "") + " (ID " + a.ServicePointID + ")")}</td>
|
||||
<td>${escapeHtml(a.lt_Beacon_Businesses_ServicePointNotes || "")}</td>
|
||||
<td>${escapeHtml(a.CreatedAt || "")}</td>
|
||||
`;
|
||||
|
|
@ -183,12 +183,12 @@ async function refreshBeacons(assignedBeaconIDs, keepSelectedBeaconID){
|
|||
setSelectPlaceholder(sel, "-- Select Beacon --");
|
||||
|
||||
(out.BEACONS || []).forEach(b => {
|
||||
const isAssigned = assignedBeaconIDs.has(String(b.BeaconID));
|
||||
const isAssigned = assignedBeaconIDs.has(String(b.ID));
|
||||
if (HIDE_ASSIGNED_BEACONS && isAssigned) return;
|
||||
|
||||
const opt = document.createElement("option");
|
||||
opt.value = b.BeaconID;
|
||||
opt.textContent = String(b.BeaconID) + " - " + (b.BeaconName || "");
|
||||
opt.value = b.ID;
|
||||
opt.textContent = String(b.ID) + " - " + (b.Name || "");
|
||||
sel.appendChild(opt);
|
||||
});
|
||||
|
||||
|
|
@ -203,12 +203,12 @@ async function refreshServicePoints(assignedServicePointIDs, keepSelectedService
|
|||
setSelectPlaceholder(sel, "-- Select ServicePoint --");
|
||||
|
||||
(out.SERVICEPOINTS || []).forEach(sp => {
|
||||
const isAssigned = assignedServicePointIDs.has(String(sp.ServicePointID));
|
||||
const isAssigned = assignedServicePointIDs.has(String(sp.ID));
|
||||
if (HIDE_ASSIGNED_SERVICEPOINTS && isAssigned) return;
|
||||
|
||||
const opt = document.createElement("option");
|
||||
opt.value = sp.ServicePointID;
|
||||
opt.textContent = String(sp.ServicePointID) + " - " + (sp.ServicePointName || "");
|
||||
opt.value = sp.ID;
|
||||
opt.textContent = String(sp.ID) + " - " + (sp.Name || "");
|
||||
sel.appendChild(opt);
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
</head>
|
||||
<body>
|
||||
<h2>Beacons</h2>
|
||||
<div class="warn">Required: BeaconName</div>
|
||||
<div class="warn">Required: Name</div>
|
||||
<div class="ok" id="jsStatus">(JS not loaded yet)</div>
|
||||
|
||||
<div class="row">
|
||||
|
|
@ -38,8 +38,8 @@
|
|||
</div>
|
||||
|
||||
<div>
|
||||
<label>BeaconName (required)</label><br>
|
||||
<input id="BeaconName" placeholder="Front Door" required>
|
||||
<label>Name (required)</label><br>
|
||||
<input id="Name" placeholder="Front Door" required>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
|
|
@ -160,13 +160,13 @@ function escapeHtml(s){
|
|||
}
|
||||
|
||||
function loadIntoForm(b){
|
||||
document.getElementById("BeaconID").value = b.BeaconID || "";
|
||||
document.getElementById("BeaconName").value = b.BeaconName || "";
|
||||
document.getElementById("BeaconID").value = b.ID || "";
|
||||
document.getElementById("Name").value = b.Name || "";
|
||||
document.getElementById("UUID").value = b.UUID || "";
|
||||
document.getElementById("NamespaceId").value = b.NamespaceId || "";
|
||||
document.getElementById("InstanceId").value = b.InstanceId || "";
|
||||
document.getElementById("IsActive").value = ("" + (b.IsActive ?? 1));
|
||||
document.getElementById("DelBeaconID").value = b.BeaconID || "";
|
||||
document.getElementById("DelBeaconID").value = b.ID || "";
|
||||
}
|
||||
|
||||
async function refresh() {
|
||||
|
|
@ -180,8 +180,8 @@ async function refresh() {
|
|||
for (const b of items) {
|
||||
const tr = document.createElement("tr");
|
||||
tr.innerHTML = `
|
||||
<td>${b.BeaconID}</td>
|
||||
<td>${escapeHtml(b.BeaconName||"")}</td>
|
||||
<td>${b.ID}</td>
|
||||
<td>${escapeHtml(b.Name||"")}</td>
|
||||
<td>${escapeHtml(b.UUID||"")}</td>
|
||||
<td>${escapeHtml(b.NamespaceId||"")}</td>
|
||||
<td>${escapeHtml(b.InstanceId||"")}</td>
|
||||
|
|
@ -194,15 +194,15 @@ async function refresh() {
|
|||
}
|
||||
|
||||
async function saveBeacon() {
|
||||
const name = (document.getElementById("BeaconName").value || "").trim();
|
||||
const name = (document.getElementById("Name").value || "").trim();
|
||||
if (!name) {
|
||||
show({ OK:false, ERROR:"missing_beacon_name", MESSAGE:"BeaconName is required" });
|
||||
show({ OK:false, ERROR:"missing_beacon_name", MESSAGE:"Name is required" });
|
||||
return;
|
||||
}
|
||||
|
||||
const body = {
|
||||
BeaconID: valIntOrNull("BeaconID"),
|
||||
BeaconName: name,
|
||||
Name: name,
|
||||
UUID: (document.getElementById("UUID").value || "").trim(),
|
||||
NamespaceId: (document.getElementById("NamespaceId").value || "").trim(),
|
||||
InstanceId: (document.getElementById("InstanceId").value || "").trim(),
|
||||
|
|
|
|||
|
|
@ -7,16 +7,16 @@
|
|||
<cfparam name="users_to_email" default="">
|
||||
|
||||
<cfquery name="select_users_to_email" datasource="#application.datasource#">
|
||||
SELECT U.UserEmailAddress
|
||||
SELECT U.EmailAddress
|
||||
FROM Users U
|
||||
WHERE UserID in (0,1,2)
|
||||
</cfquery>
|
||||
|
||||
<cfoutput query="select_users_to_email">
|
||||
|
||||
#UserEmailAddress#,
|
||||
#EmailAddress#,
|
||||
|
||||
<cfset users_to_email=listappend(users_to_email, #UserEmailAddress#)>
|
||||
<cfset users_to_email=listappend(users_to_email, #EmailAddress#)>
|
||||
|
||||
</cfoutput><br><br>
|
||||
|
||||
|
|
@ -95,18 +95,18 @@
|
|||
<cfloop index="the_email_address" list="#users_to_email#">
|
||||
|
||||
<cfquery name="get_user_email" datasource="#application.datasource#">
|
||||
SELECT UserUUID
|
||||
SELECT UUID
|
||||
FROM Users
|
||||
WHERE UserEmailAddress = '#the_email_address#'
|
||||
WHERE EmailAddress = '#the_email_address#'
|
||||
AND
|
||||
UserIsEmailverified = 1
|
||||
AND
|
||||
UserIsContactVerified > 0
|
||||
IsContactVerified > 0
|
||||
</cfquery>
|
||||
|
||||
<cfset form.this_email_body = form.email_body & "
|
||||
|
||||
instant unsubscribe link: https://www.payfrit.com/remove_me.cfm?UserUUID="&#get_user_email.UserUUID#>
|
||||
instant unsubscribe link: https://www.payfrit.com/remove_me.cfm?UUID="&#get_user_email.UUID#>
|
||||
|
||||
<cfmail to="#the_email_address#" from="admin@payfrit.com" subject="#form.email_subject#" type="HTML">
|
||||
#HTMLCodeFormat(form.this_email_body)#</cfmail>
|
||||
|
|
|
|||
|
|
@ -5,14 +5,14 @@
|
|||
<cfif form.mode eq "start">
|
||||
|
||||
<CFQUERY name="get_verified_users" datasource="#application.datasource#">
|
||||
SELECT U.UserID, U.UserEmailAddress, U.UserContactNumber,U.UserAddedOn
|
||||
SELECT U.ID, U.EmailAddress, U.ContactNumber,U.AddedOn
|
||||
FROM Users U
|
||||
WHERE U.UserIsEmailVerified = 1
|
||||
WHERE U.IsEmailVerified = 1
|
||||
AND
|
||||
U.UserIsCOntactVerified > 0
|
||||
AND
|
||||
U.UserID > 435
|
||||
ORDER BY U.UserID DESC
|
||||
U.ID > 435
|
||||
ORDER BY U.ID DESC
|
||||
</cfquery>
|
||||
|
||||
|
||||
|
|
@ -48,16 +48,16 @@
|
|||
</form>
|
||||
|
||||
</td>
|
||||
<td>#UserEmailAddress#</td>
|
||||
<td>#UserContactNumber#</td>
|
||||
<td>#dateformat(UserAddedOn, "mmmm dd, YYYY")# at #timeformat(UserAddedOn, "hh:nn tt")#</td>
|
||||
<td>#EmailAddress#</td>
|
||||
<td>#ContactNumber#</td>
|
||||
<td>#dateformat(AddedOn, "mmmm dd, YYYY")# at #timeformat(AddedOn, "hh:nn tt")#</td>
|
||||
<td>
|
||||
|
||||
<CFQUERY name="get_orders" datasource="#application.datasource#">
|
||||
SELECT O.OrderUUID
|
||||
SELECT O.UUID
|
||||
FROM Orders O
|
||||
WHERE O.OrderUserID = #get_verified_users.UserID#
|
||||
ORDER BY O.OrderID DESC
|
||||
WHERE O.UserID = #get_verified_users.ID#
|
||||
ORDER BY O.ID DESC
|
||||
</cfquery>
|
||||
|
||||
<cfparam name="looper" default="">
|
||||
|
|
@ -66,7 +66,7 @@
|
|||
|
||||
<cfloop query="get_orders">
|
||||
<cfset looper=incrementvalue(looper)>
|
||||
<a href="https://payfr.it/show_order.cfm?OrderUUID=#get_orders.OrderUUID#&is_admin_view=1" target="_blank">#looper#</a>,
|
||||
<a href="https://payfr.it/show_order.cfm?UUID=#get_orders.UUID#&is_admin_view=1" target="_blank">#looper#</a>,
|
||||
</cfloop>
|
||||
|
||||
</td>
|
||||
|
|
@ -79,10 +79,10 @@
|
|||
<cfelseif form.mode eq "user_traffic">
|
||||
|
||||
<CFQUERY name="get_user_traffic" datasource="#application.datasource#">
|
||||
SELECT V.VisitorTrackingPageMode, V.VisitorTrackingAddedOn
|
||||
FROM VisitorTracking V
|
||||
WHERE V.VisitorTrackingUserID = #form.chip#
|
||||
ORDER BY V.VisitorTrackingAddedOn DESC
|
||||
SELECT V.PageMode, V.AddedOn
|
||||
FROM VisitorTrackings V
|
||||
WHERE V.UserID = #form.chip#
|
||||
ORDER BY V.AddedOn DESC
|
||||
</cfquery>
|
||||
|
||||
<table>
|
||||
|
|
@ -92,8 +92,8 @@
|
|||
</tr>
|
||||
<cfoutput query="get_user_traffic">
|
||||
<tr>
|
||||
<td>#VisitorTrackingPageMode#</td>
|
||||
<td>#VisitorTrackingAddedOn#</td>
|
||||
<td>#PageMode#</td>
|
||||
<td>#AddedOn#</td>
|
||||
</tr>
|
||||
</cfoutput>
|
||||
</table>
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
</head>
|
||||
<body>
|
||||
<h2>ServicePoints</h2>
|
||||
<div class="warn">Required: ServicePointName</div>
|
||||
<div class="warn">Required: Name</div>
|
||||
<div class="ok" id="jsStatus">(JS not loaded yet)</div>
|
||||
|
||||
<div class="row">
|
||||
|
|
@ -38,18 +38,18 @@
|
|||
</div>
|
||||
|
||||
<div>
|
||||
<label>ServicePointName (required)</label><br>
|
||||
<input id="ServicePointName" placeholder="Front Counter" required>
|
||||
<label>Name (required)</label><br>
|
||||
<input id="Name" placeholder="Front Counter" required>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label>ServicePointTypeID</label><br>
|
||||
<input id="ServicePointTypeID" placeholder="0">
|
||||
<label>TypeID</label><br>
|
||||
<input id="TypeID" placeholder="0">
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label>ServicePointCode</label><br>
|
||||
<input id="ServicePointCode" placeholder="COUNTER">
|
||||
<label>Code</label><br>
|
||||
<input id="Code" placeholder="COUNTER">
|
||||
</div>
|
||||
|
||||
<div>
|
||||
|
|
@ -160,14 +160,14 @@ function escapeHtml(s){
|
|||
}
|
||||
|
||||
function loadIntoForm(sp){
|
||||
document.getElementById("ServicePointID").value = sp.ServicePointID || "";
|
||||
document.getElementById("ServicePointName").value = sp.ServicePointName || "";
|
||||
document.getElementById("ServicePointTypeID").value = (sp.ServicePointTypeID ?? 0);
|
||||
document.getElementById("ServicePointCode").value = sp.ServicePointCode || "";
|
||||
document.getElementById("ServicePointID").value = sp.ID || "";
|
||||
document.getElementById("Name").value = sp.Name || "";
|
||||
document.getElementById("TypeID").value = (sp.TypeID ?? 0);
|
||||
document.getElementById("Code").value = sp.Code || "";
|
||||
document.getElementById("Description").value = sp.Description || "";
|
||||
document.getElementById("SortOrder").value = (sp.SortOrder ?? 0);
|
||||
document.getElementById("IsActive").value = ("" + (sp.IsActive ?? 1));
|
||||
document.getElementById("DelServicePointID").value = sp.ServicePointID || "";
|
||||
document.getElementById("DelServicePointID").value = sp.ID || "";
|
||||
}
|
||||
|
||||
async function refresh() {
|
||||
|
|
@ -181,10 +181,10 @@ async function refresh() {
|
|||
for (const sp of items) {
|
||||
const tr = document.createElement("tr");
|
||||
tr.innerHTML = `
|
||||
<td>${sp.ServicePointID}</td>
|
||||
<td>${escapeHtml(sp.ServicePointName||"")}</td>
|
||||
<td>${sp.ServicePointTypeID}</td>
|
||||
<td>${escapeHtml(sp.ServicePointCode||"")}</td>
|
||||
<td>${sp.ID}</td>
|
||||
<td>${escapeHtml(sp.Name||"")}</td>
|
||||
<td>${sp.TypeID}</td>
|
||||
<td>${escapeHtml(sp.Code||"")}</td>
|
||||
<td>${sp.SortOrder}</td>
|
||||
<td>${sp.IsActive}</td>
|
||||
`;
|
||||
|
|
@ -195,17 +195,17 @@ async function refresh() {
|
|||
}
|
||||
|
||||
async function saveSP() {
|
||||
const name = (document.getElementById("ServicePointName").value || "").trim();
|
||||
const name = (document.getElementById("Name").value || "").trim();
|
||||
if (!name) {
|
||||
show({ OK:false, ERROR:"missing_servicepoint_name", MESSAGE:"ServicePointName is required" });
|
||||
show({ OK:false, ERROR:"missing_servicepoint_name", MESSAGE:"Name is required" });
|
||||
return;
|
||||
}
|
||||
|
||||
const body = {
|
||||
ServicePointID: valIntOrNull("ServicePointID"),
|
||||
ServicePointName: name,
|
||||
ServicePointTypeID: valIntOrZero("ServicePointTypeID"),
|
||||
ServicePointCode: (document.getElementById("ServicePointCode").value || "").trim(),
|
||||
Name: name,
|
||||
TypeID: valIntOrZero("TypeID"),
|
||||
Code: (document.getElementById("Code").value || "").trim(),
|
||||
Description: (document.getElementById("Description").value || "").trim(),
|
||||
SortOrder: valIntOrZero("SortOrder"),
|
||||
IsActive: parseInt(document.getElementById("IsActive").value, 10)
|
||||
|
|
|
|||
|
|
@ -1,11 +1,6 @@
|
|||
<cfsetting showdebugoutput="false">
|
||||
<cfsetting enablecfoutputonly="true">
|
||||
|
||||
<!--- Performance timing: start clock as early as possible --->
|
||||
<cfset request._perf_start = getTickCount()>
|
||||
<cfset request._perf_queryCount = 0>
|
||||
<cfset request._perf_queryTimeMs = 0>
|
||||
|
||||
<!---
|
||||
Payfrit API Application.cfm (updated 2026-01-22)
|
||||
|
||||
|
|
@ -178,6 +173,11 @@ if (len(request._api_path)) {
|
|||
|
||||
// Worker app endpoints
|
||||
if (findNoCase("/api/workers/myBusinesses.cfm", request._api_path)) request._api_isPublic = true;
|
||||
if (findNoCase("/api/workers/tierStatus.cfm", request._api_path)) request._api_isPublic = true;
|
||||
if (findNoCase("/api/workers/createAccount.cfm", request._api_path)) request._api_isPublic = true;
|
||||
if (findNoCase("/api/workers/onboardingLink.cfm", request._api_path)) request._api_isPublic = true;
|
||||
if (findNoCase("/api/workers/earlyUnlock.cfm", request._api_path)) request._api_isPublic = true;
|
||||
if (findNoCase("/api/workers/ledger.cfm", request._api_path)) request._api_isPublic = true;
|
||||
|
||||
// Portal endpoints
|
||||
if (findNoCase("/api/portal/stats.cfm", request._api_path)) request._api_isPublic = true;
|
||||
|
|
|
|||
|
|
@ -58,8 +58,8 @@ try {
|
|||
queryExecute("
|
||||
UPDATE Addresses
|
||||
SET AddressIsDefaultDelivery = 0
|
||||
WHERE AddressUserID = :userId
|
||||
AND (AddressBusinessID = 0 OR AddressBusinessID IS NULL)
|
||||
WHERE UserID = :userId
|
||||
AND (BusinessID = 0 OR BusinessID IS NULL)
|
||||
AND AddressTypeID = :typeId
|
||||
", {
|
||||
userId: { value: userId, cfsqltype: "cf_sql_integer" },
|
||||
|
|
@ -75,18 +75,18 @@ try {
|
|||
queryExecute("
|
||||
INSERT INTO Addresses (
|
||||
AddressID,
|
||||
AddressUserID,
|
||||
AddressBusinessID,
|
||||
UserID,
|
||||
BusinessID,
|
||||
AddressTypeID,
|
||||
AddressLabel,
|
||||
AddressIsDefaultDelivery,
|
||||
AddressLine1,
|
||||
AddressLine2,
|
||||
AddressCity,
|
||||
AddressStateID,
|
||||
AddressZIPCode,
|
||||
AddressIsDeleted,
|
||||
AddressAddedOn
|
||||
Line1,
|
||||
Line2,
|
||||
City,
|
||||
StateID,
|
||||
ZIPCode,
|
||||
IsDeleted,
|
||||
AddedOn
|
||||
) VALUES (
|
||||
:addressId,
|
||||
:userId,
|
||||
|
|
@ -117,7 +117,7 @@ try {
|
|||
}, { datasource: "payfrit" });
|
||||
|
||||
// Get state info for response
|
||||
qState = queryExecute("SELECT tt_StateAbbreviation as StateAbbreviation, tt_StateName as StateName FROM tt_States WHERE tt_StateID = :stateId", {
|
||||
qState = queryExecute("SELECT Abbreviation as StateAbbreviation, Name as StateName FROM tt_States WHERE ID = :stateId", {
|
||||
stateId: { value: stateId, cfsqltype: "cf_sql_integer" }
|
||||
}, { datasource: "payfrit" });
|
||||
|
||||
|
|
|
|||
|
|
@ -76,11 +76,11 @@ if (addressId <= 0) {
|
|||
try {
|
||||
// First, get the address details so we can find all matching duplicates
|
||||
qAddr = queryExecute("
|
||||
SELECT AddressLine1, AddressLine2, AddressCity, AddressStateID, AddressZIPCode
|
||||
SELECT Line1, Line2, City, StateID, ZIPCode
|
||||
FROM Addresses
|
||||
WHERE AddressID = :addressId
|
||||
AND AddressUserID = :userId
|
||||
AND AddressIsDeleted = 0
|
||||
WHERE ID = :addressId
|
||||
AND UserID = :userId
|
||||
AND IsDeleted = 0
|
||||
", {
|
||||
addressId: { value = addressId, cfsqltype = "cf_sql_integer" },
|
||||
userId: { value = userId, cfsqltype = "cf_sql_integer" }
|
||||
|
|
@ -93,21 +93,21 @@ try {
|
|||
// Soft-delete ALL addresses that match the same Line1, Line2, City, StateID, ZIPCode
|
||||
qDelete = queryExecute("
|
||||
UPDATE Addresses
|
||||
SET AddressIsDeleted = 1
|
||||
WHERE AddressUserID = :userId
|
||||
AND AddressLine1 = :line1
|
||||
AND AddressLine2 = :line2
|
||||
AND AddressCity = :city
|
||||
AND AddressStateID = :stateId
|
||||
AND AddressZIPCode = :zip
|
||||
AND AddressIsDeleted = 0
|
||||
SET IsDeleted = 1
|
||||
WHERE UserID = :userId
|
||||
AND Line1 = :line1
|
||||
AND Line2 = :line2
|
||||
AND City = :city
|
||||
AND StateID = :stateId
|
||||
AND ZIPCode = :zip
|
||||
AND IsDeleted = 0
|
||||
", {
|
||||
userId: { value = userId, cfsqltype = "cf_sql_integer" },
|
||||
line1: { value = qAddr.AddressLine1, cfsqltype = "cf_sql_varchar", null = !len(qAddr.AddressLine1) },
|
||||
line2: { value = qAddr.AddressLine2, cfsqltype = "cf_sql_varchar", null = !len(qAddr.AddressLine2) },
|
||||
city: { value = qAddr.AddressCity, cfsqltype = "cf_sql_varchar", null = !len(qAddr.AddressCity) },
|
||||
stateId: { value = qAddr.AddressStateID, cfsqltype = "cf_sql_integer" },
|
||||
zip: { value = qAddr.AddressZIPCode, cfsqltype = "cf_sql_varchar", null = !len(qAddr.AddressZIPCode) }
|
||||
line1: { value = qAddr.Line1, cfsqltype = "cf_sql_varchar", null = !len(qAddr.Line1) },
|
||||
line2: { value = qAddr.Line2, cfsqltype = "cf_sql_varchar", null = !len(qAddr.Line2) },
|
||||
city: { value = qAddr.City, cfsqltype = "cf_sql_varchar", null = !len(qAddr.City) },
|
||||
stateId: { value = qAddr.StateID, cfsqltype = "cf_sql_integer" },
|
||||
zip: { value = qAddr.ZIPCode, cfsqltype = "cf_sql_varchar", null = !len(qAddr.ZIPCode) }
|
||||
});
|
||||
|
||||
writeOutput(serializeJSON({
|
||||
|
|
|
|||
|
|
@ -49,22 +49,22 @@ try {
|
|||
// Get user's delivery addresses
|
||||
qAddresses = queryExecute("
|
||||
SELECT
|
||||
a.AddressID,
|
||||
a.AddressIsDefaultDelivery,
|
||||
a.AddressLine1,
|
||||
a.AddressLine2,
|
||||
a.AddressCity,
|
||||
a.AddressStateID,
|
||||
s.tt_StateAbbreviation as StateAbbreviation,
|
||||
s.tt_StateName as StateName,
|
||||
a.AddressZIPCode
|
||||
a.ID,
|
||||
a.IsDefaultDelivery,
|
||||
a.Line1,
|
||||
a.Line2,
|
||||
a.City,
|
||||
a.StateID,
|
||||
s.Abbreviation as StateAbbreviation,
|
||||
s.Name as StateName,
|
||||
a.ZIPCode
|
||||
FROM Addresses a
|
||||
LEFT JOIN tt_States s ON a.AddressStateID = s.tt_StateID
|
||||
WHERE a.AddressUserID = :userId
|
||||
AND (a.AddressBusinessID = 0 OR a.AddressBusinessID IS NULL)
|
||||
LEFT JOIN tt_States s ON a.StateID = s.ID
|
||||
WHERE a.UserID = :userId
|
||||
AND (a.BusinessID = 0 OR a.BusinessID IS NULL)
|
||||
AND a.AddressTypeID = 2
|
||||
AND a.AddressIsDeleted = 0
|
||||
ORDER BY a.AddressIsDefaultDelivery DESC, a.AddressID DESC
|
||||
AND a.IsDeleted = 0
|
||||
ORDER BY a.IsDefaultDelivery DESC, a.ID DESC
|
||||
", {
|
||||
userId: { value = userId, cfsqltype = "cf_sql_integer" }
|
||||
});
|
||||
|
|
@ -72,15 +72,15 @@ try {
|
|||
addresses = [];
|
||||
for (row in qAddresses) {
|
||||
arrayAppend(addresses, {
|
||||
"AddressID": row.AddressID,
|
||||
"IsDefault": row.AddressIsDefaultDelivery == 1,
|
||||
"Line1": row.AddressLine1,
|
||||
"Line2": row.AddressLine2 ?: "",
|
||||
"City": row.AddressCity,
|
||||
"StateID": row.AddressStateID,
|
||||
"AddressID": row.ID,
|
||||
"IsDefault": row.IsDefaultDelivery == 1,
|
||||
"Line1": row.Line1,
|
||||
"Line2": row.Line2 ?: "",
|
||||
"City": row.City,
|
||||
"StateID": row.StateID,
|
||||
"StateAbbr": row.StateAbbreviation ?: "",
|
||||
"ZIPCode": row.AddressZIPCode,
|
||||
"DisplayText": row.AddressLine1 & (len(row.AddressLine2) ? ", " & row.AddressLine2 : "") & ", " & row.AddressCity & ", " & (row.StateAbbreviation ?: "") & " " & row.AddressZIPCode
|
||||
"ZIPCode": row.ZIPCode,
|
||||
"DisplayText": row.Line1 & (len(row.Line2) ? ", " & row.Line2 : "") & ", " & row.City & ", " & (row.StateAbbreviation ?: "") & " " & row.ZIPCode
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -41,11 +41,11 @@ try {
|
|||
|
||||
// Verify address belongs to user
|
||||
qCheck = queryExecute("
|
||||
SELECT AddressID
|
||||
SELECT ID
|
||||
FROM Addresses
|
||||
WHERE AddressID = :addressId
|
||||
AND AddressUserID = :userId
|
||||
AND AddressIsDeleted = 0
|
||||
WHERE ID = :addressId
|
||||
AND UserID = :userId
|
||||
AND IsDeleted = 0
|
||||
", {
|
||||
addressId: { value: addressId, cfsqltype: "cf_sql_integer" },
|
||||
userId: { value: userId, cfsqltype: "cf_sql_integer" }
|
||||
|
|
@ -64,8 +64,8 @@ try {
|
|||
queryExecute("
|
||||
UPDATE Addresses
|
||||
SET AddressIsDefaultDelivery = 0
|
||||
WHERE AddressUserID = :userId
|
||||
AND (AddressBusinessID = 0 OR AddressBusinessID IS NULL)
|
||||
WHERE UserID = :userId
|
||||
AND (BusinessID = 0 OR BusinessID IS NULL)
|
||||
AND AddressTypeID LIKE '%2%'
|
||||
", {
|
||||
userId: { value: userId, cfsqltype: "cf_sql_integer" }
|
||||
|
|
@ -75,7 +75,7 @@ try {
|
|||
queryExecute("
|
||||
UPDATE Addresses
|
||||
SET AddressIsDefaultDelivery = 1
|
||||
WHERE AddressID = :addressId
|
||||
WHERE ID = :addressId
|
||||
", {
|
||||
addressId: { value: addressId, cfsqltype: "cf_sql_integer" }
|
||||
}, { datasource: "payfrit" });
|
||||
|
|
|
|||
|
|
@ -2,19 +2,13 @@
|
|||
<cfsetting enablecfoutputonly="true">
|
||||
<cfcontent type="application/json; charset=utf-8">
|
||||
|
||||
<!--- List US states for address forms (cached 24h - static data) --->
|
||||
<!--- List US states for address forms --->
|
||||
<cfscript>
|
||||
try {
|
||||
cached = appCacheGet("states", 86400);
|
||||
if (!isNull(cached)) {
|
||||
writeOutput(cached);
|
||||
abort;
|
||||
}
|
||||
|
||||
qStates = queryExecute("
|
||||
SELECT tt_StateID as StateID, tt_StateAbbreviation as StateAbbreviation, tt_StateName as StateName
|
||||
SELECT tt_StateID as StateID, Abbreviation as StateAbbreviation, Name as StateName
|
||||
FROM tt_States
|
||||
ORDER BY tt_StateName
|
||||
ORDER BY Name
|
||||
", {}, { datasource: "payfrit" });
|
||||
|
||||
states = [];
|
||||
|
|
@ -26,12 +20,10 @@ try {
|
|||
});
|
||||
}
|
||||
|
||||
jsonResponse = serializeJSON({
|
||||
writeOutput(serializeJSON({
|
||||
"OK": true,
|
||||
"STATES": states
|
||||
});
|
||||
appCachePut("states", jsonResponse);
|
||||
writeOutput(jsonResponse);
|
||||
}));
|
||||
|
||||
} catch (any e) {
|
||||
writeOutput(serializeJSON({
|
||||
|
|
|
|||
|
|
@ -2,25 +2,25 @@
|
|||
<cfcontent type="application/json; charset=utf-8" reset="true">
|
||||
|
||||
<cfscript>
|
||||
// Add TaskCategoryIsActive column to TaskCategories table
|
||||
// Add IsActive column to TaskCategories table
|
||||
try {
|
||||
// Check if column exists
|
||||
qCheck = queryExecute("
|
||||
SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE TABLE_SCHEMA = 'payfrit'
|
||||
AND TABLE_NAME = 'TaskCategories'
|
||||
AND COLUMN_NAME = 'TaskCategoryIsActive'
|
||||
AND COLUMN_NAME = 'IsActive'
|
||||
", [], { datasource: "payfrit" });
|
||||
|
||||
if (qCheck.recordCount == 0) {
|
||||
queryExecute("
|
||||
ALTER TABLE TaskCategories
|
||||
ADD COLUMN TaskCategoryIsActive TINYINT(1) NOT NULL DEFAULT 1
|
||||
ADD COLUMN IsActive TINYINT(1) NOT NULL DEFAULT 1
|
||||
", [], { datasource: "payfrit" });
|
||||
|
||||
writeOutput(serializeJSON({
|
||||
"OK": true,
|
||||
"MESSAGE": "Column TaskCategoryIsActive added to TaskCategories"
|
||||
"MESSAGE": "Column IsActive added to TaskCategories"
|
||||
}));
|
||||
} else {
|
||||
writeOutput(serializeJSON({
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@
|
|||
* Add Schedule Fields to Categories Table
|
||||
*
|
||||
* Adds time-based scheduling fields:
|
||||
* - CategoryScheduleStart: TIME - Start time when category is available (e.g., 06:00:00 for breakfast)
|
||||
* - CategoryScheduleEnd: TIME - End time when category stops being available (e.g., 11:00:00)
|
||||
* - CategoryScheduleDays: VARCHAR(20) - Comma-separated list of day IDs (1=Sun, 2=Mon, etc.) or NULL for all days
|
||||
* - ScheduleStart: TIME - Start time when category is available (e.g., 06:00:00 for breakfast)
|
||||
* - ScheduleEnd: TIME - End time when category stops being available (e.g., 11:00:00)
|
||||
* - ScheduleDays: VARCHAR(20) - Comma-separated list of day IDs (1=Sun, 2=Mon, etc.) or NULL for all days
|
||||
*
|
||||
* Run this once to migrate the schema.
|
||||
*/
|
||||
|
|
@ -24,38 +24,38 @@ try {
|
|||
FROM INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE TABLE_SCHEMA = 'payfrit'
|
||||
AND TABLE_NAME = 'Categories'
|
||||
AND COLUMN_NAME IN ('CategoryScheduleStart', 'CategoryScheduleEnd', 'CategoryScheduleDays')
|
||||
AND COLUMN_NAME IN ('ScheduleStart', 'ScheduleEnd', 'ScheduleDays')
|
||||
", {}, { datasource: "payfrit" });
|
||||
|
||||
existingCols = valueList(qCheck.COLUMN_NAME);
|
||||
|
||||
added = [];
|
||||
|
||||
// Add CategoryScheduleStart if not exists
|
||||
if (!listFindNoCase(existingCols, "CategoryScheduleStart")) {
|
||||
// Add ScheduleStart if not exists
|
||||
if (!listFindNoCase(existingCols, "ScheduleStart")) {
|
||||
queryExecute("
|
||||
ALTER TABLE Categories
|
||||
ADD COLUMN CategoryScheduleStart TIME NULL
|
||||
ADD COLUMN ScheduleStart TIME NULL
|
||||
", {}, { datasource: "payfrit" });
|
||||
arrayAppend(added, "CategoryScheduleStart");
|
||||
arrayAppend(added, "ScheduleStart");
|
||||
}
|
||||
|
||||
// Add CategoryScheduleEnd if not exists
|
||||
if (!listFindNoCase(existingCols, "CategoryScheduleEnd")) {
|
||||
// Add ScheduleEnd if not exists
|
||||
if (!listFindNoCase(existingCols, "ScheduleEnd")) {
|
||||
queryExecute("
|
||||
ALTER TABLE Categories
|
||||
ADD COLUMN CategoryScheduleEnd TIME NULL
|
||||
ADD COLUMN ScheduleEnd TIME NULL
|
||||
", {}, { datasource: "payfrit" });
|
||||
arrayAppend(added, "CategoryScheduleEnd");
|
||||
arrayAppend(added, "ScheduleEnd");
|
||||
}
|
||||
|
||||
// Add CategoryScheduleDays if not exists
|
||||
if (!listFindNoCase(existingCols, "CategoryScheduleDays")) {
|
||||
// Add ScheduleDays if not exists
|
||||
if (!listFindNoCase(existingCols, "ScheduleDays")) {
|
||||
queryExecute("
|
||||
ALTER TABLE Categories
|
||||
ADD COLUMN CategoryScheduleDays VARCHAR(20) NULL
|
||||
ADD COLUMN ScheduleDays VARCHAR(20) NULL
|
||||
", {}, { datasource: "payfrit" });
|
||||
arrayAppend(added, "CategoryScheduleDays");
|
||||
arrayAppend(added, "ScheduleDays");
|
||||
}
|
||||
|
||||
response["OK"] = true;
|
||||
|
|
|
|||
|
|
@ -15,8 +15,8 @@ try {
|
|||
|
||||
// Find the Fountain Soda item we created
|
||||
qFountain = queryExecute("
|
||||
SELECT ItemID, ItemName FROM Items
|
||||
WHERE ItemBusinessID = :bizId AND ItemName = 'Fountain Soda'
|
||||
SELECT ID, Name FROM Items
|
||||
WHERE BusinessID = :bizId AND Name = 'Fountain Soda'
|
||||
", { bizId: bigDeansBusinessId }, { datasource: "payfrit" });
|
||||
|
||||
if (qFountain.recordCount == 0) {
|
||||
|
|
@ -31,13 +31,13 @@ try {
|
|||
// Update Fountain Soda to require child selection and be collapsible
|
||||
queryExecute("
|
||||
UPDATE Items
|
||||
SET ItemRequiresChildSelection = 1, ItemIsCollapsible = 1
|
||||
SET RequiresChildSelection = 1, IsCollapsible = 1
|
||||
WHERE ItemID = :itemId
|
||||
", { itemId: fountainId }, { datasource: "payfrit" });
|
||||
|
||||
// Check if modifiers already exist
|
||||
qExisting = queryExecute("
|
||||
SELECT COUNT(*) as cnt FROM Items WHERE ItemParentItemID = :parentId
|
||||
SELECT COUNT(*) as cnt FROM Items WHERE ParentItemID = :parentId
|
||||
", { parentId: fountainId }, { datasource: "payfrit" });
|
||||
|
||||
if (qExisting.cnt > 0) {
|
||||
|
|
@ -53,10 +53,10 @@ try {
|
|||
|
||||
queryExecute("
|
||||
INSERT INTO Items (
|
||||
ItemID, ItemBusinessID, ItemCategoryID, ItemParentItemID,
|
||||
ItemName, ItemDescription, ItemPrice, ItemIsActive,
|
||||
ItemSortOrder, ItemIsCollapsible, ItemRequiresChildSelection,
|
||||
ItemMaxNumSelectionReq, ItemAddedOn
|
||||
ItemID, BusinessID, CategoryID, ParentItemID,
|
||||
Name, Description, Price, IsActive,
|
||||
SortOrder, IsCollapsible, RequiresChildSelection,
|
||||
MaxNumSelectionReq, AddedOn
|
||||
) VALUES (
|
||||
:itemId, :bizId, 0, :parentId,
|
||||
'Size', 'Choose your size', 0, 1,
|
||||
|
|
@ -80,10 +80,10 @@ try {
|
|||
qMaxItem = queryExecute("SELECT COALESCE(MAX(ItemID), 0) + 1 as nextId FROM Items", {}, { datasource: "payfrit" });
|
||||
queryExecute("
|
||||
INSERT INTO Items (
|
||||
ItemID, ItemBusinessID, ItemCategoryID, ItemParentItemID,
|
||||
ItemName, ItemDescription, ItemPrice, ItemIsActive,
|
||||
ItemSortOrder, ItemIsCollapsible, ItemIsCheckedByDefault,
|
||||
ItemAddedOn
|
||||
ItemID, BusinessID, CategoryID, ParentItemID,
|
||||
Name, Description, Price, IsActive,
|
||||
SortOrder, IsCollapsible, IsCheckedByDefault,
|
||||
AddedOn
|
||||
) VALUES (
|
||||
:itemId, :bizId, 0, :parentId,
|
||||
:name, '', :price, 1,
|
||||
|
|
@ -108,10 +108,10 @@ try {
|
|||
|
||||
queryExecute("
|
||||
INSERT INTO Items (
|
||||
ItemID, ItemBusinessID, ItemCategoryID, ItemParentItemID,
|
||||
ItemName, ItemDescription, ItemPrice, ItemIsActive,
|
||||
ItemSortOrder, ItemIsCollapsible, ItemRequiresChildSelection,
|
||||
ItemMaxNumSelectionReq, ItemAddedOn
|
||||
ItemID, BusinessID, CategoryID, ParentItemID,
|
||||
Name, Description, Price, IsActive,
|
||||
SortOrder, IsCollapsible, RequiresChildSelection,
|
||||
MaxNumSelectionReq, AddedOn
|
||||
) VALUES (
|
||||
:itemId, :bizId, 0, :parentId,
|
||||
'Flavor', 'Choose your drink', 0, 1,
|
||||
|
|
@ -139,10 +139,10 @@ try {
|
|||
qMaxItem = queryExecute("SELECT COALESCE(MAX(ItemID), 0) + 1 as nextId FROM Items", {}, { datasource: "payfrit" });
|
||||
queryExecute("
|
||||
INSERT INTO Items (
|
||||
ItemID, ItemBusinessID, ItemCategoryID, ItemParentItemID,
|
||||
ItemName, ItemDescription, ItemPrice, ItemIsActive,
|
||||
ItemSortOrder, ItemIsCollapsible, ItemIsCheckedByDefault,
|
||||
ItemAddedOn
|
||||
ItemID, BusinessID, CategoryID, ParentItemID,
|
||||
Name, Description, Price, IsActive,
|
||||
SortOrder, IsCollapsible, IsCheckedByDefault,
|
||||
AddedOn
|
||||
) VALUES (
|
||||
:itemId, :bizId, 0, :parentId,
|
||||
:name, '', 0, 1,
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
<cfscript>
|
||||
/**
|
||||
* Add ItemCategoryID column to Items table
|
||||
* Add CategoryID column to Items table
|
||||
*/
|
||||
|
||||
response = { "OK": false };
|
||||
|
|
@ -17,30 +17,30 @@ try {
|
|||
FROM INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE TABLE_SCHEMA = 'payfrit'
|
||||
AND TABLE_NAME = 'Items'
|
||||
AND COLUMN_NAME = 'ItemCategoryID'
|
||||
AND COLUMN_NAME = 'CategoryID'
|
||||
", {}, { datasource: "payfrit" });
|
||||
|
||||
if (qCheck.recordCount > 0) {
|
||||
response["OK"] = true;
|
||||
response["MESSAGE"] = "ItemCategoryID column already exists";
|
||||
response["MESSAGE"] = "CategoryID column already exists";
|
||||
} else {
|
||||
// Add the column
|
||||
queryExecute("
|
||||
ALTER TABLE Items
|
||||
ADD COLUMN ItemCategoryID INT NULL DEFAULT 0 AFTER ItemParentItemID
|
||||
ADD COLUMN CategoryID INT NULL DEFAULT 0 AFTER ParentItemID
|
||||
", {}, { datasource: "payfrit" });
|
||||
|
||||
// Add index for performance
|
||||
try {
|
||||
queryExecute("
|
||||
CREATE INDEX idx_items_categoryid ON Items(ItemCategoryID)
|
||||
CREATE INDEX idx_items_categoryid ON Items(CategoryID)
|
||||
", {}, { datasource: "payfrit" });
|
||||
} catch (any indexErr) {
|
||||
// Index might already exist
|
||||
}
|
||||
|
||||
response["OK"] = true;
|
||||
response["MESSAGE"] = "ItemCategoryID column added successfully";
|
||||
response["MESSAGE"] = "CategoryID column added successfully";
|
||||
}
|
||||
|
||||
} catch (any e) {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
try {
|
||||
// Check if columns already exist
|
||||
checkCols = queryExecute(
|
||||
"SHOW COLUMNS FROM Addresses LIKE 'AddressLat'",
|
||||
"SHOW COLUMNS FROM Addresses LIKE 'Latitude'",
|
||||
[],
|
||||
{ datasource = "payfrit" }
|
||||
);
|
||||
|
|
@ -15,8 +15,8 @@ try {
|
|||
// Add the columns
|
||||
queryExecute(
|
||||
"ALTER TABLE Addresses
|
||||
ADD COLUMN AddressLat DECIMAL(10,7) NULL,
|
||||
ADD COLUMN AddressLng DECIMAL(10,7) NULL",
|
||||
ADD COLUMN Latitude DECIMAL(10,7) NULL,
|
||||
ADD COLUMN Longitude DECIMAL(10,7) NULL",
|
||||
[],
|
||||
{ datasource = "payfrit" }
|
||||
);
|
||||
|
|
|
|||
|
|
@ -9,18 +9,18 @@ try {
|
|||
SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE TABLE_SCHEMA = 'payfrit'
|
||||
AND TABLE_NAME = 'tt_TaskTypes'
|
||||
AND COLUMN_NAME = 'tt_TaskTypeCategoryID'
|
||||
AND COLUMN_NAME = 'TaskCategoryID'
|
||||
", [], { datasource: "payfrit" });
|
||||
|
||||
if (qCheck.recordCount == 0) {
|
||||
queryExecute("
|
||||
ALTER TABLE tt_TaskTypes
|
||||
ADD COLUMN tt_TaskTypeCategoryID INT NULL
|
||||
ADD COLUMN TaskCategoryID INT NULL
|
||||
", [], { datasource: "payfrit" });
|
||||
|
||||
writeOutput(serializeJSON({
|
||||
"OK": true,
|
||||
"MESSAGE": "Column tt_TaskTypeCategoryID added to tt_TaskTypes"
|
||||
"MESSAGE": "Column TaskCategoryID added to tt_TaskTypes"
|
||||
}));
|
||||
} else {
|
||||
writeOutput(serializeJSON({
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
<cfcontent type="application/json; charset=utf-8" reset="true">
|
||||
|
||||
<cfscript>
|
||||
// Add TaskSourceType and TaskSourceID columns to Tasks table
|
||||
// Add SourceType and SourceID columns to Tasks table
|
||||
// These are needed for chat persistence feature
|
||||
|
||||
result = { "OK": true, "STEPS": [] };
|
||||
|
|
@ -15,30 +15,30 @@ try {
|
|||
FROM INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE TABLE_SCHEMA = 'payfrit'
|
||||
AND TABLE_NAME = 'Tasks'
|
||||
AND COLUMN_NAME IN ('TaskSourceType', 'TaskSourceID')
|
||||
AND COLUMN_NAME IN ('SourceType', 'SourceID')
|
||||
", [], { datasource: "payfrit" });
|
||||
|
||||
existingCols = valueList(cols.COLUMN_NAME);
|
||||
arrayAppend(result.STEPS, "Existing columns: #existingCols#");
|
||||
|
||||
// Add TaskSourceType if missing
|
||||
if (!listFindNoCase(existingCols, "TaskSourceType")) {
|
||||
// Add SourceType if missing
|
||||
if (!listFindNoCase(existingCols, "SourceType")) {
|
||||
queryExecute("
|
||||
ALTER TABLE Tasks ADD COLUMN TaskSourceType VARCHAR(50) NULL
|
||||
ALTER TABLE Tasks ADD COLUMN SourceType VARCHAR(50) NULL
|
||||
", [], { datasource: "payfrit" });
|
||||
arrayAppend(result.STEPS, "Added TaskSourceType column");
|
||||
arrayAppend(result.STEPS, "Added SourceType column");
|
||||
} else {
|
||||
arrayAppend(result.STEPS, "TaskSourceType already exists");
|
||||
arrayAppend(result.STEPS, "SourceType already exists");
|
||||
}
|
||||
|
||||
// Add TaskSourceID if missing
|
||||
if (!listFindNoCase(existingCols, "TaskSourceID")) {
|
||||
// Add SourceID if missing
|
||||
if (!listFindNoCase(existingCols, "SourceID")) {
|
||||
queryExecute("
|
||||
ALTER TABLE Tasks ADD COLUMN TaskSourceID INT NULL
|
||||
ALTER TABLE Tasks ADD COLUMN SourceID INT NULL
|
||||
", [], { datasource: "payfrit" });
|
||||
arrayAppend(result.STEPS, "Added TaskSourceID column");
|
||||
arrayAppend(result.STEPS, "Added SourceID column");
|
||||
} else {
|
||||
arrayAppend(result.STEPS, "TaskSourceID already exists");
|
||||
arrayAppend(result.STEPS, "SourceID already exists");
|
||||
}
|
||||
|
||||
// Verify columns now exist
|
||||
|
|
@ -47,7 +47,7 @@ try {
|
|||
FROM INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE TABLE_SCHEMA = 'payfrit'
|
||||
AND TABLE_NAME = 'Tasks'
|
||||
AND COLUMN_NAME IN ('TaskSourceType', 'TaskSourceID')
|
||||
AND COLUMN_NAME IN ('SourceType', 'SourceID')
|
||||
", [], { datasource: "payfrit" });
|
||||
|
||||
result.COLUMNS = [];
|
||||
|
|
|
|||
|
|
@ -6,49 +6,49 @@
|
|||
// Show all beacons with their current business/service point assignments
|
||||
q = queryExecute("
|
||||
SELECT
|
||||
b.BeaconID,
|
||||
b.BeaconUUID,
|
||||
b.BeaconName,
|
||||
lt.BusinessID,
|
||||
lt.ServicePointID,
|
||||
biz.BusinessName,
|
||||
sp.ServicePointName
|
||||
b.ID,
|
||||
b.UUID,
|
||||
b.Name,
|
||||
sp_link.BusinessID,
|
||||
sp_link.ID,
|
||||
biz.Name,
|
||||
sp.Name
|
||||
FROM Beacons b
|
||||
LEFT JOIN lt_Beacon_Businesses_ServicePoints lt ON lt.BeaconID = b.BeaconID
|
||||
LEFT JOIN Businesses biz ON biz.BusinessID = lt.BusinessID
|
||||
LEFT JOIN ServicePoints sp ON sp.ServicePointID = lt.ServicePointID
|
||||
WHERE b.BeaconIsActive = 1
|
||||
ORDER BY b.BeaconID
|
||||
LEFT JOIN ServicePoints sp_link ON sp_link.BeaconID = b.ID
|
||||
LEFT JOIN Businesses biz ON biz.ID = sp_link.BusinessID
|
||||
LEFT JOIN ServicePoints sp ON sp.ID = sp_link.ID
|
||||
WHERE b.IsActive = 1
|
||||
ORDER BY b.ID
|
||||
", {}, { datasource: "payfrit" });
|
||||
|
||||
rows = [];
|
||||
for (row in q) {
|
||||
arrayAppend(rows, {
|
||||
"BeaconID": row.BeaconID,
|
||||
"BeaconUUID": row.BeaconUUID,
|
||||
"BeaconName": row.BeaconName ?: "",
|
||||
"BeaconID": row.ID,
|
||||
"UUID": row.UUID,
|
||||
"Name": row.Name ?: "",
|
||||
"BusinessID": row.BusinessID ?: 0,
|
||||
"BusinessName": row.BusinessName ?: "",
|
||||
"Name": row.Name ?: "",
|
||||
"ServicePointID": row.ServicePointID ?: 0,
|
||||
"ServicePointName": row.ServicePointName ?: ""
|
||||
"Name": row.Name ?: ""
|
||||
});
|
||||
}
|
||||
|
||||
// Also get service points for reference
|
||||
spQuery = queryExecute("
|
||||
SELECT sp.ServicePointID, sp.ServicePointName, sp.ServicePointBusinessID, b.BusinessName
|
||||
SELECT sp.ID, sp.Name, sp.BusinessID, b.Name
|
||||
FROM ServicePoints sp
|
||||
JOIN Businesses b ON b.BusinessID = sp.ServicePointBusinessID
|
||||
ORDER BY sp.ServicePointBusinessID, sp.ServicePointID
|
||||
JOIN Businesses b ON b.ID = sp.BusinessID
|
||||
ORDER BY sp.BusinessID, sp.ID
|
||||
", {}, { datasource: "payfrit" });
|
||||
|
||||
servicePoints = [];
|
||||
for (sp in spQuery) {
|
||||
arrayAppend(servicePoints, {
|
||||
"ServicePointID": sp.ServicePointID,
|
||||
"ServicePointName": sp.ServicePointName,
|
||||
"BusinessID": sp.ServicePointBusinessID,
|
||||
"BusinessName": sp.BusinessName
|
||||
"ServicePointID": sp.ID,
|
||||
"Name": sp.Name,
|
||||
"BusinessID": sp.BusinessID,
|
||||
"Name": sp.Name
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,16 +5,16 @@
|
|||
<cfscript>
|
||||
// Check Big Dean's owner
|
||||
q = queryExecute("
|
||||
SELECT b.BusinessID, b.BusinessName, b.BusinessUserID
|
||||
SELECT b.ID, b.Name, b.UserID
|
||||
FROM Businesses b
|
||||
WHERE b.BusinessID = 27
|
||||
WHERE b.ID = 27
|
||||
", {}, { datasource: "payfrit" });
|
||||
|
||||
// Get users
|
||||
users = queryExecute("
|
||||
SELECT *
|
||||
FROM Users
|
||||
ORDER BY UserID
|
||||
ORDER BY ID
|
||||
LIMIT 20
|
||||
", {}, { datasource: "payfrit" });
|
||||
|
||||
|
|
@ -23,9 +23,9 @@ colNames = users.getColumnNames();
|
|||
writeOutput(serializeJSON({
|
||||
"OK": true,
|
||||
"BigDeans": {
|
||||
"BusinessID": q.BusinessID,
|
||||
"BusinessName": q.BusinessName,
|
||||
"BusinessUserID": q.BusinessUserID
|
||||
"BusinessID": q.ID,
|
||||
"Name": q.Name,
|
||||
"UserID": q.UserID
|
||||
},
|
||||
"UserColumns": colNames,
|
||||
"UserCount": users.recordCount
|
||||
|
|
|
|||
|
|
@ -12,9 +12,9 @@ if (!len(phone)) {
|
|||
}
|
||||
|
||||
q = queryExecute("
|
||||
SELECT UserID, UserFirstName, UserLastName, UserEmail, UserPhone, UserIsContactVerified
|
||||
SELECT ID, FirstName, LastName, EmailAddress, ContactNumber, IsContactVerified
|
||||
FROM Users
|
||||
WHERE UserPhone = :phone OR UserEmail = :phone
|
||||
WHERE ContactNumber = :phone OR EmailAddress = :phone
|
||||
LIMIT 1
|
||||
", { phone: phone }, { datasource: "payfrit" });
|
||||
|
||||
|
|
@ -25,11 +25,11 @@ if (q.recordCount EQ 0) {
|
|||
|
||||
writeOutput(serializeJSON({
|
||||
"OK": true,
|
||||
"UserID": q.UserID,
|
||||
"FirstName": q.UserFirstName,
|
||||
"LastName": q.UserLastName,
|
||||
"Email": q.UserEmail,
|
||||
"Phone": q.UserPhone,
|
||||
"Verified": q.UserIsContactVerified
|
||||
"UserID": q.ID,
|
||||
"FirstName": q.FirstName,
|
||||
"LastName": q.LastName,
|
||||
"Email": q.EmailAddress,
|
||||
"Phone": q.ContactNumber,
|
||||
"Verified": q.IsContactVerified
|
||||
}));
|
||||
</cfscript>
|
||||
|
|
|
|||
|
|
@ -5,7 +5,8 @@
|
|||
<cfscript>
|
||||
/**
|
||||
* Cleanup Lazy Daisy Beacons
|
||||
* - Removes duplicate beacons created by setupBeaconTables
|
||||
* - Unassigns beacons 7, 8, 9 from service points
|
||||
* - Deletes beacons 7, 8, 9
|
||||
* - Updates original beacons with proper names
|
||||
*/
|
||||
response = { "OK": false, "steps": [] };
|
||||
|
|
@ -13,52 +14,50 @@ response = { "OK": false, "steps": [] };
|
|||
try {
|
||||
lazyDaisyID = 37;
|
||||
|
||||
// Delete duplicate assignments for beacons 7, 8, 9
|
||||
// Unassign beacons 7, 8, 9 from any service points
|
||||
queryExecute("
|
||||
DELETE FROM lt_Beacon_Businesses_ServicePoints
|
||||
UPDATE ServicePoints
|
||||
SET BeaconID = NULL, AssignedByUserID = NULL
|
||||
WHERE BeaconID IN (7, 8, 9) AND BusinessID = :bizId
|
||||
", { bizId: lazyDaisyID }, { datasource: "payfrit" });
|
||||
response.steps.append("Deleted duplicate assignments for beacons 7, 8, 9");
|
||||
response.steps.append("Unassigned beacons 7, 8, 9 from service points");
|
||||
|
||||
// Delete duplicate beacons 7, 8, 9
|
||||
queryExecute("
|
||||
DELETE FROM Beacons
|
||||
WHERE BeaconID IN (7, 8, 9) AND BeaconBusinessID = :bizId
|
||||
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
|
||||
// Beacon 4 -> Table 1 (ServicePointID 4)
|
||||
// Beacon 5 -> Table 2 (ServicePointID 5)
|
||||
// Beacon 6 -> Table 3 (ServicePointID 6)
|
||||
|
||||
queryExecute("
|
||||
UPDATE Beacons SET BeaconName = 'Beacon - Table 1'
|
||||
WHERE BeaconID = 4 AND BeaconBusinessID = :bizId
|
||||
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("
|
||||
UPDATE Beacons SET BeaconName = 'Beacon - Table 2'
|
||||
WHERE BeaconID = 5 AND BeaconBusinessID = :bizId
|
||||
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("
|
||||
UPDATE Beacons SET BeaconName = 'Beacon - Table 3'
|
||||
WHERE BeaconID = 6 AND BeaconBusinessID = :bizId
|
||||
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("
|
||||
SELECT lt.BeaconID, b.BeaconUUID, b.BeaconName, lt.BusinessID, biz.BusinessName, lt.ServicePointID, sp.ServicePointName
|
||||
FROM lt_Beacon_Businesses_ServicePoints lt
|
||||
JOIN Beacons b ON b.BeaconID = lt.BeaconID
|
||||
JOIN Businesses biz ON biz.BusinessID = lt.BusinessID
|
||||
LEFT JOIN ServicePoints sp ON sp.ServicePointID = lt.ServicePointID
|
||||
WHERE lt.BusinessID = :bizId
|
||||
ORDER BY lt.BeaconID
|
||||
SELECT sp.ID AS ServicePointID, sp.BeaconID, sp.BusinessID,
|
||||
b.Name AS BeaconName, b.UUID, sp.Name AS ServicePointName,
|
||||
biz.Name AS BusinessName
|
||||
FROM ServicePoints sp
|
||||
JOIN Beacons b ON b.ID = sp.BeaconID
|
||||
JOIN Businesses biz ON biz.ID = sp.BusinessID
|
||||
WHERE sp.BusinessID = :bizId AND sp.BeaconID IS NOT NULL
|
||||
ORDER BY sp.BeaconID
|
||||
", { bizId: lazyDaisyID }, { datasource: "payfrit" });
|
||||
|
||||
beacons = [];
|
||||
|
|
@ -66,8 +65,9 @@ try {
|
|||
arrayAppend(beacons, {
|
||||
"BeaconID": qFinal.BeaconID[i],
|
||||
"BeaconName": qFinal.BeaconName[i],
|
||||
"UUID": qFinal.BeaconUUID[i],
|
||||
"UUID": qFinal.UUID[i],
|
||||
"BusinessName": qFinal.BusinessName[i],
|
||||
"ServicePointID": qFinal.ServicePointID[i],
|
||||
"ServicePointName": qFinal.ServicePointName[i]
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,10 +13,10 @@
|
|||
* Cleanup Categories - Final step after migration verification
|
||||
*
|
||||
* This script:
|
||||
* 1. Verifies all Items have ItemBusinessID set
|
||||
* 1. Verifies all Items have BusinessID set
|
||||
* 2. Finds orphan items (ParentID=0, no children, not in links)
|
||||
* 3. Drops ItemCategoryID column
|
||||
* 4. Drops ItemIsModifierTemplate column (derived from ItemTemplateLinks now)
|
||||
* 3. Drops CategoryID column
|
||||
* 4. Drops IsModifierTemplate column (derived from lt_ItemID_TemplateItemID now)
|
||||
* 5. Drops Categories table
|
||||
*
|
||||
* Query param: ?confirm=YES to actually execute (otherwise shows verification only)
|
||||
|
|
@ -30,7 +30,7 @@ try {
|
|||
// Verification Step 1: Check for items without BusinessID
|
||||
qNoBusinessID = queryExecute("
|
||||
SELECT COUNT(*) as cnt FROM Items
|
||||
WHERE ItemBusinessID IS NULL OR ItemBusinessID = 0
|
||||
WHERE BusinessID IS NULL OR BusinessID = 0
|
||||
", {}, { datasource: "payfrit" });
|
||||
|
||||
response.verification["itemsWithoutBusinessID"] = qNoBusinessID.cnt;
|
||||
|
|
@ -46,38 +46,38 @@ try {
|
|||
qCategoryItems = queryExecute("
|
||||
SELECT COUNT(DISTINCT p.ItemID) as cnt
|
||||
FROM Items p
|
||||
INNER JOIN Items c ON c.ItemParentItemID = p.ItemID
|
||||
WHERE p.ItemParentItemID = 0
|
||||
AND p.ItemBusinessID > 0
|
||||
INNER JOIN Items c ON c.ParentItemID = p.ItemID
|
||||
WHERE p.ParentItemID = 0
|
||||
AND p.BusinessID > 0
|
||||
AND NOT EXISTS (
|
||||
SELECT 1 FROM ItemTemplateLinks tl WHERE tl.TemplateItemID = p.ItemID
|
||||
SELECT 1 FROM lt_ItemID_TemplateItemID tl WHERE tl.TemplateItemID = p.ItemID
|
||||
)
|
||||
", {}, { datasource: "payfrit" });
|
||||
|
||||
response.verification["categoryItemsCreated"] = qCategoryItems.cnt;
|
||||
|
||||
// Verification Step 4: Check templates exist (in ItemTemplateLinks)
|
||||
// Verification Step 4: Check templates exist (in lt_ItemID_TemplateItemID)
|
||||
qTemplates = queryExecute("
|
||||
SELECT COUNT(DISTINCT tl.TemplateItemID) as cnt
|
||||
FROM ItemTemplateLinks tl
|
||||
FROM lt_ItemID_TemplateItemID tl
|
||||
INNER JOIN Items t ON t.ItemID = tl.TemplateItemID
|
||||
", {}, { datasource: "payfrit" });
|
||||
|
||||
response.verification["templatesInLinks"] = qTemplates.cnt;
|
||||
|
||||
// Verification Step 5: Find orphans at ParentID=0
|
||||
// Orphan = ParentID=0, no children pointing to it, not in ItemTemplateLinks
|
||||
// Orphan = ParentID=0, no children pointing to it, not in lt_ItemID_TemplateItemID
|
||||
qOrphans = queryExecute("
|
||||
SELECT i.ItemID, i.ItemName, i.ItemBusinessID
|
||||
SELECT i.ID, i.Name, i.BusinessID
|
||||
FROM Items i
|
||||
WHERE i.ItemParentItemID = 0
|
||||
WHERE i.ParentItemID = 0
|
||||
AND NOT EXISTS (
|
||||
SELECT 1 FROM Items child WHERE child.ItemParentItemID = i.ItemID
|
||||
SELECT 1 FROM Items child WHERE child.ParentItemID = i.ID
|
||||
)
|
||||
AND NOT EXISTS (
|
||||
SELECT 1 FROM ItemTemplateLinks tl WHERE tl.TemplateItemID = i.ItemID
|
||||
SELECT 1 FROM lt_ItemID_TemplateItemID tl WHERE tl.TemplateItemID = i.ID
|
||||
)
|
||||
ORDER BY i.ItemBusinessID, i.ItemName
|
||||
ORDER BY i.BusinessID, i.Name
|
||||
", {}, { datasource: "payfrit" });
|
||||
|
||||
response.verification["orphanCount"] = qOrphans.recordCount;
|
||||
|
|
@ -85,8 +85,8 @@ try {
|
|||
for (orphan in qOrphans) {
|
||||
arrayAppend(response.orphans, {
|
||||
"ItemID": orphan.ItemID,
|
||||
"ItemName": orphan.ItemName,
|
||||
"BusinessID": orphan.ItemBusinessID
|
||||
"Name": orphan.Name,
|
||||
"BusinessID": orphan.BusinessID
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -96,7 +96,7 @@ try {
|
|||
|
||||
if (!safeToCleanup) {
|
||||
arrayAppend(response.steps, "VERIFICATION FAILED - Cannot cleanup yet");
|
||||
arrayAppend(response.steps, "- " & qNoBusinessID.cnt & " items still missing ItemBusinessID");
|
||||
arrayAppend(response.steps, "- " & qNoBusinessID.cnt & " items still missing BusinessID");
|
||||
response["OK"] = false;
|
||||
writeOutput(serializeJSON(response));
|
||||
abort;
|
||||
|
|
@ -119,31 +119,31 @@ try {
|
|||
// Execute cleanup
|
||||
arrayAppend(response.steps, "Executing cleanup...");
|
||||
|
||||
// Step 1: Drop ItemCategoryID column
|
||||
// Step 1: Drop CategoryID column
|
||||
try {
|
||||
queryExecute("
|
||||
ALTER TABLE Items DROP COLUMN ItemCategoryID
|
||||
ALTER TABLE Items DROP COLUMN CategoryID
|
||||
", {}, { datasource: "payfrit" });
|
||||
arrayAppend(response.steps, "Dropped ItemCategoryID column from Items");
|
||||
arrayAppend(response.steps, "Dropped CategoryID column from Items");
|
||||
} catch (any e) {
|
||||
if (findNoCase("check that column", e.message) || findNoCase("Unknown column", e.message)) {
|
||||
arrayAppend(response.steps, "ItemCategoryID column already dropped");
|
||||
arrayAppend(response.steps, "CategoryID column already dropped");
|
||||
} else {
|
||||
arrayAppend(response.steps, "Warning dropping ItemCategoryID: " & e.message);
|
||||
arrayAppend(response.steps, "Warning dropping CategoryID: " & e.message);
|
||||
}
|
||||
}
|
||||
|
||||
// Step 2: Drop ItemIsModifierTemplate column (now derived from ItemTemplateLinks)
|
||||
// Step 2: Drop IsModifierTemplate column (now derived from lt_ItemID_TemplateItemID)
|
||||
try {
|
||||
queryExecute("
|
||||
ALTER TABLE Items DROP COLUMN ItemIsModifierTemplate
|
||||
ALTER TABLE Items DROP COLUMN IsModifierTemplate
|
||||
", {}, { datasource: "payfrit" });
|
||||
arrayAppend(response.steps, "Dropped ItemIsModifierTemplate column from Items");
|
||||
arrayAppend(response.steps, "Dropped IsModifierTemplate column from Items");
|
||||
} catch (any e) {
|
||||
if (findNoCase("check that column", e.message) || findNoCase("Unknown column", e.message)) {
|
||||
arrayAppend(response.steps, "ItemIsModifierTemplate column already dropped");
|
||||
arrayAppend(response.steps, "IsModifierTemplate column already dropped");
|
||||
} else {
|
||||
arrayAppend(response.steps, "Warning dropping ItemIsModifierTemplate: " & e.message);
|
||||
arrayAppend(response.steps, "Warning dropping IsModifierTemplate: " & e.message);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -34,8 +34,8 @@ if (businessId <= 0) {
|
|||
try {
|
||||
// Find duplicate UserIDs for this business (keep the one with highest status or oldest)
|
||||
qDupes = queryExecute("
|
||||
SELECT UserID, COUNT(*) as cnt, MIN(EmployeeID) as keepId
|
||||
FROM lt_Users_Businesses_Employees
|
||||
SELECT ID, COUNT(*) as cnt, MIN(ID) as keepId
|
||||
FROM Employees
|
||||
WHERE BusinessID = ?
|
||||
GROUP BY UserID
|
||||
HAVING COUNT(*) > 1
|
||||
|
|
@ -45,8 +45,8 @@ try {
|
|||
for (row in qDupes) {
|
||||
// Delete all but the one we want to keep (the one with lowest EmployeeID)
|
||||
qDel = queryExecute("
|
||||
DELETE FROM lt_Users_Businesses_Employees
|
||||
WHERE BusinessID = ? AND UserID = ? AND EmployeeID != ?
|
||||
DELETE FROM Employees
|
||||
WHERE BusinessID = ? AND UserID = ? AND ID != ?
|
||||
", [
|
||||
{ value: businessId, cfsqltype: "cf_sql_integer" },
|
||||
{ value: row.UserID, cfsqltype: "cf_sql_integer" },
|
||||
|
|
@ -57,19 +57,19 @@ try {
|
|||
|
||||
// Get remaining employees
|
||||
qRemaining = queryExecute("
|
||||
SELECT e.EmployeeID, e.UserID, u.UserFirstName, u.UserLastName
|
||||
FROM lt_Users_Businesses_Employees e
|
||||
JOIN Users u ON e.UserID = u.UserID
|
||||
SELECT e.ID, e.UserID, u.FirstName, u.LastName
|
||||
FROM Employees e
|
||||
JOIN Users u ON e.UserID = u.ID
|
||||
WHERE e.BusinessID = ?
|
||||
ORDER BY e.EmployeeID
|
||||
ORDER BY e.ID
|
||||
", [{ value: businessId, cfsqltype: "cf_sql_integer" }], { datasource: "payfrit" });
|
||||
|
||||
remaining = [];
|
||||
for (r in qRemaining) {
|
||||
arrayAppend(remaining, {
|
||||
"EmployeeID": r.EmployeeID,
|
||||
"EmployeeID": r.ID,
|
||||
"UserID": r.UserID,
|
||||
"Name": trim(r.UserFirstName & " " & r.UserLastName)
|
||||
"Name": trim(r.FirstName & " " & r.LastName)
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,106 +9,120 @@ try {
|
|||
// Keep only Lazy Daisy (BusinessID 37)
|
||||
keepBusinessID = 37;
|
||||
|
||||
// First, reassign all beacons to Lazy Daisy
|
||||
// Unassign all beacons from service points of other businesses
|
||||
queryExecute("
|
||||
UPDATE lt_Beacon_Businesses_ServicePoints
|
||||
SET BusinessID = :keepID
|
||||
UPDATE ServicePoints
|
||||
SET BeaconID = NULL, AssignedByUserID = NULL
|
||||
WHERE BusinessID != :keepID AND BeaconID IS NOT NULL
|
||||
", { keepID: keepBusinessID }, { datasource: "payfrit" });
|
||||
response.steps.append("Reassigned all beacons to Lazy Daisy");
|
||||
response.steps.append("Unassigned beacons from other businesses' service points");
|
||||
|
||||
// Get list of businesses to delete
|
||||
qBiz = queryExecute("
|
||||
SELECT BusinessID, BusinessName FROM Businesses WHERE BusinessID != :keepID
|
||||
SELECT ID, Name FROM Businesses WHERE ID != :keepID
|
||||
", { keepID: keepBusinessID }, { datasource: "payfrit" });
|
||||
|
||||
deletedBusinesses = [];
|
||||
for (i = 1; i <= qBiz.recordCount; i++) {
|
||||
arrayAppend(deletedBusinesses, qBiz.BusinessName[i]);
|
||||
arrayAppend(deletedBusinesses, qBiz.Name[i]);
|
||||
}
|
||||
response.steps.append("Found " & qBiz.recordCount & " businesses to delete");
|
||||
|
||||
// Delete related data first (foreign key constraints)
|
||||
// Delete ItemTemplateLinks for items from other businesses
|
||||
// Delete lt_ItemID_TemplateItemID for items from other businesses
|
||||
queryExecute("
|
||||
DELETE itl FROM ItemTemplateLinks itl
|
||||
JOIN Items i ON i.ItemID = itl.ItemID
|
||||
WHERE i.ItemBusinessID != :keepID
|
||||
DELETE itl FROM lt_ItemID_TemplateItemID itl
|
||||
JOIN Items i ON i.ID = itl.ItemID
|
||||
WHERE i.BusinessID != :keepID
|
||||
", { keepID: keepBusinessID }, { datasource: "payfrit" });
|
||||
response.steps.append("Deleted ItemTemplateLinks for other businesses");
|
||||
response.steps.append("Deleted lt_ItemID_TemplateItemID for other businesses");
|
||||
|
||||
// Delete Items for other businesses
|
||||
qItems = queryExecute("
|
||||
SELECT COUNT(*) as cnt FROM Items WHERE ItemBusinessID != :keepID
|
||||
SELECT COUNT(*) as cnt FROM Items WHERE BusinessID != :keepID
|
||||
", { keepID: keepBusinessID }, { datasource: "payfrit" });
|
||||
queryExecute("
|
||||
DELETE FROM Items WHERE ItemBusinessID != :keepID
|
||||
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("
|
||||
DELETE FROM Categories WHERE CategoryBusinessID != :keepID
|
||||
DELETE FROM Categories WHERE BusinessID != :keepID
|
||||
", { keepID: keepBusinessID }, { datasource: "payfrit" });
|
||||
response.steps.append("Deleted categories from other businesses");
|
||||
|
||||
// Delete Hours for other businesses
|
||||
queryExecute("
|
||||
DELETE FROM Hours WHERE HoursBusinessID != :keepID
|
||||
DELETE FROM Hours WHERE BusinessID != :keepID
|
||||
", { keepID: keepBusinessID }, { datasource: "payfrit" });
|
||||
response.steps.append("Deleted hours from other businesses");
|
||||
|
||||
// Delete Employees for other businesses (skip if table doesn't exist)
|
||||
// Delete Employees for other businesses
|
||||
try {
|
||||
queryExecute("
|
||||
DELETE FROM Employees WHERE EmployeeBusinessID != :keepID
|
||||
DELETE FROM Employees WHERE BusinessID != :keepID
|
||||
", { keepID: keepBusinessID }, { datasource: "payfrit" });
|
||||
response.steps.append("Deleted employees from other businesses");
|
||||
} catch (any e) {
|
||||
response.steps.append("Skipped employees (table may not exist)");
|
||||
}
|
||||
|
||||
// Delete ServicePoints for other businesses (skip if table doesn't exist)
|
||||
// Delete ServicePoints for other businesses
|
||||
try {
|
||||
queryExecute("
|
||||
DELETE FROM ServicePoints WHERE ServicePointBusinessID != :keepID
|
||||
DELETE FROM ServicePoints WHERE BusinessID != :keepID
|
||||
", { keepID: keepBusinessID }, { datasource: "payfrit" });
|
||||
response.steps.append("Deleted service points from other businesses");
|
||||
} catch (any e) {
|
||||
response.steps.append("Skipped service points (table may not exist)");
|
||||
}
|
||||
|
||||
// Delete Stations for other businesses (skip if table doesn't exist)
|
||||
// Delete Stations for other businesses
|
||||
try {
|
||||
queryExecute("
|
||||
DELETE FROM Stations WHERE StationBusinessID != :keepID
|
||||
DELETE FROM Stations WHERE BusinessID != :keepID
|
||||
", { keepID: keepBusinessID }, { datasource: "payfrit" });
|
||||
response.steps.append("Deleted stations from other businesses");
|
||||
} catch (any e) {
|
||||
response.steps.append("Skipped stations (table may not exist)");
|
||||
}
|
||||
|
||||
// Delete beacon-business mappings for other businesses
|
||||
try {
|
||||
queryExecute("
|
||||
DELETE FROM lt_BeaconsID_BusinessesID WHERE BusinessID != :keepID
|
||||
", { keepID: keepBusinessID }, { datasource: "payfrit" });
|
||||
response.steps.append("Deleted beacon mappings for other businesses");
|
||||
} catch (any e) {
|
||||
response.steps.append("Skipped beacon mappings (table may not exist)");
|
||||
}
|
||||
|
||||
// Finally delete the businesses themselves
|
||||
queryExecute("
|
||||
DELETE FROM Businesses WHERE BusinessID != :keepID
|
||||
DELETE FROM Businesses WHERE ID != :keepID
|
||||
", { keepID: keepBusinessID }, { datasource: "payfrit" });
|
||||
response.steps.append("Deleted " & arrayLen(deletedBusinesses) & " businesses");
|
||||
|
||||
// Get beacon status
|
||||
qBeacons = queryExecute("
|
||||
SELECT lt.BeaconID, b.BeaconUUID, lt.BusinessID, biz.BusinessName, lt.ServicePointID
|
||||
FROM lt_Beacon_Businesses_ServicePoints lt
|
||||
JOIN Beacons b ON b.BeaconID = lt.BeaconID
|
||||
JOIN Businesses biz ON biz.BusinessID = lt.BusinessID
|
||||
SELECT sp.ID AS ServicePointID, sp.BeaconID, sp.BusinessID,
|
||||
b.UUID, biz.Name AS BusinessName, sp.Name AS ServicePointName
|
||||
FROM ServicePoints sp
|
||||
JOIN Beacons b ON b.ID = sp.BeaconID
|
||||
JOIN Businesses biz ON biz.ID = sp.BusinessID
|
||||
WHERE sp.BeaconID IS NOT NULL
|
||||
", {}, { datasource: "payfrit" });
|
||||
|
||||
beacons = [];
|
||||
for (i = 1; i <= qBeacons.recordCount; i++) {
|
||||
arrayAppend(beacons, {
|
||||
"BeaconID": qBeacons.BeaconID[i],
|
||||
"UUID": qBeacons.BeaconUUID[i],
|
||||
"UUID": qBeacons.UUID[i],
|
||||
"BusinessID": qBeacons.BusinessID[i],
|
||||
"BusinessName": qBeacons.BusinessName[i],
|
||||
"ServicePointID": qBeacons.ServicePointID[i]
|
||||
"ServicePointID": qBeacons.ServicePointID[i],
|
||||
"ServicePointName": qBeacons.ServicePointName[i]
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,9 +7,9 @@ param name="url.action" default="check"; // "check" or "deactivate"
|
|||
|
||||
// Check the item first
|
||||
qItem = queryExecute("
|
||||
SELECT ItemID, ItemName, ItemParentItemID, ItemIsActive, ItemIsCollapsible
|
||||
SELECT ID, Name, ParentItemID, IsActive, IsCollapsible
|
||||
FROM Items
|
||||
WHERE ItemID = :itemId
|
||||
WHERE ID = :itemId
|
||||
", { itemId: url.itemId });
|
||||
|
||||
if (qItem.recordCount == 0) {
|
||||
|
|
@ -19,25 +19,25 @@ if (qItem.recordCount == 0) {
|
|||
|
||||
// Get all children (direct only for display)
|
||||
qChildren = queryExecute("
|
||||
SELECT ItemID, ItemName
|
||||
SELECT ID, Name
|
||||
FROM Items
|
||||
WHERE ItemParentItemID = :itemId
|
||||
WHERE ParentItemID = :itemId
|
||||
", { itemId: url.itemId });
|
||||
|
||||
childList = [];
|
||||
for (row in qChildren) {
|
||||
arrayAppend(childList, { "ItemID": row.ItemID, "ItemName": row.ItemName });
|
||||
arrayAppend(childList, { "ItemID": row.ID, "Name": row.Name });
|
||||
}
|
||||
|
||||
result = {
|
||||
"OK": true,
|
||||
"ACTION": url.action,
|
||||
"ITEM": {
|
||||
"ItemID": qItem.ItemID,
|
||||
"ItemName": qItem.ItemName,
|
||||
"ItemParentItemID": qItem.ItemParentItemID,
|
||||
"ItemIsActive": qItem.ItemIsActive,
|
||||
"ItemIsCollapsible": qItem.ItemIsCollapsible
|
||||
"ItemID": qItem.ID,
|
||||
"Name": qItem.Name,
|
||||
"ParentItemID": qItem.ParentItemID,
|
||||
"IsActive": qItem.IsActive,
|
||||
"IsCollapsible": qItem.IsCollapsible
|
||||
},
|
||||
"HAS_CHILDREN": qChildren.recordCount > 0,
|
||||
"CHILD_COUNT": qChildren.recordCount,
|
||||
|
|
@ -48,14 +48,14 @@ if (url.action == "deactivate") {
|
|||
// Deactivate children first
|
||||
queryExecute("
|
||||
UPDATE Items
|
||||
SET ItemIsActive = 0
|
||||
WHERE ItemParentItemID = :itemId
|
||||
SET IsActive = 0
|
||||
WHERE ParentItemID = :itemId
|
||||
", { itemId: url.itemId });
|
||||
|
||||
// Then deactivate the parent
|
||||
queryExecute("
|
||||
UPDATE Items
|
||||
SET ItemIsActive = 0
|
||||
SET IsActive = 0
|
||||
WHERE ItemID = :itemId
|
||||
", { itemId: url.itemId });
|
||||
|
||||
|
|
|
|||
|
|
@ -5,13 +5,13 @@
|
|||
// Delete cart orders (status 0) to reset for testing
|
||||
result = queryExecute("
|
||||
DELETE FROM OrderLineItems
|
||||
WHERE OrderLineItemOrderID IN (
|
||||
SELECT OrderID FROM Orders WHERE OrderStatusID = 0
|
||||
WHERE OrderID IN (
|
||||
SELECT ID FROM Orders WHERE StatusID = 0
|
||||
)
|
||||
", {}, { datasource = "payfrit" });
|
||||
|
||||
result2 = queryExecute("
|
||||
DELETE FROM Orders WHERE OrderStatusID = 0
|
||||
DELETE FROM Orders WHERE StatusID = 0
|
||||
", {}, { datasource = "payfrit" });
|
||||
|
||||
writeOutput(serializeJSON({
|
||||
|
|
|
|||
|
|
@ -10,27 +10,27 @@ try {
|
|||
businessIDs = [38, 39, 40, 41, 42];
|
||||
|
||||
for (bizID in businessIDs) {
|
||||
// Delete ItemTemplateLinks for items belonging to this business
|
||||
// Delete lt_ItemID_TemplateItemID for items belonging to this business
|
||||
queryExecute("
|
||||
DELETE itl FROM ItemTemplateLinks itl
|
||||
INNER JOIN Items i ON i.ItemID = itl.ItemID
|
||||
WHERE i.ItemBusinessID = :bizID
|
||||
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 ItemBusinessID = :bizID", { bizID: bizID }, { datasource: "payfrit" });
|
||||
queryExecute("DELETE FROM Items WHERE BusinessID = :bizID", { bizID: bizID }, { datasource: "payfrit" });
|
||||
|
||||
// Delete Categories
|
||||
queryExecute("DELETE FROM Categories WHERE CategoryBusinessID = :bizID", { bizID: bizID }, { datasource: "payfrit" });
|
||||
queryExecute("DELETE FROM Categories WHERE BusinessID = :bizID", { bizID: bizID }, { datasource: "payfrit" });
|
||||
|
||||
// Delete Hours
|
||||
queryExecute("DELETE FROM Hours WHERE HoursBusinessID = :bizID", { bizID: bizID }, { datasource: "payfrit" });
|
||||
queryExecute("DELETE FROM Hours WHERE BusinessID = :bizID", { bizID: bizID }, { datasource: "payfrit" });
|
||||
|
||||
// Delete Addresses linked to this business
|
||||
queryExecute("DELETE FROM Addresses WHERE AddressBusinessID = :bizID", { bizID: bizID }, { datasource: "payfrit" });
|
||||
queryExecute("DELETE FROM Addresses WHERE BusinessID = :bizID", { bizID: bizID }, { datasource: "payfrit" });
|
||||
|
||||
// Delete the Business itself
|
||||
queryExecute("DELETE FROM Businesses WHERE BusinessID = :bizID", { bizID: bizID }, { datasource: "payfrit" });
|
||||
queryExecute("DELETE FROM Businesses WHERE ID = :bizID", { bizID: bizID }, { datasource: "payfrit" });
|
||||
|
||||
response.steps.append("Deleted business " & bizID & " and all related data");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,9 +5,9 @@
|
|||
try {
|
||||
result = queryExecute("
|
||||
UPDATE Tasks
|
||||
SET TaskCompletedOn = NOW()
|
||||
SET CompletedOn = NOW()
|
||||
WHERE TaskTypeID = 2
|
||||
AND TaskCompletedOn IS NULL
|
||||
AND CompletedOn IS NULL
|
||||
", {}, { datasource: "payfrit" });
|
||||
|
||||
affected = result.recordCount ?: 0;
|
||||
|
|
|
|||
|
|
@ -15,24 +15,24 @@ try {
|
|||
|
||||
// First, check if Big Dean's has a Beverages/Drinks category
|
||||
qExistingCat = queryExecute("
|
||||
SELECT CategoryID, CategoryName FROM Categories
|
||||
WHERE CategoryBusinessID = :bizId AND (CategoryName LIKE '%Drink%' OR CategoryName LIKE '%Beverage%')
|
||||
SELECT ID, Name FROM Categories
|
||||
WHERE BusinessID = :bizId AND (Name LIKE '%Drink%' OR Name LIKE '%Beverage%')
|
||||
", { bizId: bigDeansBusinessId }, { datasource: "payfrit" });
|
||||
|
||||
if (qExistingCat.recordCount > 0) {
|
||||
drinksCategoryId = qExistingCat.CategoryID;
|
||||
response["CategoryNote"] = "Using existing category: " & qExistingCat.CategoryName;
|
||||
response["CategoryNote"] = "Using existing category: " & qExistingCat.Name;
|
||||
} else {
|
||||
// Create a new Beverages category for Big Dean's
|
||||
qMaxCat = queryExecute("SELECT COALESCE(MAX(CategoryID), 0) + 1 as nextId FROM Categories", {}, { datasource: "payfrit" });
|
||||
drinksCategoryId = qMaxCat.nextId;
|
||||
|
||||
qMaxSort = queryExecute("
|
||||
SELECT COALESCE(MAX(CategorySortOrder), 0) + 1 as nextSort FROM Categories WHERE CategoryBusinessID = :bizId
|
||||
SELECT COALESCE(MAX(SortOrder), 0) + 1 as nextSort FROM Categories WHERE BusinessID = :bizId
|
||||
", { bizId: bigDeansBusinessId }, { datasource: "payfrit" });
|
||||
|
||||
queryExecute("
|
||||
INSERT INTO Categories (CategoryID, CategoryBusinessID, CategoryParentCategoryID, CategoryName, CategorySortOrder, CategoryAddedOn)
|
||||
INSERT INTO Categories (CategoryID, BusinessID, ParentCategoryID, Name, SortOrder, AddedOn)
|
||||
VALUES (:catId, :bizId, 0, 'Beverages', :sortOrder, NOW())
|
||||
", {
|
||||
catId: drinksCategoryId,
|
||||
|
|
@ -61,8 +61,8 @@ try {
|
|||
for (drink in drinks) {
|
||||
// Check if item already exists
|
||||
qExists = queryExecute("
|
||||
SELECT ItemID FROM Items
|
||||
WHERE ItemBusinessID = :bizId AND ItemName = :name AND ItemCategoryID = :catId
|
||||
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) {
|
||||
|
|
@ -72,10 +72,10 @@ try {
|
|||
|
||||
queryExecute("
|
||||
INSERT INTO Items (
|
||||
ItemID, ItemBusinessID, ItemCategoryID, ItemParentItemID,
|
||||
ItemName, ItemDescription, ItemPrice, ItemIsActive,
|
||||
ItemSortOrder, ItemIsCollapsible, ItemRequiresChildSelection,
|
||||
ItemAddedOn
|
||||
ItemID, BusinessID, CategoryID, ParentItemID,
|
||||
Name, Description, Price, IsActive,
|
||||
SortOrder, IsCollapsible, RequiresChildSelection,
|
||||
AddedOn
|
||||
) VALUES (
|
||||
:itemId, :bizId, :catId, 0,
|
||||
:name, :desc, :price, 1,
|
||||
|
|
@ -103,10 +103,10 @@ try {
|
|||
qMaxOpt = queryExecute("SELECT COALESCE(MAX(ItemID), 0) + 1 as nextId FROM Items", {}, { datasource: "payfrit" });
|
||||
queryExecute("
|
||||
INSERT INTO Items (
|
||||
ItemID, ItemBusinessID, ItemCategoryID, ItemParentItemID,
|
||||
ItemName, ItemDescription, ItemPrice, ItemIsActive,
|
||||
ItemSortOrder, ItemIsCollapsible, ItemIsCheckedByDefault,
|
||||
ItemAddedOn
|
||||
ItemID, BusinessID, CategoryID, ParentItemID,
|
||||
Name, Description, Price, IsActive,
|
||||
SortOrder, IsCollapsible, IsCheckedByDefault,
|
||||
AddedOn
|
||||
) VALUES (
|
||||
:itemId, :bizId, 0, :parentId,
|
||||
:name, '', 0, 1,
|
||||
|
|
|
|||
|
|
@ -20,69 +20,74 @@ try {
|
|||
uuid = beaconUUIDs[i];
|
||||
|
||||
// Check if beacon exists
|
||||
qB = queryExecute("SELECT BeaconID FROM Beacons WHERE BeaconUUID = :uuid", { uuid: uuid }, { datasource: "payfrit" });
|
||||
qB = queryExecute("SELECT ID FROM Beacons WHERE UUID = :uuid", { uuid: uuid }, { datasource: "payfrit" });
|
||||
|
||||
if (qB.recordCount == 0) {
|
||||
queryExecute("INSERT INTO Beacons (BeaconUUID, BeaconBusinessID) VALUES (:uuid, :bizID)", { uuid: uuid, bizID: lazyDaisyID }, { datasource: "payfrit" });
|
||||
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" });
|
||||
beaconID = qNew.id;
|
||||
response.steps.append("Created beacon " & beaconID & " with UUID: " & uuid);
|
||||
} else {
|
||||
beaconID = qB.BeaconID;
|
||||
beaconID = qB.ID;
|
||||
response.steps.append("Beacon exists: " & beaconID & " with UUID: " & uuid);
|
||||
}
|
||||
}
|
||||
|
||||
// Get service point Table 1
|
||||
qSP = queryExecute("
|
||||
SELECT ServicePointID FROM ServicePoints
|
||||
WHERE ServicePointBusinessID = :bizID AND ServicePointName = 'Table 1'
|
||||
SELECT ID FROM ServicePoints
|
||||
WHERE BusinessID = :bizID AND Name = 'Table 1'
|
||||
", { bizID: lazyDaisyID }, { datasource: "payfrit" });
|
||||
|
||||
if (qSP.recordCount == 0) {
|
||||
queryExecute("
|
||||
INSERT INTO ServicePoints (ServicePointBusinessID, ServicePointName, ServicePointTypeID)
|
||||
VALUES (:bizID, 'Table 1', 1)
|
||||
INSERT INTO ServicePoints (BusinessID, Name)
|
||||
VALUES (:bizID, 'Table 1')
|
||||
", { bizID: lazyDaisyID }, { datasource: "payfrit" });
|
||||
qSP = queryExecute("SELECT LAST_INSERT_ID() as id", {}, { datasource: "payfrit" });
|
||||
servicePointID = qSP.id;
|
||||
response.steps.append("Created service point 'Table 1' (ID: " & servicePointID & ")");
|
||||
} else {
|
||||
servicePointID = qSP.ServicePointID;
|
||||
servicePointID = qSP.ID;
|
||||
response.steps.append("Found service point 'Table 1' (ID: " & servicePointID & ")");
|
||||
}
|
||||
|
||||
// Get all beacons and map them
|
||||
qBeacons = queryExecute("SELECT BeaconID, BeaconUUID FROM Beacons", {}, { datasource: "payfrit" });
|
||||
// Assign all beacons to the Table 1 service point
|
||||
qBeacons = queryExecute("SELECT ID, UUID FROM Beacons WHERE BusinessID = :bizID", { bizID: lazyDaisyID }, { datasource: "payfrit" });
|
||||
|
||||
for (i = 1; i <= qBeacons.recordCount; i++) {
|
||||
beaconID = qBeacons.BeaconID[i];
|
||||
beaconID = qBeacons.ID[i];
|
||||
|
||||
// Delete old mapping if exists
|
||||
queryExecute("DELETE FROM lt_Beacon_Businesses_ServicePoints WHERE BeaconID = :beaconID", { beaconID: beaconID }, { datasource: "payfrit" });
|
||||
|
||||
// Create new mapping
|
||||
// Unassign this beacon from any existing service point
|
||||
queryExecute("
|
||||
INSERT INTO lt_Beacon_Businesses_ServicePoints (BeaconID, BusinessID, ServicePointID)
|
||||
VALUES (:beaconID, :bizID, :spID)
|
||||
UPDATE ServicePoints SET BeaconID = NULL, AssignedByUserID = NULL
|
||||
WHERE BeaconID = :beaconID
|
||||
", { beaconID: beaconID }, { datasource: "payfrit" });
|
||||
|
||||
// Assign beacon to Table 1 service point
|
||||
queryExecute("
|
||||
UPDATE ServicePoints SET BeaconID = :beaconID, AssignedByUserID = 1
|
||||
WHERE ID = :spID AND BusinessID = :bizID
|
||||
", { beaconID: beaconID, bizID: lazyDaisyID, spID: servicePointID }, { datasource: "payfrit" });
|
||||
response.steps.append("Mapped beacon " & beaconID & " to Lazy Daisy, Table 1");
|
||||
response.steps.append("Assigned beacon " & beaconID & " to Table 1");
|
||||
}
|
||||
|
||||
// Get final status
|
||||
qFinal = queryExecute("
|
||||
SELECT lt.BeaconID, b.BeaconUUID, lt.BusinessID, biz.BusinessName, lt.ServicePointID, sp.ServicePointName
|
||||
FROM lt_Beacon_Businesses_ServicePoints lt
|
||||
JOIN Beacons b ON b.BeaconID = lt.BeaconID
|
||||
JOIN Businesses biz ON biz.BusinessID = lt.BusinessID
|
||||
LEFT JOIN ServicePoints sp ON sp.ServicePointID = lt.ServicePointID
|
||||
SELECT sp.ID AS ServicePointID, sp.BeaconID, sp.BusinessID,
|
||||
b.Name AS BeaconName, b.UUID, sp.Name AS ServicePointName,
|
||||
biz.Name AS BusinessName
|
||||
FROM ServicePoints sp
|
||||
JOIN Beacons b ON b.ID = sp.BeaconID
|
||||
JOIN Businesses biz ON biz.ID = sp.BusinessID
|
||||
WHERE sp.BeaconID IS NOT NULL
|
||||
", {}, { datasource: "payfrit" });
|
||||
|
||||
beacons = [];
|
||||
for (i = 1; i <= qFinal.recordCount; i++) {
|
||||
arrayAppend(beacons, {
|
||||
"BeaconID": qFinal.BeaconID[i],
|
||||
"UUID": qFinal.BeaconUUID[i],
|
||||
"UUID": qFinal.UUID[i],
|
||||
"BusinessID": qFinal.BusinessID[i],
|
||||
"BusinessName": qFinal.BusinessName[i],
|
||||
"ServicePointID": qFinal.ServicePointID[i],
|
||||
|
|
|
|||
|
|
@ -5,11 +5,11 @@ try {
|
|||
// Create ChatMessages table
|
||||
queryExecute("
|
||||
CREATE TABLE IF NOT EXISTS ChatMessages (
|
||||
MessageID INT AUTO_INCREMENT PRIMARY KEY,
|
||||
ID INT AUTO_INCREMENT PRIMARY KEY,
|
||||
TaskID INT NOT NULL,
|
||||
SenderUserID INT NOT NULL,
|
||||
SenderType ENUM('customer', 'worker') NOT NULL,
|
||||
MessageText TEXT NOT NULL,
|
||||
MessageBody TEXT NOT NULL,
|
||||
IsRead TINYINT(1) DEFAULT 0,
|
||||
CreatedOn DATETIME DEFAULT NOW(),
|
||||
|
||||
|
|
@ -21,13 +21,13 @@ try {
|
|||
|
||||
// Also add a "Chat" category if it doesn't exist for business 17
|
||||
existing = queryExecute("
|
||||
SELECT TaskCategoryID FROM TaskCategories
|
||||
WHERE TaskCategoryBusinessID = 17 AND TaskCategoryName = 'Chat'
|
||||
SELECT ID FROM TaskCategories
|
||||
WHERE BusinessID = 17 AND Name = 'Chat'
|
||||
", {}, { datasource: "payfrit" });
|
||||
|
||||
if (existing.recordCount == 0) {
|
||||
queryExecute("
|
||||
INSERT INTO TaskCategories (TaskCategoryBusinessID, TaskCategoryName, TaskCategoryColor)
|
||||
INSERT INTO TaskCategories (BusinessID, Name, Color)
|
||||
VALUES (17, 'Chat', '##2196F3')
|
||||
", {}, { datasource: "payfrit" });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,47 +32,47 @@ try {
|
|||
queryExecute("
|
||||
CREATE TABLE Menus (
|
||||
MenuID INT AUTO_INCREMENT PRIMARY KEY,
|
||||
MenuBusinessID INT NOT NULL,
|
||||
MenuName VARCHAR(100) NOT NULL,
|
||||
MenuDescription VARCHAR(500) NULL,
|
||||
MenuDaysActive INT NOT NULL DEFAULT 127,
|
||||
MenuStartTime TIME NULL,
|
||||
MenuEndTime TIME NULL,
|
||||
MenuSortOrder INT NOT NULL DEFAULT 0,
|
||||
MenuIsActive TINYINT NOT NULL DEFAULT 1,
|
||||
MenuAddedOn DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
INDEX idx_menus_business (MenuBusinessID),
|
||||
INDEX idx_menus_active (MenuBusinessID, MenuIsActive)
|
||||
BusinessID INT NOT NULL,
|
||||
Name VARCHAR(100) NOT NULL,
|
||||
Description VARCHAR(500) NULL,
|
||||
DaysActive INT NOT NULL DEFAULT 127,
|
||||
StartTime TIME NULL,
|
||||
EndTime TIME NULL,
|
||||
SortOrder INT NOT NULL DEFAULT 0,
|
||||
IsActive TINYINT NOT NULL DEFAULT 1,
|
||||
AddedOn DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
INDEX idx_menus_business (BusinessID),
|
||||
INDEX idx_menus_active (BusinessID, IsActive)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
||||
", {}, { datasource: "payfrit" });
|
||||
|
||||
response["OK"] = true;
|
||||
response["MESSAGE"] = "Menus table created successfully";
|
||||
response["SCHEMA"] = {
|
||||
"MenuDaysActive": "Bitmask: 1=Sun, 2=Mon, 4=Tue, 8=Wed, 16=Thu, 32=Fri, 64=Sat (127 = all days)"
|
||||
"DaysActive": "Bitmask: 1=Sun, 2=Mon, 4=Tue, 8=Wed, 16=Thu, 32=Fri, 64=Sat (127 = all days)"
|
||||
};
|
||||
}
|
||||
|
||||
// Check if CategoryMenuID column exists in Categories table
|
||||
// Check if MenuID column exists in Categories table
|
||||
qCatCol = queryExecute("
|
||||
SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE TABLE_SCHEMA = 'payfrit'
|
||||
AND TABLE_NAME = 'Categories'
|
||||
AND COLUMN_NAME = 'CategoryMenuID'
|
||||
AND COLUMN_NAME = 'MenuID'
|
||||
", {}, { datasource: "payfrit" });
|
||||
|
||||
if (qCatCol.recordCount == 0) {
|
||||
// Add CategoryMenuID column to Categories table
|
||||
// Add MenuID column to Categories table
|
||||
queryExecute("
|
||||
ALTER TABLE Categories
|
||||
ADD COLUMN CategoryMenuID INT NULL DEFAULT NULL AFTER CategoryBusinessID,
|
||||
ADD INDEX idx_categories_menu (CategoryMenuID)
|
||||
ADD COLUMN MenuID INT NULL DEFAULT NULL AFTER BusinessID,
|
||||
ADD INDEX idx_categories_menu (MenuID)
|
||||
", {}, { datasource: "payfrit" });
|
||||
response["CATEGORIES_UPDATED"] = true;
|
||||
response["CATEGORIES_MESSAGE"] = "Added CategoryMenuID column to Categories table";
|
||||
response["CATEGORIES_MESSAGE"] = "Added MenuID column to Categories table";
|
||||
} else {
|
||||
response["CATEGORIES_UPDATED"] = false;
|
||||
response["CATEGORIES_MESSAGE"] = "CategoryMenuID column already exists";
|
||||
response["CATEGORIES_MESSAGE"] = "MenuID column already exists";
|
||||
}
|
||||
|
||||
} catch (any e) {
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
*
|
||||
* POST body:
|
||||
* {
|
||||
* "BusinessName": "Century Casino",
|
||||
* "Name": "Century Casino",
|
||||
* "UserID": 1,
|
||||
* "ChildBusinessIDs": [47, 48] // Optional: link existing businesses as children
|
||||
* }
|
||||
|
|
@ -36,13 +36,13 @@ response = { "OK": false };
|
|||
try {
|
||||
data = readJsonBody();
|
||||
|
||||
BusinessName = structKeyExists(data, "BusinessName") ? trim(data.BusinessName) : "";
|
||||
Name = structKeyExists(data, "Name") ? trim(data.Name) : "";
|
||||
UserID = structKeyExists(data, "UserID") ? val(data.UserID) : 0;
|
||||
ChildBusinessIDs = structKeyExists(data, "ChildBusinessIDs") && isArray(data.ChildBusinessIDs) ? data.ChildBusinessIDs : [];
|
||||
|
||||
if (!len(BusinessName)) {
|
||||
if (!len(Name)) {
|
||||
response["ERROR"] = "missing_name";
|
||||
response["MESSAGE"] = "BusinessName is required";
|
||||
response["MESSAGE"] = "Name is required";
|
||||
writeOutput(serializeJSON(response));
|
||||
abort;
|
||||
}
|
||||
|
|
@ -56,7 +56,7 @@ try {
|
|||
|
||||
// Create minimal address record (just a placeholder)
|
||||
queryExecute("
|
||||
INSERT INTO Addresses (AddressLine1, AddressUserID, AddressTypeID, AddressAddedOn)
|
||||
INSERT INTO Addresses (Line1, UserID, AddressTypeID, AddedOn)
|
||||
VALUES ('Parent Business - No Physical Location', :userID, 2, NOW())
|
||||
", {
|
||||
userID: UserID
|
||||
|
|
@ -67,10 +67,10 @@ try {
|
|||
|
||||
// Create parent business (no menu, no hours, just a shell)
|
||||
queryExecute("
|
||||
INSERT INTO Businesses (BusinessName, BusinessUserID, BusinessAddressID, BusinessParentBusinessID, BusinessDeliveryZipCodes, BusinessAddedOn)
|
||||
INSERT INTO Businesses (Name, UserID, AddressID, ParentBusinessID, BusinessDeliveryZipCodes, AddedOn)
|
||||
VALUES (:name, :userId, :addressId, NULL, '', NOW())
|
||||
", {
|
||||
name: BusinessName,
|
||||
name: Name,
|
||||
userId: UserID,
|
||||
addressId: addressId
|
||||
}, { datasource = "payfrit" });
|
||||
|
|
@ -80,7 +80,7 @@ try {
|
|||
|
||||
// Link address back to business
|
||||
queryExecute("
|
||||
UPDATE Addresses SET AddressBusinessID = :bizId WHERE AddressID = :addrId
|
||||
UPDATE Addresses SET BusinessID = :bizId WHERE ID = :addrId
|
||||
", {
|
||||
bizId: newBusinessID,
|
||||
addrId: addressId
|
||||
|
|
@ -92,7 +92,7 @@ try {
|
|||
childID = val(childID);
|
||||
if (childID > 0) {
|
||||
queryExecute("
|
||||
UPDATE Businesses SET BusinessParentBusinessID = :parentId WHERE BusinessID = :childId
|
||||
UPDATE Businesses SET ParentBusinessID = :parentId WHERE ID = :childId
|
||||
", {
|
||||
parentId: newBusinessID,
|
||||
childId: childID
|
||||
|
|
@ -103,7 +103,7 @@ try {
|
|||
|
||||
response["OK"] = true;
|
||||
response["BusinessID"] = newBusinessID;
|
||||
response["BusinessName"] = BusinessName;
|
||||
response["Name"] = Name;
|
||||
response["MESSAGE"] = "Parent business created";
|
||||
if (arrayLen(linkedChildren) > 0) {
|
||||
response["LinkedChildren"] = linkedChildren;
|
||||
|
|
|
|||
|
|
@ -9,22 +9,22 @@ bizId = 27;
|
|||
deactivatedIds = [11177, 11180, 11183, 11186, 11190, 11193, 11196, 11199, 11204, 11212, 11220, 11259];
|
||||
|
||||
qDeactivated = queryExecute("
|
||||
SELECT i.ItemID, i.ItemName, i.ItemParentItemID, i.ItemIsActive, i.ItemIsCollapsible,
|
||||
(SELECT COUNT(*) FROM Items c WHERE c.ItemParentItemID = i.ItemID) as ChildCount,
|
||||
(SELECT GROUP_CONCAT(c.ItemName) FROM Items c WHERE c.ItemParentItemID = i.ItemID) as Children
|
||||
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
|
||||
FROM Items i
|
||||
WHERE i.ItemID IN (:ids)
|
||||
ORDER BY i.ItemID
|
||||
WHERE i.ID IN (:ids)
|
||||
ORDER BY i.ID
|
||||
", { ids: { value: arrayToList(deactivatedIds), list: true } }, { datasource: "payfrit" });
|
||||
|
||||
items = [];
|
||||
for (row in qDeactivated) {
|
||||
arrayAppend(items, {
|
||||
"ItemID": row.ItemID,
|
||||
"ItemName": row.ItemName,
|
||||
"ParentID": row.ItemParentItemID,
|
||||
"IsActive": row.ItemIsActive,
|
||||
"IsCollapsible": row.ItemIsCollapsible,
|
||||
"ItemID": row.ID,
|
||||
"Name": row.Name,
|
||||
"ParentID": row.ParentItemID,
|
||||
"IsActive": row.IsActive,
|
||||
"IsCollapsible": row.IsCollapsible,
|
||||
"ChildCount": row.ChildCount,
|
||||
"Children": row.Children
|
||||
});
|
||||
|
|
|
|||
|
|
@ -9,24 +9,24 @@ bizId = 27;
|
|||
qLinks = queryExecute("
|
||||
SELECT
|
||||
tl.ItemID as MenuItemID,
|
||||
mi.ItemName as MenuItemName,
|
||||
mi.ItemParentItemID,
|
||||
mi.Name as MenuName,
|
||||
mi.ParentItemID,
|
||||
tl.TemplateItemID,
|
||||
t.ItemName as TemplateName,
|
||||
t.Name as TemplateName,
|
||||
tl.SortOrder
|
||||
FROM ItemTemplateLinks tl
|
||||
JOIN Items mi ON mi.ItemID = tl.ItemID
|
||||
FROM lt_ItemID_TemplateItemID tl
|
||||
JOIN Items mi ON mi.ID = tl.ItemID
|
||||
JOIN Items t ON t.ItemID = tl.TemplateItemID
|
||||
WHERE mi.ItemBusinessID = :bizId
|
||||
ORDER BY mi.ItemParentItemID, mi.ItemName, tl.SortOrder
|
||||
WHERE mi.BusinessID = :bizId
|
||||
ORDER BY mi.ParentItemID, mi.Name, tl.SortOrder
|
||||
", { bizId: bizId }, { datasource: "payfrit" });
|
||||
|
||||
links = [];
|
||||
for (row in qLinks) {
|
||||
arrayAppend(links, {
|
||||
"MenuItemID": row.MenuItemID,
|
||||
"MenuItemName": row.MenuItemName,
|
||||
"ParentItemID": row.ItemParentItemID,
|
||||
"MenuName": row.MenuName,
|
||||
"ParentItemID": row.ParentItemID,
|
||||
"TemplateItemID": row.TemplateItemID,
|
||||
"TemplateName": row.TemplateName
|
||||
});
|
||||
|
|
@ -34,20 +34,20 @@ for (row in qLinks) {
|
|||
|
||||
// Get burgers specifically (parent = 11271)
|
||||
qBurgers = queryExecute("
|
||||
SELECT ItemID, ItemName FROM Items
|
||||
WHERE ItemBusinessID = :bizId AND ItemParentItemID = 11271 AND ItemIsActive = 1
|
||||
ORDER BY ItemSortOrder
|
||||
SELECT ID, Name FROM Items
|
||||
WHERE BusinessID = :bizId AND ParentItemID = 11271 AND IsActive = 1
|
||||
ORDER BY SortOrder
|
||||
", { bizId: bizId }, { datasource: "payfrit" });
|
||||
|
||||
burgers = [];
|
||||
for (row in qBurgers) {
|
||||
// Get templates for this burger
|
||||
qBurgerTemplates = queryExecute("
|
||||
SELECT tl.TemplateItemID, t.ItemName as TemplateName
|
||||
FROM ItemTemplateLinks tl
|
||||
SELECT tl.TemplateItemID, t.Name as TemplateName
|
||||
FROM lt_ItemID_TemplateItemID tl
|
||||
JOIN Items t ON t.ItemID = tl.TemplateItemID
|
||||
WHERE tl.ItemID = :itemId
|
||||
", { itemId: row.ItemID }, { datasource: "payfrit" });
|
||||
", { itemId: row.ID }, { datasource: "payfrit" });
|
||||
|
||||
templates = [];
|
||||
for (t in qBurgerTemplates) {
|
||||
|
|
@ -55,8 +55,8 @@ for (row in qBurgers) {
|
|||
}
|
||||
|
||||
arrayAppend(burgers, {
|
||||
"ItemID": row.ItemID,
|
||||
"ItemName": row.ItemName,
|
||||
"ItemID": row.ID,
|
||||
"Name": row.Name,
|
||||
"Templates": templates
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,38 +9,38 @@ businessID = 27;
|
|||
qCategories = queryExecute("
|
||||
SELECT DISTINCT
|
||||
p.ItemID as CategoryID,
|
||||
p.ItemName as CategoryName,
|
||||
p.ItemSortOrder
|
||||
p.Name as Name,
|
||||
p.SortOrder
|
||||
FROM Items p
|
||||
INNER JOIN Items c ON c.ItemParentItemID = p.ItemID
|
||||
WHERE p.ItemBusinessID = :businessID
|
||||
AND p.ItemParentItemID = 0
|
||||
AND p.ItemIsActive = 1
|
||||
INNER JOIN Items c ON c.ParentItemID = p.ItemID
|
||||
WHERE p.BusinessID = :businessID
|
||||
AND p.ParentItemID = 0
|
||||
AND p.IsActive = 1
|
||||
AND NOT EXISTS (
|
||||
SELECT 1 FROM ItemTemplateLinks tl WHERE tl.TemplateItemID = p.ItemID
|
||||
SELECT 1 FROM lt_ItemID_TemplateItemID tl WHERE tl.TemplateItemID = p.ItemID
|
||||
)
|
||||
ORDER BY p.ItemSortOrder, p.ItemName
|
||||
ORDER BY p.SortOrder, p.Name
|
||||
", { businessID: businessID });
|
||||
|
||||
cats = [];
|
||||
for (c in qCategories) {
|
||||
arrayAppend(cats, {
|
||||
"CategoryID": c.CategoryID,
|
||||
"CategoryName": c.CategoryName
|
||||
"CategoryID": c.ID,
|
||||
"Name": c.Name
|
||||
});
|
||||
}
|
||||
|
||||
// Also check raw counts
|
||||
rawCount = queryExecute("
|
||||
SELECT COUNT(*) as cnt FROM Items
|
||||
WHERE ItemBusinessID = :bizId AND ItemParentItemID = 0 AND ItemIsActive = 1
|
||||
WHERE BusinessID = :bizId AND ParentItemID = 0 AND IsActive = 1
|
||||
", { bizId: businessID });
|
||||
|
||||
childrenCount = queryExecute("
|
||||
SELECT COUNT(DISTINCT c.ItemParentItemID) as cnt
|
||||
SELECT COUNT(DISTINCT c.ParentItemID) as cnt
|
||||
FROM Items c
|
||||
INNER JOIN Items p ON p.ItemID = c.ItemParentItemID
|
||||
WHERE p.ItemBusinessID = :bizId AND p.ItemParentItemID = 0
|
||||
INNER JOIN Items p ON p.ItemID = c.ParentItemID
|
||||
WHERE p.BusinessID = :bizId AND p.ParentItemID = 0
|
||||
", { bizId: businessID });
|
||||
|
||||
writeOutput(serializeJSON({
|
||||
|
|
|
|||
|
|
@ -9,24 +9,24 @@ bizId = 27;
|
|||
qLinks = queryExecute("
|
||||
SELECT
|
||||
tl.ItemID as MenuItemID,
|
||||
mi.ItemName as MenuItemName,
|
||||
mi.ItemParentItemID as MenuItemParentID,
|
||||
mi.Name as MenuName,
|
||||
mi.ParentItemID as MenuItemParentID,
|
||||
tl.TemplateItemID,
|
||||
t.ItemName as TemplateName,
|
||||
t.ItemIsActive as TemplateActive,
|
||||
t.Name as TemplateName,
|
||||
t.IsActive as TemplateActive,
|
||||
tl.SortOrder
|
||||
FROM ItemTemplateLinks tl
|
||||
JOIN Items mi ON mi.ItemID = tl.ItemID
|
||||
FROM lt_ItemID_TemplateItemID tl
|
||||
JOIN Items mi ON mi.ID = tl.ItemID
|
||||
JOIN Items t ON t.ItemID = tl.TemplateItemID
|
||||
WHERE mi.ItemBusinessID = :bizId
|
||||
ORDER BY mi.ItemName, tl.SortOrder
|
||||
WHERE mi.BusinessID = :bizId
|
||||
ORDER BY mi.Name, tl.SortOrder
|
||||
", { bizId: bizId }, { datasource: "payfrit" });
|
||||
|
||||
links = [];
|
||||
for (row in qLinks) {
|
||||
arrayAppend(links, {
|
||||
"MenuItemID": row.MenuItemID,
|
||||
"MenuItemName": row.MenuItemName,
|
||||
"MenuName": row.MenuName,
|
||||
"MenuItemParentID": row.MenuItemParentID,
|
||||
"TemplateItemID": row.TemplateItemID,
|
||||
"TemplateName": row.TemplateName,
|
||||
|
|
@ -37,20 +37,20 @@ for (row in qLinks) {
|
|||
|
||||
// Get all templates that exist for this business
|
||||
qTemplates = queryExecute("
|
||||
SELECT ItemID, ItemName, ItemIsActive, ItemParentItemID
|
||||
SELECT ID, Name, IsActive, ParentItemID
|
||||
FROM Items
|
||||
WHERE ItemBusinessID = :bizId
|
||||
AND ItemIsCollapsible = 1
|
||||
ORDER BY ItemName
|
||||
WHERE BusinessID = :bizId
|
||||
AND IsCollapsible = 1
|
||||
ORDER BY Name
|
||||
", { bizId: bizId }, { datasource: "payfrit" });
|
||||
|
||||
templates = [];
|
||||
for (row in qTemplates) {
|
||||
arrayAppend(templates, {
|
||||
"ItemID": row.ItemID,
|
||||
"ItemName": row.ItemName,
|
||||
"IsActive": row.ItemIsActive,
|
||||
"ParentID": row.ItemParentItemID
|
||||
"ItemID": row.ID,
|
||||
"Name": row.Name,
|
||||
"IsActive": row.IsActive,
|
||||
"ParentID": row.ParentItemID
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,67 +5,67 @@
|
|||
<cfscript>
|
||||
bizId = 27;
|
||||
|
||||
// Check the template items themselves (IDs from ItemTemplateLinks)
|
||||
// Check the template items themselves (IDs from lt_ItemID_TemplateItemID)
|
||||
templateIds = "11267, 11251, 11246, 11224, 11233, 11230, 11240, 11243, 11237, 11227";
|
||||
|
||||
qTemplates = queryExecute("
|
||||
SELECT ItemID, ItemName, ItemIsCollapsible, ItemIsActive, ItemParentItemID, ItemBusinessID
|
||||
SELECT ID, Name, IsCollapsible, IsActive, ParentItemID, BusinessID
|
||||
FROM Items
|
||||
WHERE ItemID IN (#templateIds#)
|
||||
ORDER BY ItemName
|
||||
WHERE ID IN (#templateIds#)
|
||||
ORDER BY Name
|
||||
", {}, { datasource: "payfrit" });
|
||||
|
||||
templates = [];
|
||||
for (row in qTemplates) {
|
||||
arrayAppend(templates, {
|
||||
"ItemID": row.ItemID,
|
||||
"ItemName": row.ItemName,
|
||||
"IsCollapsible": row.ItemIsCollapsible,
|
||||
"IsActive": row.ItemIsActive,
|
||||
"ParentID": row.ItemParentItemID,
|
||||
"BusinessID": row.ItemBusinessID
|
||||
"ItemID": row.ID,
|
||||
"Name": row.Name,
|
||||
"IsCollapsible": row.IsCollapsible,
|
||||
"IsActive": row.IsActive,
|
||||
"ParentID": row.ParentItemID,
|
||||
"BusinessID": row.BusinessID
|
||||
});
|
||||
}
|
||||
|
||||
// Also check what other templates might exist for burgers
|
||||
// Look for items that are in ItemTemplateLinks but NOT linked to burgers
|
||||
// Look for items that are in lt_ItemID_TemplateItemID but NOT linked to burgers
|
||||
qMissingTemplates = queryExecute("
|
||||
SELECT DISTINCT t.ItemID, t.ItemName, t.ItemIsCollapsible, t.ItemIsActive
|
||||
SELECT DISTINCT t.ItemID, t.Name, t.IsCollapsible, t.IsActive
|
||||
FROM Items t
|
||||
WHERE t.ItemBusinessID = :bizId
|
||||
AND t.ItemParentItemID = 0
|
||||
WHERE t.BusinessID = :bizId
|
||||
AND t.ParentItemID = 0
|
||||
AND t.ItemID NOT IN (
|
||||
SELECT i.ItemID FROM Items i WHERE i.ItemBusinessID = :bizId AND i.ItemCategoryID > 0
|
||||
SELECT i.ID FROM Items i WHERE i.BusinessID = :bizId AND i.CategoryID > 0
|
||||
)
|
||||
AND EXISTS (SELECT 1 FROM Items child WHERE child.ItemParentItemID = t.ItemID)
|
||||
ORDER BY t.ItemName
|
||||
AND EXISTS (SELECT 1 FROM Items child WHERE child.ParentItemID = t.ItemID)
|
||||
ORDER BY t.Name
|
||||
", { bizId: bizId }, { datasource: "payfrit" });
|
||||
|
||||
potentialTemplates = [];
|
||||
for (row in qMissingTemplates) {
|
||||
arrayAppend(potentialTemplates, {
|
||||
"ItemID": row.ItemID,
|
||||
"ItemName": row.ItemName,
|
||||
"IsCollapsible": row.ItemIsCollapsible,
|
||||
"IsActive": row.ItemIsActive
|
||||
"ItemID": row.ID,
|
||||
"Name": row.Name,
|
||||
"IsCollapsible": row.IsCollapsible,
|
||||
"IsActive": row.IsActive
|
||||
});
|
||||
}
|
||||
|
||||
// What templates SHOULD burgers have? Let's see all templates used by ANY item
|
||||
qAllTemplateUsage = queryExecute("
|
||||
SELECT t.ItemID, t.ItemName, COUNT(tl.ItemID) as UsageCount
|
||||
FROM ItemTemplateLinks tl
|
||||
SELECT t.ItemID, t.Name, COUNT(tl.ItemID) as UsageCount
|
||||
FROM lt_ItemID_TemplateItemID tl
|
||||
JOIN Items t ON t.ItemID = tl.TemplateItemID
|
||||
JOIN Items mi ON mi.ItemID = tl.ItemID AND mi.ItemBusinessID = :bizId
|
||||
GROUP BY t.ItemID, t.ItemName
|
||||
ORDER BY t.ItemName
|
||||
JOIN Items mi ON mi.ID = tl.ItemID AND mi.BusinessID = :bizId
|
||||
GROUP BY t.ItemID, t.Name
|
||||
ORDER BY t.Name
|
||||
", { bizId: bizId }, { datasource: "payfrit" });
|
||||
|
||||
allTemplates = [];
|
||||
for (row in qAllTemplateUsage) {
|
||||
arrayAppend(allTemplates, {
|
||||
"TemplateID": row.ItemID,
|
||||
"TemplateName": row.ItemName,
|
||||
"TemplateID": row.ID,
|
||||
"TemplateName": row.Name,
|
||||
"UsageCount": row.UsageCount
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,41 +7,41 @@ bizId = 27;
|
|||
|
||||
// Get the template items themselves
|
||||
qTemplates = queryExecute("
|
||||
SELECT ItemID, ItemName, ItemIsCollapsible, ItemIsActive, ItemParentItemID, ItemBusinessID
|
||||
SELECT ID, Name, IsCollapsible, IsActive, ParentItemID, BusinessID
|
||||
FROM Items
|
||||
WHERE ItemID IN (11267, 11251, 11246, 11224, 11233, 11230, 11240, 11243, 11237, 11227)
|
||||
ORDER BY ItemName
|
||||
WHERE ID IN (11267, 11251, 11246, 11224, 11233, 11230, 11240, 11243, 11237, 11227)
|
||||
ORDER BY Name
|
||||
", {}, { datasource: "payfrit" });
|
||||
|
||||
templates = [];
|
||||
for (row in qTemplates) {
|
||||
arrayAppend(templates, {
|
||||
"ItemID": row.ItemID,
|
||||
"ItemName": row.ItemName,
|
||||
"IsCollapsible": row.ItemIsCollapsible,
|
||||
"IsActive": row.ItemIsActive,
|
||||
"ParentID": row.ItemParentItemID,
|
||||
"BusinessID": row.ItemBusinessID
|
||||
"ItemID": row.ID,
|
||||
"Name": row.Name,
|
||||
"IsCollapsible": row.IsCollapsible,
|
||||
"IsActive": row.IsActive,
|
||||
"ParentID": row.ParentItemID,
|
||||
"BusinessID": row.BusinessID
|
||||
});
|
||||
}
|
||||
|
||||
// What templates are used by burgers vs all items?
|
||||
qBurgerLinks = queryExecute("
|
||||
SELECT mi.ItemID, mi.ItemName, GROUP_CONCAT(t.ItemName ORDER BY tl.SortOrder) as Templates
|
||||
SELECT mi.ID, mi.Name, GROUP_CONCAT(t.Name ORDER BY tl.SortOrder) as Templates
|
||||
FROM Items mi
|
||||
JOIN ItemTemplateLinks tl ON tl.ItemID = mi.ItemID
|
||||
JOIN lt_ItemID_TemplateItemID tl ON tl.ItemID = mi.ID
|
||||
JOIN Items t ON t.ItemID = tl.TemplateItemID
|
||||
WHERE mi.ItemBusinessID = :bizId
|
||||
AND mi.ItemParentItemID = 11271
|
||||
GROUP BY mi.ItemID, mi.ItemName
|
||||
ORDER BY mi.ItemName
|
||||
WHERE mi.BusinessID = :bizId
|
||||
AND mi.ParentItemID = 11271
|
||||
GROUP BY mi.ID, mi.Name
|
||||
ORDER BY mi.Name
|
||||
", { bizId: bizId }, { datasource: "payfrit" });
|
||||
|
||||
burgerLinks = [];
|
||||
for (row in qBurgerLinks) {
|
||||
arrayAppend(burgerLinks, {
|
||||
"ItemID": row.ItemID,
|
||||
"ItemName": row.ItemName,
|
||||
"ItemID": row.ID,
|
||||
"Name": row.Name,
|
||||
"Templates": row.Templates
|
||||
});
|
||||
}
|
||||
|
|
@ -49,20 +49,20 @@ for (row in qBurgerLinks) {
|
|||
// Also check: are there templates that SHOULD be linked to burgers?
|
||||
// (e.g., Add Cheese, etc.)
|
||||
qCheeseTemplate = queryExecute("
|
||||
SELECT ItemID, ItemName, ItemParentItemID, ItemIsActive
|
||||
SELECT ID, Name, ParentItemID, IsActive
|
||||
FROM Items
|
||||
WHERE ItemBusinessID = :bizId
|
||||
AND ItemName LIKE '%Cheese%'
|
||||
ORDER BY ItemName
|
||||
WHERE BusinessID = :bizId
|
||||
AND Name LIKE '%Cheese%'
|
||||
ORDER BY Name
|
||||
", { bizId: bizId }, { datasource: "payfrit" });
|
||||
|
||||
cheeseItems = [];
|
||||
for (row in qCheeseTemplate) {
|
||||
arrayAppend(cheeseItems, {
|
||||
"ItemID": row.ItemID,
|
||||
"ItemName": row.ItemName,
|
||||
"ParentID": row.ItemParentItemID,
|
||||
"IsActive": row.ItemIsActive
|
||||
"ItemID": row.ID,
|
||||
"Name": row.Name,
|
||||
"ParentID": row.ParentItemID,
|
||||
"IsActive": row.IsActive
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -26,36 +26,36 @@
|
|||
<cftry>
|
||||
<!--- Get raw employee records --- >
|
||||
<cfset qEmployees = queryExecute("
|
||||
SELECT e.*, b.BusinessName
|
||||
FROM lt_Users_Businesses_Employees e
|
||||
INNER JOIN Businesses b ON b.BusinessID = e.BusinessID
|
||||
SELECT e.*, b.Name
|
||||
FROM Employees e
|
||||
INNER JOIN Businesses b ON b.ID = e.BusinessID
|
||||
WHERE e.UserID = ?
|
||||
ORDER BY b.BusinessName ASC
|
||||
ORDER BY b.Name ASC
|
||||
", [ { value = UserID, cfsqltype = "cf_sql_integer" } ], { datasource = "payfrit" })>
|
||||
|
||||
<cfset employees = []>
|
||||
<cfloop query="qEmployees">
|
||||
<cfset arrayAppend(employees, {
|
||||
"EmployeeID": qEmployees.EmployeeID,
|
||||
"EmployeeID": qEmployees.ID,
|
||||
"UserID": qEmployees.UserID,
|
||||
"BusinessID": qEmployees.BusinessID,
|
||||
"BusinessName": qEmployees.BusinessName,
|
||||
"EmployeeIsActive": qEmployees.EmployeeIsActive
|
||||
"Name": qEmployees.Name,
|
||||
"IsActive": qEmployees.IsActive
|
||||
})>
|
||||
</cfloop>
|
||||
|
||||
<!--- Check for duplicate businesses --- >
|
||||
<cfset qDuplicates = queryExecute("
|
||||
SELECT BusinessName, COUNT(*) AS cnt
|
||||
SELECT Name, COUNT(*) AS cnt
|
||||
FROM Businesses
|
||||
GROUP BY BusinessName
|
||||
GROUP BY Name
|
||||
HAVING COUNT(*) > 1
|
||||
", [], { datasource = "payfrit" })>
|
||||
|
||||
<cfset duplicates = []>
|
||||
<cfloop query="qDuplicates">
|
||||
<cfset arrayAppend(duplicates, {
|
||||
"BusinessName": qDuplicates.BusinessName,
|
||||
"Name": qDuplicates.Name,
|
||||
"Count": qDuplicates.cnt
|
||||
})>
|
||||
</cfloop>
|
||||
|
|
|
|||
|
|
@ -10,11 +10,11 @@ try {
|
|||
messages = [];
|
||||
for (row in qAll) {
|
||||
arrayAppend(messages, {
|
||||
"MessageID": row.MessageID,
|
||||
"MessageID": row.ID,
|
||||
"TaskID": row.TaskID,
|
||||
"SenderUserID": row.SenderUserID,
|
||||
"SenderType": row.SenderType,
|
||||
"MessageText": left(row.MessageText, 100),
|
||||
"MessageBody": left(row.MessageBody, 100),
|
||||
"CreatedOn": row.CreatedOn
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,54 +10,54 @@ response = { "OK": true };
|
|||
try {
|
||||
// Get Fountain Drinks item
|
||||
qFountain = queryExecute("
|
||||
SELECT ItemID, ItemName, ItemParentItemID, ItemPrice, ItemIsCollapsible, ItemRequiresChildSelection
|
||||
SELECT ID, Name, ParentItemID, Price, IsCollapsible, RequiresChildSelection
|
||||
FROM Items
|
||||
WHERE ItemBusinessID = 17 AND ItemName LIKE '%Fountain%'
|
||||
WHERE BusinessID = 17 AND Name LIKE '%Fountain%'
|
||||
", {}, { datasource: "payfrit" });
|
||||
|
||||
response["FountainDrinks"] = [];
|
||||
for (row in qFountain) {
|
||||
fountainItem = {
|
||||
"ItemID": row.ItemID,
|
||||
"ItemName": row.ItemName,
|
||||
"ItemPrice": row.ItemPrice,
|
||||
"ItemIsCollapsible": row.ItemIsCollapsible,
|
||||
"ItemRequiresChildSelection": row.ItemRequiresChildSelection,
|
||||
"ItemID": row.ID,
|
||||
"Name": row.Name,
|
||||
"Price": row.Price,
|
||||
"IsCollapsible": row.IsCollapsible,
|
||||
"RequiresChildSelection": row.RequiresChildSelection,
|
||||
"Children": []
|
||||
};
|
||||
|
||||
// Get children of this item
|
||||
qChildren = queryExecute("
|
||||
SELECT ItemID, ItemName, ItemParentItemID, ItemPrice, ItemIsCollapsible, ItemRequiresChildSelection, ItemIsCheckedByDefault
|
||||
SELECT ID, Name, ParentItemID, Price, IsCollapsible, RequiresChildSelection, IsCheckedByDefault
|
||||
FROM Items
|
||||
WHERE ItemParentItemID = :parentId
|
||||
ORDER BY ItemSortOrder
|
||||
", { parentId: row.ItemID }, { datasource: "payfrit" });
|
||||
WHERE ParentItemID = :parentId
|
||||
ORDER BY SortOrder
|
||||
", { parentId: row.ID }, { datasource: "payfrit" });
|
||||
|
||||
for (child in qChildren) {
|
||||
childItem = {
|
||||
"ItemID": child.ItemID,
|
||||
"ItemName": child.ItemName,
|
||||
"ItemPrice": child.ItemPrice,
|
||||
"ItemIsCollapsible": child.ItemIsCollapsible,
|
||||
"ItemIsCheckedByDefault": child.ItemIsCheckedByDefault,
|
||||
"Name": child.Name,
|
||||
"Price": child.Price,
|
||||
"IsCollapsible": child.IsCollapsible,
|
||||
"IsCheckedByDefault": child.IsCheckedByDefault,
|
||||
"Grandchildren": []
|
||||
};
|
||||
|
||||
// Get grandchildren
|
||||
qGrandchildren = queryExecute("
|
||||
SELECT ItemID, ItemName, ItemPrice, ItemIsCheckedByDefault
|
||||
SELECT ID, Name, Price, IsCheckedByDefault
|
||||
FROM Items
|
||||
WHERE ItemParentItemID = :parentId
|
||||
ORDER BY ItemSortOrder
|
||||
WHERE ParentItemID = :parentId
|
||||
ORDER BY SortOrder
|
||||
", { parentId: child.ItemID }, { datasource: "payfrit" });
|
||||
|
||||
for (gc in qGrandchildren) {
|
||||
arrayAppend(childItem.Grandchildren, {
|
||||
"ItemID": gc.ItemID,
|
||||
"ItemName": gc.ItemName,
|
||||
"ItemPrice": gc.ItemPrice,
|
||||
"ItemIsCheckedByDefault": gc.ItemIsCheckedByDefault
|
||||
"Name": gc.Name,
|
||||
"Price": gc.Price,
|
||||
"IsCheckedByDefault": gc.IsCheckedByDefault
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,10 +14,10 @@ if (structKeyExists(data, "Phone") && len(data.Phone)) {
|
|||
phone = reReplace(data.Phone, "[^0-9]", "", "all");
|
||||
|
||||
qUser = queryExecute("
|
||||
SELECT UserID, UserFirstName, UserLastName, UserEmailAddress, UserContactNumber
|
||||
SELECT ID, FirstName, LastName, EmailAddress, ContactNumber
|
||||
FROM Users
|
||||
WHERE REPLACE(REPLACE(REPLACE(UserContactNumber, '-', ''), '(', ''), ')', '') LIKE ?
|
||||
OR UserContactNumber LIKE ?
|
||||
WHERE REPLACE(REPLACE(REPLACE(ContactNumber, '-', ''), '(', ''), ')', '') LIKE ?
|
||||
OR ContactNumber LIKE ?
|
||||
", [
|
||||
{ value: "%" & phone & "%", cfsqltype: "cf_sql_varchar" },
|
||||
{ value: "%" & phone & "%", cfsqltype: "cf_sql_varchar" }
|
||||
|
|
@ -28,35 +28,35 @@ if (structKeyExists(data, "Phone") && len(data.Phone)) {
|
|||
abort;
|
||||
}
|
||||
|
||||
userId = qUser.UserID;
|
||||
userId = qUser.ID;
|
||||
|
||||
qEmployees = queryExecute("
|
||||
SELECT e.EmployeeID, e.BusinessID, e.EmployeeStatusID,
|
||||
CAST(e.EmployeeIsActive AS UNSIGNED) AS EmployeeIsActive,
|
||||
b.BusinessName
|
||||
FROM lt_Users_Businesses_Employees e
|
||||
JOIN Businesses b ON e.BusinessID = b.BusinessID
|
||||
SELECT e.ID, e.BusinessID, e.StatusID,
|
||||
CAST(e.IsActive AS UNSIGNED) AS IsActive,
|
||||
b.Name
|
||||
FROM Employees e
|
||||
JOIN Businesses b ON e.BusinessID = b.ID
|
||||
WHERE e.UserID = ?
|
||||
", [{ value: userId, cfsqltype: "cf_sql_integer" }], { datasource: "payfrit" });
|
||||
|
||||
employees = [];
|
||||
for (row in qEmployees) {
|
||||
arrayAppend(employees, {
|
||||
"EmployeeID": row.EmployeeID,
|
||||
"EmployeeID": row.ID,
|
||||
"BusinessID": row.BusinessID,
|
||||
"BusinessName": row.BusinessName,
|
||||
"StatusID": row.EmployeeStatusID,
|
||||
"IsActive": row.EmployeeIsActive
|
||||
"Name": row.Name,
|
||||
"StatusID": row.StatusID,
|
||||
"IsActive": row.IsActive
|
||||
});
|
||||
}
|
||||
|
||||
writeOutput(serializeJSON({
|
||||
"OK": true,
|
||||
"USER": {
|
||||
"UserID": qUser.UserID,
|
||||
"Name": trim(qUser.UserFirstName & " " & qUser.UserLastName),
|
||||
"Email": qUser.UserEmailAddress,
|
||||
"Phone": qUser.UserContactNumber
|
||||
"UserID": qUser.ID,
|
||||
"Name": trim(qUser.FirstName & " " & qUser.LastName),
|
||||
"Email": qUser.EmailAddress,
|
||||
"Phone": qUser.ContactNumber
|
||||
},
|
||||
"EMPLOYEES": employees
|
||||
}));
|
||||
|
|
@ -67,23 +67,23 @@ if (structKeyExists(data, "Phone") && len(data.Phone)) {
|
|||
businessId = structKeyExists(data, "BusinessID") ? val(data.BusinessID) : 17;
|
||||
|
||||
q = queryExecute("
|
||||
SELECT EmployeeID, UserID, EmployeeStatusID, EmployeeIsActive,
|
||||
CAST(EmployeeIsActive AS UNSIGNED) AS IsActiveInt
|
||||
FROM lt_Users_Businesses_Employees
|
||||
SELECT ID, UserID, StatusID, IsActive,
|
||||
CAST(IsActive AS UNSIGNED) AS IsActiveInt
|
||||
FROM Employees
|
||||
WHERE BusinessID = ?
|
||||
", [{ value: businessId, cfsqltype: "cf_sql_integer" }], { datasource: "payfrit" });
|
||||
|
||||
rows = [];
|
||||
for (r in q) {
|
||||
arrayAppend(rows, {
|
||||
"EmployeeID": r.EmployeeID,
|
||||
"EmployeeID": r.ID,
|
||||
"UserID": r.UserID,
|
||||
"StatusID": r.EmployeeStatusID,
|
||||
"RawIsActive": r.EmployeeIsActive,
|
||||
"StatusID": r.StatusID,
|
||||
"RawIsActive": r.IsActive,
|
||||
"CastIsActive": r.IsActiveInt,
|
||||
"ValRaw": val(r.EmployeeIsActive),
|
||||
"ValRaw": val(r.IsActive),
|
||||
"ValCast": val(r.IsActiveInt),
|
||||
"EqRaw1": r.EmployeeIsActive == 1,
|
||||
"EqRaw1": r.IsActive == 1,
|
||||
"EqCast1": r.IsActiveInt == 1
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,8 +13,8 @@ try {
|
|||
// Close all open chats action
|
||||
if (structKeyExists(data, "action") && data.action == "closeAllChats") {
|
||||
queryExecute("
|
||||
UPDATE Tasks SET TaskCompletedOn = NOW()
|
||||
WHERE TaskTypeID = 2 AND TaskCompletedOn IS NULL
|
||||
UPDATE Tasks SET CompletedOn = NOW()
|
||||
WHERE TaskTypeID = 2 AND CompletedOn IS NULL
|
||||
", {}, { datasource: "payfrit" });
|
||||
writeOutput(serializeJSON({ "OK": true, "MESSAGE": "All open chats closed" }));
|
||||
abort;
|
||||
|
|
@ -24,38 +24,38 @@ if (structKeyExists(data, "action") && data.action == "closeAllChats") {
|
|||
<cftry>
|
||||
<cfset qTasks = queryExecute("
|
||||
SELECT
|
||||
t.TaskID,
|
||||
t.TaskBusinessID,
|
||||
t.TaskOrderID,
|
||||
t.TaskClaimedByUserID,
|
||||
t.TaskClaimedOn,
|
||||
t.TaskCompletedOn,
|
||||
o.OrderStatusID
|
||||
t.ID,
|
||||
t.BusinessID,
|
||||
t.OrderID,
|
||||
t.ClaimedByUserID,
|
||||
t.ClaimedOn,
|
||||
t.CompletedOn,
|
||||
o.StatusID
|
||||
FROM Tasks t
|
||||
LEFT JOIN Orders o ON o.OrderID = t.TaskOrderID
|
||||
ORDER BY t.TaskID DESC
|
||||
LEFT JOIN Orders o ON o.ID = t.OrderID
|
||||
ORDER BY t.ID DESC
|
||||
LIMIT 20
|
||||
", [], { datasource = "payfrit" })>
|
||||
|
||||
<cfset tasks = []>
|
||||
<cfloop query="qTasks">
|
||||
<cfset arrayAppend(tasks, {
|
||||
"TaskID": qTasks.TaskID,
|
||||
"TaskBusinessID": qTasks.TaskBusinessID,
|
||||
"TaskOrderID": qTasks.TaskOrderID,
|
||||
"TaskClaimedByUserID": qTasks.TaskClaimedByUserID,
|
||||
"TaskClaimedOn": isNull(qTasks.TaskClaimedOn) ? "NULL" : dateTimeFormat(qTasks.TaskClaimedOn, "yyyy-mm-dd HH:nn:ss"),
|
||||
"TaskCompletedOn": isNull(qTasks.TaskCompletedOn) ? "NULL" : dateTimeFormat(qTasks.TaskCompletedOn, "yyyy-mm-dd HH:nn:ss"),
|
||||
"OrderStatusID": isNull(qTasks.OrderStatusID) ? "NULL" : qTasks.OrderStatusID
|
||||
"TaskID": qTasks.ID,
|
||||
"BusinessID": qTasks.BusinessID,
|
||||
"OrderID": qTasks.OrderID,
|
||||
"ClaimedByUserID": qTasks.ClaimedByUserID,
|
||||
"ClaimedOn": isNull(qTasks.ClaimedOn) ? "NULL" : dateTimeFormat(qTasks.ClaimedOn, "yyyy-mm-dd HH:nn:ss"),
|
||||
"CompletedOn": isNull(qTasks.CompletedOn) ? "NULL" : dateTimeFormat(qTasks.CompletedOn, "yyyy-mm-dd HH:nn:ss"),
|
||||
"StatusID": isNull(qTasks.StatusID) ? "NULL" : qTasks.StatusID
|
||||
})>
|
||||
</cfloop>
|
||||
|
||||
<cfset qStats = queryExecute("
|
||||
SELECT
|
||||
COUNT(*) as Total,
|
||||
SUM(CASE WHEN TaskClaimedByUserID > 0 AND TaskCompletedOn IS NULL THEN 1 ELSE 0 END) as ClaimedNotCompleted,
|
||||
SUM(CASE WHEN TaskClaimedByUserID = 0 OR TaskClaimedByUserID IS NULL THEN 1 ELSE 0 END) as Unclaimed,
|
||||
SUM(CASE WHEN TaskCompletedOn IS NOT NULL THEN 1 ELSE 0 END) as Completed
|
||||
SUM(CASE WHEN ClaimedByUserID > 0 AND CompletedOn IS NULL THEN 1 ELSE 0 END) as ClaimedNotCompleted,
|
||||
SUM(CASE WHEN ClaimedByUserID = 0 OR ClaimedByUserID IS NULL THEN 1 ELSE 0 END) as Unclaimed,
|
||||
SUM(CASE WHEN CompletedOn IS NOT NULL THEN 1 ELSE 0 END) as Completed
|
||||
FROM Tasks
|
||||
", [], { datasource = "payfrit" })>
|
||||
|
||||
|
|
|
|||
|
|
@ -4,19 +4,19 @@
|
|||
|
||||
<cftry>
|
||||
<cfset qAll = queryExecute("
|
||||
SELECT TaskID, TaskClaimedByUserID, TaskCompletedOn, TaskOrderID,
|
||||
CASE WHEN TaskCompletedOn IS NULL THEN 'YES_NULL' ELSE 'NOT_NULL' END AS IsNull
|
||||
SELECT ID, ClaimedByUserID, CompletedOn, OrderID,
|
||||
CASE WHEN CompletedOn IS NULL THEN 'YES_NULL' ELSE 'NOT_NULL' END AS IsNull
|
||||
FROM Tasks
|
||||
ORDER BY TaskID DESC
|
||||
ORDER BY ID DESC
|
||||
", [], { datasource = "payfrit" })>
|
||||
|
||||
<cfset tasks = []>
|
||||
<cfloop query="qAll">
|
||||
<cfset arrayAppend(tasks, {
|
||||
"TaskID": qAll.TaskID,
|
||||
"TaskClaimedByUserID": qAll.TaskClaimedByUserID,
|
||||
"TaskOrderID": qAll.TaskOrderID,
|
||||
"TaskCompletedOn": len(trim(qAll.TaskCompletedOn)) ? toString(qAll.TaskCompletedOn) : "",
|
||||
"TaskID": qAll.ID,
|
||||
"ClaimedByUserID": qAll.ClaimedByUserID,
|
||||
"OrderID": qAll.OrderID,
|
||||
"CompletedOn": len(trim(qAll.CompletedOn)) ? toString(qAll.CompletedOn) : "",
|
||||
"IsNull": qAll.IsNull
|
||||
})>
|
||||
</cfloop>
|
||||
|
|
|
|||
|
|
@ -3,39 +3,39 @@
|
|||
<cfcontent type="application/json; charset=utf-8" reset="true">
|
||||
|
||||
<cfscript>
|
||||
// Check ItemTemplateLinks for Big Dean's (BusinessID 27)
|
||||
// Check lt_ItemID_TemplateItemID for Big Dean's (BusinessID 27)
|
||||
bizId = 27;
|
||||
|
||||
// Count total links
|
||||
qCount = queryExecute("SELECT COUNT(*) as cnt FROM ItemTemplateLinks", {}, { datasource: "payfrit" });
|
||||
qCount = queryExecute("SELECT COUNT(*) as cnt FROM lt_ItemID_TemplateItemID", {}, { datasource: "payfrit" });
|
||||
|
||||
// Get template item IDs for this business
|
||||
qTemplates = queryExecute("
|
||||
SELECT DISTINCT tl.TemplateItemID, i.ItemName
|
||||
FROM ItemTemplateLinks tl
|
||||
JOIN Items i ON i.ItemID = tl.TemplateItemID
|
||||
WHERE i.ItemBusinessID = :bizId
|
||||
SELECT DISTINCT tl.TemplateItemID, i.Name
|
||||
FROM lt_ItemID_TemplateItemID tl
|
||||
JOIN Items i ON i.ID = tl.TemplateItemID
|
||||
WHERE i.BusinessID = :bizId
|
||||
", { bizId: bizId }, { datasource: "payfrit" });
|
||||
|
||||
templates = [];
|
||||
for (row in qTemplates) {
|
||||
arrayAppend(templates, { "TemplateItemID": row.TemplateItemID, "ItemName": row.ItemName });
|
||||
arrayAppend(templates, { "TemplateItemID": row.TemplateItemID, "Name": row.Name });
|
||||
}
|
||||
|
||||
// Get items that should be categories (ParentItemID=0, not templates)
|
||||
qCategories = queryExecute("
|
||||
SELECT i.ItemID, i.ItemName, i.ItemParentItemID, i.ItemIsCollapsible
|
||||
SELECT i.ID, i.Name, i.ParentItemID, i.IsCollapsible
|
||||
FROM Items i
|
||||
WHERE i.ItemBusinessID = :bizId
|
||||
AND i.ItemParentItemID = 0
|
||||
AND i.ItemIsCollapsible = 0
|
||||
AND NOT EXISTS (SELECT 1 FROM ItemTemplateLinks tl WHERE tl.TemplateItemID = i.ItemID)
|
||||
ORDER BY i.ItemSortOrder
|
||||
WHERE i.BusinessID = :bizId
|
||||
AND i.ParentItemID = 0
|
||||
AND i.IsCollapsible = 0
|
||||
AND NOT EXISTS (SELECT 1 FROM lt_ItemID_TemplateItemID tl WHERE tl.TemplateItemID = i.ID)
|
||||
ORDER BY i.SortOrder
|
||||
", { bizId: bizId }, { datasource: "payfrit" });
|
||||
|
||||
categories = [];
|
||||
for (row in qCategories) {
|
||||
arrayAppend(categories, { "ItemID": row.ItemID, "ItemName": row.ItemName });
|
||||
arrayAppend(categories, { "ItemID": row.ID, "Name": row.Name });
|
||||
}
|
||||
|
||||
writeOutput(serializeJSON({
|
||||
|
|
|
|||
|
|
@ -20,10 +20,10 @@ if (len(phone) == 0) {
|
|||
|
||||
// Find user by phone
|
||||
qUser = queryExecute("
|
||||
SELECT UserID, UserFirstName, UserLastName, UserEmailAddress, UserContactNumber
|
||||
SELECT ID, FirstName, LastName, EmailAddress, ContactNumber
|
||||
FROM Users
|
||||
WHERE REPLACE(REPLACE(REPLACE(UserContactNumber, '-', ''), '(', ''), ')', '') LIKE ?
|
||||
OR UserContactNumber LIKE ?
|
||||
WHERE REPLACE(REPLACE(REPLACE(ContactNumber, '-', ''), '(', ''), ')', '') LIKE ?
|
||||
OR ContactNumber LIKE ?
|
||||
", [
|
||||
{ value: "%" & phone & "%", cfsqltype: "cf_sql_varchar" },
|
||||
{ value: "%" & phone & "%", cfsqltype: "cf_sql_varchar" }
|
||||
|
|
@ -34,36 +34,36 @@ if (qUser.recordCount == 0) {
|
|||
abort;
|
||||
}
|
||||
|
||||
userId = qUser.UserID;
|
||||
userId = qUser.ID;
|
||||
|
||||
// Get all employee records for this user
|
||||
qEmployees = queryExecute("
|
||||
SELECT e.EmployeeID, e.BusinessID, e.EmployeeStatusID,
|
||||
CAST(e.EmployeeIsActive AS UNSIGNED) AS EmployeeIsActive,
|
||||
b.BusinessName
|
||||
FROM lt_Users_Businesses_Employees e
|
||||
JOIN Businesses b ON e.BusinessID = b.BusinessID
|
||||
SELECT e.ID, e.BusinessID, e.StatusID,
|
||||
CAST(e.IsActive AS UNSIGNED) AS IsActive,
|
||||
b.Name
|
||||
FROM Employees e
|
||||
JOIN Businesses b ON e.BusinessID = b.ID
|
||||
WHERE e.UserID = ?
|
||||
", [{ value: userId, cfsqltype: "cf_sql_integer" }], { datasource: "payfrit" });
|
||||
|
||||
employees = [];
|
||||
for (row in qEmployees) {
|
||||
arrayAppend(employees, {
|
||||
"EmployeeID": row.EmployeeID,
|
||||
"EmployeeID": row.ID,
|
||||
"BusinessID": row.BusinessID,
|
||||
"BusinessName": row.BusinessName,
|
||||
"StatusID": row.EmployeeStatusID,
|
||||
"IsActive": row.EmployeeIsActive
|
||||
"Name": row.Name,
|
||||
"StatusID": row.StatusID,
|
||||
"IsActive": row.IsActive
|
||||
});
|
||||
}
|
||||
|
||||
writeOutput(serializeJSON({
|
||||
"OK": true,
|
||||
"USER": {
|
||||
"UserID": qUser.UserID,
|
||||
"Name": trim(qUser.UserFirstName & " " & qUser.UserLastName),
|
||||
"Email": qUser.UserEmailAddress,
|
||||
"Phone": qUser.UserContactNumber
|
||||
"UserID": qUser.ID,
|
||||
"Name": trim(qUser.FirstName & " " & qUser.LastName),
|
||||
"Email": qUser.EmailAddress,
|
||||
"Phone": qUser.ContactNumber
|
||||
},
|
||||
"EMPLOYEES": employees
|
||||
}));
|
||||
|
|
|
|||
|
|
@ -28,19 +28,19 @@ try {
|
|||
response["ERROR"] = "BusinessID required";
|
||||
} else {
|
||||
// Get address ID first
|
||||
qBiz = queryExecute("SELECT BusinessAddressID FROM Businesses WHERE BusinessID = :id", { id: bizID }, { datasource = "payfrit" });
|
||||
qBiz = queryExecute("SELECT AddressID FROM Businesses WHERE ID = :id", { id: bizID }, { datasource = "payfrit" });
|
||||
|
||||
if (qBiz.recordCount == 0) {
|
||||
response["ERROR"] = "Business not found";
|
||||
} else {
|
||||
addrID = qBiz.BusinessAddressID;
|
||||
addrID = qBiz.AddressID;
|
||||
|
||||
// Delete business
|
||||
queryExecute("DELETE FROM Businesses WHERE BusinessID = :id", { id: bizID }, { datasource = "payfrit" });
|
||||
queryExecute("DELETE FROM Businesses WHERE ID = :id", { id: bizID }, { datasource = "payfrit" });
|
||||
|
||||
// Delete address if exists
|
||||
if (val(addrID) > 0) {
|
||||
queryExecute("DELETE FROM Addresses WHERE AddressID = :id", { id: addrID }, { datasource = "payfrit" });
|
||||
queryExecute("DELETE FROM Addresses WHERE ID = :id", { id: addrID }, { datasource = "payfrit" });
|
||||
}
|
||||
|
||||
response["OK"] = true;
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
* Delete Orphan Modifiers for In and Out Burger (BusinessID=17)
|
||||
*
|
||||
* This script deletes duplicate modifier items that are no longer needed
|
||||
* because we now use ItemTemplateLinks.
|
||||
* because we now use lt_ItemID_TemplateItemID.
|
||||
*
|
||||
* The orphan items are level-1 modifiers (direct children of parent items)
|
||||
* that have been replaced by template links.
|
||||
|
|
@ -29,18 +29,18 @@ try {
|
|||
qOrphans = queryExecute("
|
||||
SELECT
|
||||
m.ItemID,
|
||||
m.ItemName,
|
||||
m.ItemParentItemID,
|
||||
p.ItemName as ParentName
|
||||
m.Name,
|
||||
m.ParentItemID,
|
||||
p.Name as ParentName
|
||||
FROM Items m
|
||||
INNER JOIN Items p ON p.ItemID = m.ItemParentItemID
|
||||
INNER JOIN Categories c ON c.CategoryID = p.ItemCategoryID
|
||||
WHERE c.CategoryBusinessID = :businessID
|
||||
AND m.ItemParentItemID > 0
|
||||
AND p.ItemParentItemID = 0
|
||||
AND (m.ItemIsModifierTemplate IS NULL OR m.ItemIsModifierTemplate = 0)
|
||||
AND m.ItemIsActive = 1
|
||||
ORDER BY m.ItemName
|
||||
INNER JOIN Items p ON p.ItemID = m.ParentItemID
|
||||
INNER JOIN Categories c ON c.ID = p.CategoryID
|
||||
WHERE c.BusinessID = :businessID
|
||||
AND m.ParentItemID > 0
|
||||
AND p.ParentItemID = 0
|
||||
AND (m.IsModifierTemplate IS NULL OR m.IsModifierTemplate = 0)
|
||||
AND m.IsActive = 1
|
||||
ORDER BY m.Name
|
||||
", { businessID: businessID }, { datasource: "payfrit" });
|
||||
|
||||
arrayAppend(response.deleted, "Found " & qOrphans.recordCount & " orphan modifiers to delete");
|
||||
|
|
@ -50,23 +50,23 @@ try {
|
|||
try {
|
||||
// Delete children of this orphan (options within the modifier group)
|
||||
qDeleteChildren = queryExecute("
|
||||
DELETE FROM Items WHERE ItemParentItemID = :orphanID
|
||||
DELETE FROM Items WHERE ParentItemID = :orphanID
|
||||
", { orphanID: orphan.ItemID }, { datasource: "payfrit" });
|
||||
|
||||
// Delete the orphan itself
|
||||
qDeleteOrphan = queryExecute("
|
||||
DELETE FROM Items WHERE ItemID = :orphanID
|
||||
DELETE FROM Items WHERE ID = :orphanID
|
||||
", { orphanID: orphan.ItemID }, { datasource: "payfrit" });
|
||||
|
||||
arrayAppend(response.deleted, {
|
||||
"ItemID": orphan.ItemID,
|
||||
"ItemName": orphan.ItemName,
|
||||
"Name": orphan.Name,
|
||||
"WasUnder": orphan.ParentName
|
||||
});
|
||||
} catch (any deleteErr) {
|
||||
arrayAppend(response.errors, {
|
||||
"ItemID": orphan.ItemID,
|
||||
"ItemName": orphan.ItemName,
|
||||
"Name": orphan.Name,
|
||||
"Error": deleteErr.message
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
<cfscript>
|
||||
/**
|
||||
* Delete orphan Items at ParentID=0
|
||||
* Orphan = ParentID=0, no children, not in ItemTemplateLinks
|
||||
* Orphan = ParentID=0, no children, not in lt_ItemID_TemplateItemID
|
||||
*/
|
||||
|
||||
response = { "OK": false, "deleted": 0, "orphans": [] };
|
||||
|
|
@ -19,24 +19,24 @@ response = { "OK": false, "deleted": 0, "orphans": [] };
|
|||
try {
|
||||
// Find orphans
|
||||
qOrphans = queryExecute("
|
||||
SELECT i.ItemID, i.ItemName, i.ItemBusinessID
|
||||
SELECT i.ID, i.Name, i.BusinessID
|
||||
FROM Items i
|
||||
WHERE i.ItemParentItemID = 0
|
||||
WHERE i.ParentItemID = 0
|
||||
AND NOT EXISTS (
|
||||
SELECT 1 FROM Items child WHERE child.ItemParentItemID = i.ItemID
|
||||
SELECT 1 FROM Items child WHERE child.ParentItemID = i.ID
|
||||
)
|
||||
AND NOT EXISTS (
|
||||
SELECT 1 FROM ItemTemplateLinks tl WHERE tl.TemplateItemID = i.ItemID
|
||||
SELECT 1 FROM lt_ItemID_TemplateItemID tl WHERE tl.TemplateItemID = i.ID
|
||||
)
|
||||
ORDER BY i.ItemBusinessID, i.ItemName
|
||||
ORDER BY i.BusinessID, i.Name
|
||||
", {}, { datasource: "payfrit" });
|
||||
|
||||
orphanIDs = [];
|
||||
for (orphan in qOrphans) {
|
||||
arrayAppend(response.orphans, {
|
||||
"ItemID": orphan.ItemID,
|
||||
"ItemName": orphan.ItemName,
|
||||
"BusinessID": orphan.ItemBusinessID
|
||||
"Name": orphan.Name,
|
||||
"BusinessID": orphan.BusinessID
|
||||
});
|
||||
arrayAppend(orphanIDs, orphan.ItemID);
|
||||
}
|
||||
|
|
@ -44,7 +44,7 @@ try {
|
|||
// Delete them by ID list
|
||||
if (arrayLen(orphanIDs) > 0) {
|
||||
queryExecute("
|
||||
DELETE FROM Items WHERE ItemID IN (#arrayToList(orphanIDs)#)
|
||||
DELETE FROM Items WHERE ID IN (#arrayToList(orphanIDs)#)
|
||||
", {}, { datasource: "payfrit" });
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,16 +14,16 @@
|
|||
* Eliminate Categories Table - Schema Migration
|
||||
*
|
||||
* Final unified schema:
|
||||
* - Everything is an Item with ItemBusinessID
|
||||
* - Everything is an Item with BusinessID
|
||||
* - ParentID=0 items are either categories or templates (derived from usage)
|
||||
* - Categories = items at ParentID=0 that have menu items as children
|
||||
* - Templates = items at ParentID=0 that appear in ItemTemplateLinks
|
||||
* - Templates = items at ParentID=0 that appear in lt_ItemID_TemplateItemID
|
||||
* - Orphans = ParentID=0 items that are neither (cleanup candidates)
|
||||
*
|
||||
* Steps:
|
||||
* 1. Add ItemBusinessID column to Items
|
||||
* 1. Add BusinessID column to Items
|
||||
* 2. For each Category: create Item, re-parent menu items, set BusinessID
|
||||
* 3. Set ItemBusinessID on templates based on linked items
|
||||
* 3. Set BusinessID on templates based on linked items
|
||||
*
|
||||
* Query param: ?dryRun=1 to preview without making changes
|
||||
*/
|
||||
|
|
@ -34,30 +34,30 @@ try {
|
|||
dryRun = structKeyExists(url, "dryRun") && url.dryRun == 1;
|
||||
response["dryRun"] = dryRun;
|
||||
|
||||
// Step 1: Add ItemBusinessID column if it doesn't exist
|
||||
// Step 1: Add BusinessID column if it doesn't exist
|
||||
try {
|
||||
if (!dryRun) {
|
||||
queryExecute("
|
||||
ALTER TABLE Items ADD COLUMN ItemBusinessID INT DEFAULT 0 AFTER ItemID
|
||||
ALTER TABLE Items ADD COLUMN BusinessID INT DEFAULT 0 AFTER ItemID
|
||||
", {}, { datasource: "payfrit" });
|
||||
}
|
||||
arrayAppend(response.steps, "Added ItemBusinessID column to Items table");
|
||||
arrayAppend(response.steps, "Added BusinessID column to Items table");
|
||||
} catch (any e) {
|
||||
if (findNoCase("Duplicate column", e.message)) {
|
||||
arrayAppend(response.steps, "ItemBusinessID column already exists");
|
||||
arrayAppend(response.steps, "BusinessID column already exists");
|
||||
} else {
|
||||
throw(e);
|
||||
}
|
||||
}
|
||||
|
||||
// Step 2: Add index on ItemBusinessID
|
||||
// Step 2: Add index on BusinessID
|
||||
try {
|
||||
if (!dryRun) {
|
||||
queryExecute("
|
||||
CREATE INDEX idx_item_business ON Items (ItemBusinessID)
|
||||
CREATE INDEX idx_item_business ON Items (BusinessID)
|
||||
", {}, { datasource: "payfrit" });
|
||||
}
|
||||
arrayAppend(response.steps, "Added index on ItemBusinessID");
|
||||
arrayAppend(response.steps, "Added index on BusinessID");
|
||||
} catch (any e) {
|
||||
if (findNoCase("Duplicate key name", e.message)) {
|
||||
arrayAppend(response.steps, "Index idx_item_business already exists");
|
||||
|
|
@ -66,7 +66,7 @@ try {
|
|||
}
|
||||
}
|
||||
|
||||
// Step 3: Drop foreign key constraint on ItemCategoryID if it exists
|
||||
// Step 3: Drop foreign key constraint on CategoryID if it exists
|
||||
try {
|
||||
if (!dryRun) {
|
||||
queryExecute("
|
||||
|
|
@ -84,9 +84,9 @@ try {
|
|||
|
||||
// Step 4: Get all Categories
|
||||
qCategories = queryExecute("
|
||||
SELECT CategoryID, CategoryBusinessID, CategoryName
|
||||
SELECT ID, BusinessID, Name
|
||||
FROM Categories
|
||||
ORDER BY CategoryBusinessID, CategoryName
|
||||
ORDER BY BusinessID, Name
|
||||
", {}, { datasource: "payfrit" });
|
||||
|
||||
arrayAppend(response.steps, "Found " & qCategories.recordCount & " categories to migrate");
|
||||
|
|
@ -94,29 +94,29 @@ try {
|
|||
// Step 4: Migrate each category
|
||||
for (cat in qCategories) {
|
||||
migration = {
|
||||
"oldCategoryID": cat.CategoryID,
|
||||
"categoryName": cat.CategoryName,
|
||||
"businessID": cat.CategoryBusinessID,
|
||||
"oldCategoryID": cat.ID,
|
||||
"categoryName": cat.Name,
|
||||
"businessID": cat.BusinessID,
|
||||
"newItemID": 0,
|
||||
"itemsUpdated": 0
|
||||
};
|
||||
|
||||
if (!dryRun) {
|
||||
// Create new Item for this category (ParentID=0, no template flag needed)
|
||||
// Note: ItemCategoryID set to 0 temporarily until we drop that column
|
||||
// Note: CategoryID set to 0 temporarily until we drop that column
|
||||
queryExecute("
|
||||
INSERT INTO Items (
|
||||
ItemBusinessID,
|
||||
ItemCategoryID,
|
||||
ItemName,
|
||||
ItemDescription,
|
||||
ItemParentItemID,
|
||||
ItemPrice,
|
||||
ItemIsActive,
|
||||
ItemIsCheckedByDefault,
|
||||
ItemRequiresChildSelection,
|
||||
ItemSortOrder,
|
||||
ItemAddedOn
|
||||
BusinessID,
|
||||
CategoryID,
|
||||
Name,
|
||||
Description,
|
||||
ParentItemID,
|
||||
Price,
|
||||
IsActive,
|
||||
IsCheckedByDefault,
|
||||
RequiresChildSelection,
|
||||
SortOrder,
|
||||
AddedOn
|
||||
) VALUES (
|
||||
:businessID,
|
||||
0,
|
||||
|
|
@ -131,56 +131,56 @@ try {
|
|||
NOW()
|
||||
)
|
||||
", {
|
||||
businessID: cat.CategoryBusinessID,
|
||||
categoryName: cat.CategoryName
|
||||
businessID: cat.BusinessID,
|
||||
categoryName: cat.Name
|
||||
}, { datasource: "payfrit" });
|
||||
|
||||
// Get the new Item ID
|
||||
qNewItem = queryExecute("
|
||||
SELECT ItemID FROM Items
|
||||
WHERE ItemBusinessID = :businessID
|
||||
AND ItemName = :categoryName
|
||||
AND ItemParentItemID = 0
|
||||
ORDER BY ItemID DESC
|
||||
SELECT ID FROM Items
|
||||
WHERE BusinessID = :businessID
|
||||
AND Name = :categoryName
|
||||
AND ParentItemID = 0
|
||||
ORDER BY ID DESC
|
||||
LIMIT 1
|
||||
", {
|
||||
businessID: cat.CategoryBusinessID,
|
||||
categoryName: cat.CategoryName
|
||||
businessID: cat.BusinessID,
|
||||
categoryName: cat.Name
|
||||
}, { datasource: "payfrit" });
|
||||
|
||||
newItemID = qNewItem.ItemID;
|
||||
newItemID = qNewItem.ID;
|
||||
migration["newItemID"] = newItemID;
|
||||
|
||||
// Update menu items in this category:
|
||||
// - Set ItemParentItemID = newItemID (for top-level items only)
|
||||
// - Set ItemBusinessID = businessID (for all items)
|
||||
// - Set ParentItemID = newItemID (for top-level items only)
|
||||
// - Set BusinessID = businessID (for all items)
|
||||
queryExecute("
|
||||
UPDATE Items
|
||||
SET ItemBusinessID = :businessID,
|
||||
ItemParentItemID = :newItemID
|
||||
WHERE ItemCategoryID = :categoryID
|
||||
AND ItemParentItemID = 0
|
||||
SET BusinessID = :businessID,
|
||||
ParentItemID = :newItemID
|
||||
WHERE CategoryID = :categoryID
|
||||
AND ParentItemID = 0
|
||||
", {
|
||||
businessID: cat.CategoryBusinessID,
|
||||
businessID: cat.BusinessID,
|
||||
newItemID: newItemID,
|
||||
categoryID: cat.CategoryID
|
||||
categoryID: cat.ID
|
||||
}, { datasource: "payfrit" });
|
||||
|
||||
// Set ItemBusinessID on ALL items in this category (including nested)
|
||||
// Set BusinessID on ALL items in this category (including nested)
|
||||
queryExecute("
|
||||
UPDATE Items
|
||||
SET ItemBusinessID = :businessID
|
||||
WHERE ItemCategoryID = :categoryID
|
||||
AND (ItemBusinessID IS NULL OR ItemBusinessID = 0)
|
||||
SET BusinessID = :businessID
|
||||
WHERE CategoryID = :categoryID
|
||||
AND (BusinessID IS NULL OR BusinessID = 0)
|
||||
", {
|
||||
businessID: cat.CategoryBusinessID,
|
||||
categoryID: cat.CategoryID
|
||||
businessID: cat.BusinessID,
|
||||
categoryID: cat.ID
|
||||
}, { datasource: "payfrit" });
|
||||
|
||||
// Count how many were updated
|
||||
qCount = queryExecute("
|
||||
SELECT COUNT(*) as cnt FROM Items
|
||||
WHERE ItemParentItemID = :newItemID
|
||||
WHERE ParentItemID = :newItemID
|
||||
", { newItemID: newItemID }, { datasource: "payfrit" });
|
||||
|
||||
migration["itemsUpdated"] = qCount.cnt;
|
||||
|
|
@ -188,9 +188,9 @@ try {
|
|||
// Dry run - count what would be updated
|
||||
qCount = queryExecute("
|
||||
SELECT COUNT(*) as cnt FROM Items
|
||||
WHERE ItemCategoryID = :categoryID
|
||||
AND ItemParentItemID = 0
|
||||
", { categoryID: cat.CategoryID }, { datasource: "payfrit" });
|
||||
WHERE CategoryID = :categoryID
|
||||
AND ParentItemID = 0
|
||||
", { categoryID: cat.ID }, { datasource: "payfrit" });
|
||||
|
||||
migration["itemsToUpdate"] = qCount.cnt;
|
||||
}
|
||||
|
|
@ -198,37 +198,37 @@ try {
|
|||
arrayAppend(response.migrations, migration);
|
||||
}
|
||||
|
||||
// Step 5: Set ItemBusinessID for templates (items in ItemTemplateLinks)
|
||||
// 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("
|
||||
UPDATE Items t
|
||||
INNER JOIN ItemTemplateLinks tl ON tl.TemplateItemID = t.ItemID
|
||||
INNER JOIN Items i ON i.ItemID = tl.ItemID
|
||||
SET t.ItemBusinessID = i.ItemBusinessID
|
||||
WHERE (t.ItemBusinessID IS NULL OR t.ItemBusinessID = 0)
|
||||
AND i.ItemBusinessID > 0
|
||||
INNER JOIN lt_ItemID_TemplateItemID tl ON tl.TemplateItemID = t.ItemID
|
||||
INNER JOIN Items i ON i.ID = tl.ItemID
|
||||
SET t.BusinessID = i.BusinessID
|
||||
WHERE (t.BusinessID IS NULL OR t.BusinessID = 0)
|
||||
AND i.BusinessID > 0
|
||||
", {}, { datasource: "payfrit" });
|
||||
|
||||
arrayAppend(response.steps, "Set ItemBusinessID on templates from linked items");
|
||||
arrayAppend(response.steps, "Set BusinessID on templates from linked items");
|
||||
|
||||
// Set ItemBusinessID on template children (options)
|
||||
// Set BusinessID on template children (options)
|
||||
queryExecute("
|
||||
UPDATE Items c
|
||||
INNER JOIN Items t ON t.ItemID = c.ItemParentItemID
|
||||
SET c.ItemBusinessID = t.ItemBusinessID
|
||||
WHERE t.ItemBusinessID > 0
|
||||
AND (c.ItemBusinessID IS NULL OR c.ItemBusinessID = 0)
|
||||
INNER JOIN Items t ON t.ItemID = c.ParentItemID
|
||||
SET c.BusinessID = t.BusinessID
|
||||
WHERE t.BusinessID > 0
|
||||
AND (c.BusinessID IS NULL OR c.BusinessID = 0)
|
||||
", {}, { datasource: "payfrit" });
|
||||
|
||||
arrayAppend(response.steps, "Set ItemBusinessID on template children");
|
||||
arrayAppend(response.steps, "Set BusinessID on template children");
|
||||
|
||||
// Make sure templates have ParentID=0 (they live at top level)
|
||||
queryExecute("
|
||||
UPDATE Items t
|
||||
INNER JOIN ItemTemplateLinks tl ON tl.TemplateItemID = t.ItemID
|
||||
SET t.ItemParentItemID = 0
|
||||
WHERE t.ItemParentItemID != 0
|
||||
INNER JOIN lt_ItemID_TemplateItemID tl ON tl.TemplateItemID = t.ItemID
|
||||
SET t.ParentItemID = 0
|
||||
WHERE t.ParentItemID != 0
|
||||
", {}, { datasource: "payfrit" });
|
||||
|
||||
arrayAppend(response.steps, "Ensured templates have ParentItemID=0");
|
||||
|
|
|
|||
|
|
@ -14,32 +14,32 @@ 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("
|
||||
UPDATE Items SET ItemIsActive = 0 WHERE ItemID = :itemId AND ItemBusinessID = :bizId
|
||||
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("
|
||||
UPDATE Items SET ItemIsActive = 0 WHERE ItemParentItemID = :itemId AND ItemBusinessID = :bizId
|
||||
UPDATE Items SET IsActive = 0 WHERE ParentItemID = :itemId AND BusinessID = :bizId
|
||||
", { itemId: itemId, bizId: bizId }, { datasource: "payfrit" });
|
||||
}
|
||||
|
||||
// Now verify what categories remain
|
||||
qCategories = queryExecute("
|
||||
SELECT i.ItemID, i.ItemName
|
||||
SELECT i.ID, i.Name
|
||||
FROM Items i
|
||||
WHERE i.ItemBusinessID = :bizId
|
||||
AND i.ItemParentItemID = 0
|
||||
AND i.ItemIsActive = 1
|
||||
AND i.ItemIsCollapsible = 0
|
||||
AND NOT EXISTS (SELECT 1 FROM ItemTemplateLinks tl WHERE tl.TemplateItemID = i.ItemID)
|
||||
ORDER BY i.ItemSortOrder
|
||||
WHERE i.BusinessID = :bizId
|
||||
AND i.ParentItemID = 0
|
||||
AND i.IsActive = 1
|
||||
AND i.IsCollapsible = 0
|
||||
AND NOT EXISTS (SELECT 1 FROM lt_ItemID_TemplateItemID tl WHERE tl.TemplateItemID = i.ID)
|
||||
ORDER BY i.SortOrder
|
||||
", { bizId: bizId }, { datasource: "payfrit" });
|
||||
|
||||
categories = [];
|
||||
for (row in qCategories) {
|
||||
arrayAppend(categories, { "ItemID": row.ItemID, "ItemName": row.ItemName });
|
||||
arrayAppend(categories, { "ItemID": row.ID, "Name": row.Name });
|
||||
}
|
||||
|
||||
writeOutput(serializeJSON({
|
||||
|
|
|
|||
|
|
@ -21,8 +21,8 @@ actions = [];
|
|||
|
||||
// First, let's see what templates already exist and are active for burgers
|
||||
qExistingLinks = queryExecute("
|
||||
SELECT tl.ItemID as MenuItemID, tl.TemplateItemID, t.ItemName as TemplateName
|
||||
FROM ItemTemplateLinks tl
|
||||
SELECT tl.ItemID as MenuItemID, tl.TemplateItemID, t.Name as TemplateName
|
||||
FROM lt_ItemID_TemplateItemID tl
|
||||
JOIN Items t ON t.ItemID = tl.TemplateItemID
|
||||
WHERE tl.ItemID IN (:burgerIds)
|
||||
", { burgerIds: { value: arrayToList(burgerIds), list: true } }, { datasource: "payfrit" });
|
||||
|
|
@ -33,8 +33,8 @@ for (row in qExistingLinks) {
|
|||
|
||||
// Reactivate template 11196 (Extras with Add Cheese)
|
||||
if (!dryRun) {
|
||||
queryExecute("UPDATE Items SET ItemIsActive = 1 WHERE ItemID = 11196", {}, { datasource: "payfrit" });
|
||||
queryExecute("UPDATE Items SET ItemIsActive = 1 WHERE ItemParentItemID = 11196", {}, { datasource: "payfrit" });
|
||||
queryExecute("UPDATE Items SET IsActive = 1 WHERE ItemID = 11196", {}, { datasource: "payfrit" });
|
||||
queryExecute("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)" });
|
||||
|
||||
|
|
@ -42,13 +42,13 @@ arrayAppend(actions, { action: dryRun ? "WOULD_REACTIVATE" : "REACTIVATED", item
|
|||
for (burgerId in burgerIds) {
|
||||
// Check if link already exists
|
||||
qCheck = queryExecute("
|
||||
SELECT COUNT(*) as cnt FROM ItemTemplateLinks WHERE ItemID = :burgerId AND TemplateItemID = 11196
|
||||
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("
|
||||
INSERT INTO ItemTemplateLinks (ItemID, TemplateItemID, SortOrder)
|
||||
INSERT INTO lt_ItemID_TemplateItemID (ItemID, TemplateItemID, SortOrder)
|
||||
VALUES (:burgerId, 11196, 2)
|
||||
", { burgerId: burgerId }, { datasource: "payfrit" });
|
||||
}
|
||||
|
|
@ -59,17 +59,17 @@ for (burgerId in burgerIds) {
|
|||
// Verify the result
|
||||
if (!dryRun) {
|
||||
qVerify = queryExecute("
|
||||
SELECT mi.ItemID, mi.ItemName, GROUP_CONCAT(t.ItemName ORDER BY tl.SortOrder) as Templates
|
||||
SELECT mi.ID, mi.Name, GROUP_CONCAT(t.Name ORDER BY tl.SortOrder) as Templates
|
||||
FROM Items mi
|
||||
LEFT JOIN ItemTemplateLinks tl ON tl.ItemID = mi.ItemID
|
||||
LEFT JOIN lt_ItemID_TemplateItemID tl ON tl.ItemID = mi.ID
|
||||
LEFT JOIN Items t ON t.ItemID = tl.TemplateItemID
|
||||
WHERE mi.ItemID IN (:burgerIds)
|
||||
GROUP BY mi.ItemID, mi.ItemName
|
||||
WHERE mi.ID IN (:burgerIds)
|
||||
GROUP BY mi.ID, mi.Name
|
||||
", { burgerIds: { value: arrayToList(burgerIds), list: true } }, { datasource: "payfrit" });
|
||||
|
||||
result = [];
|
||||
for (row in qVerify) {
|
||||
arrayAppend(result, { itemID: row.ItemID, name: row.ItemName, templates: row.Templates });
|
||||
arrayAppend(result, { itemID: row.ID, name: row.Name, templates: row.Templates });
|
||||
}
|
||||
} else {
|
||||
result = "Dry run - no changes made";
|
||||
|
|
|
|||
|
|
@ -1,32 +1,32 @@
|
|||
<cfsetting showdebugoutput="false">
|
||||
<cfcontent type="application/json" reset="true">
|
||||
<cfscript>
|
||||
// One-time fix: remove # prefix from BusinessBrandColor
|
||||
// One-time fix: remove # prefix from BrandColor
|
||||
qBefore = queryExecute("
|
||||
SELECT BusinessID, BusinessBrandColor
|
||||
SELECT ID, BrandColor
|
||||
FROM Businesses
|
||||
WHERE BusinessBrandColor LIKE :pattern
|
||||
WHERE BrandColor LIKE :pattern
|
||||
", { pattern: { value: "##%", cfsqltype: "cf_sql_varchar" } }, { datasource: "payfrit" });
|
||||
|
||||
if (qBefore.recordCount > 0) {
|
||||
queryExecute("
|
||||
UPDATE Businesses
|
||||
SET BusinessBrandColor = SUBSTRING(BusinessBrandColor, 2)
|
||||
WHERE BusinessBrandColor LIKE :pattern
|
||||
SET BrandColor = SUBSTRING(BrandColor, 2)
|
||||
WHERE BrandColor LIKE :pattern
|
||||
", { pattern: { value: "##%", cfsqltype: "cf_sql_varchar" } }, { datasource: "payfrit" });
|
||||
}
|
||||
|
||||
qAfter = queryExecute("
|
||||
SELECT BusinessID, BusinessBrandColor
|
||||
SELECT ID, BrandColor
|
||||
FROM Businesses
|
||||
WHERE BusinessBrandColor IS NOT NULL AND LENGTH(BusinessBrandColor) > 0
|
||||
WHERE BrandColor IS NOT NULL AND LENGTH(BrandColor) > 0
|
||||
", {}, { datasource: "payfrit" });
|
||||
|
||||
rows = [];
|
||||
for (i = 1; i <= qAfter.recordCount; i++) {
|
||||
arrayAppend(rows, {
|
||||
"BusinessID": qAfter.BusinessID[i],
|
||||
"BusinessBrandColor": qAfter.BusinessBrandColor[i]
|
||||
"BrandColor": qAfter.BrandColor[i]
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -30,8 +30,8 @@
|
|||
* 2. Re-parent the three flavors under the new group
|
||||
* 3. Remove template flag from flavors
|
||||
* 4. Mark "Choose Flavor" as the template
|
||||
* 5. Create ItemTemplateLinks entry for Shake -> Choose Flavor
|
||||
* 6. Set ItemRequiresChildSelection=1 on the shake item
|
||||
* 5. Create lt_ItemID_TemplateItemID entry for Shake -> Choose Flavor
|
||||
* 6. Set RequiresChildSelection=1 on the shake item
|
||||
*/
|
||||
|
||||
response = { "OK": false, "steps": [] };
|
||||
|
|
@ -46,19 +46,19 @@ try {
|
|||
// Step 1: Create "Choose Flavor" modifier group under Shake
|
||||
queryExecute("
|
||||
INSERT INTO Items (
|
||||
ItemCategoryID,
|
||||
ItemName,
|
||||
ItemDescription,
|
||||
ItemParentItemID,
|
||||
ItemPrice,
|
||||
ItemIsActive,
|
||||
ItemIsCheckedByDefault,
|
||||
ItemRequiresChildSelection,
|
||||
ItemMaxNumSelectionReq,
|
||||
ItemIsCollapsible,
|
||||
ItemSortOrder,
|
||||
ItemIsModifierTemplate,
|
||||
ItemAddedOn
|
||||
CategoryID,
|
||||
Name,
|
||||
Description,
|
||||
ParentItemID,
|
||||
Price,
|
||||
IsActive,
|
||||
IsCheckedByDefault,
|
||||
RequiresChildSelection,
|
||||
MaxNumSelectionReq,
|
||||
IsCollapsible,
|
||||
SortOrder,
|
||||
IsModifierTemplate,
|
||||
AddedOn
|
||||
) VALUES (
|
||||
:categoryID,
|
||||
'Choose Flavor',
|
||||
|
|
@ -81,22 +81,22 @@ try {
|
|||
|
||||
// Get the new Choose Flavor ID
|
||||
qNewGroup = queryExecute("
|
||||
SELECT ItemID FROM Items
|
||||
WHERE ItemName = 'Choose Flavor'
|
||||
AND ItemParentItemID = :shakeItemID
|
||||
ORDER BY ItemID DESC
|
||||
SELECT ID FROM Items
|
||||
WHERE Name = 'Choose Flavor'
|
||||
AND ParentItemID = :shakeItemID
|
||||
ORDER BY ID DESC
|
||||
LIMIT 1
|
||||
", { shakeItemID: shakeItemID }, { datasource: "payfrit" });
|
||||
|
||||
chooseFlavorID = qNewGroup.ItemID;
|
||||
chooseFlavorID = qNewGroup.ID;
|
||||
arrayAppend(response.steps, "Created 'Choose Flavor' group with ID: " & chooseFlavorID);
|
||||
|
||||
// Step 2: Re-parent the three flavors under Choose Flavor
|
||||
queryExecute("
|
||||
UPDATE Items
|
||||
SET ItemParentItemID = :chooseFlavorID,
|
||||
ItemIsModifierTemplate = 0,
|
||||
ItemIsCheckedByDefault = 0
|
||||
SET ParentItemID = :chooseFlavorID,
|
||||
IsModifierTemplate = 0,
|
||||
IsCheckedByDefault = 0
|
||||
WHERE ItemID IN (:chocolateID, :strawberryID, :vanillaID)
|
||||
", {
|
||||
chooseFlavorID: chooseFlavorID,
|
||||
|
|
@ -109,14 +109,14 @@ try {
|
|||
|
||||
// Step 3: Set Vanilla as default (common choice)
|
||||
queryExecute("
|
||||
UPDATE Items SET ItemIsCheckedByDefault = 1 WHERE ItemID = :vanillaID
|
||||
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("
|
||||
DELETE FROM ItemTemplateLinks
|
||||
DELETE FROM lt_ItemID_TemplateItemID
|
||||
WHERE TemplateItemID IN (:chocolateID, :strawberryID, :vanillaID)
|
||||
", {
|
||||
chocolateID: chocolateID,
|
||||
|
|
@ -126,9 +126,9 @@ try {
|
|||
|
||||
arrayAppend(response.steps, "Removed old template links for flavor items");
|
||||
|
||||
// Step 5: Create ItemTemplateLinks for Shake -> Choose Flavor
|
||||
// Step 5: Create lt_ItemID_TemplateItemID for Shake -> Choose Flavor
|
||||
queryExecute("
|
||||
INSERT INTO ItemTemplateLinks (ItemID, TemplateItemID, SortOrder)
|
||||
INSERT INTO lt_ItemID_TemplateItemID (ItemID, TemplateItemID, SortOrder)
|
||||
VALUES (:shakeItemID, :chooseFlavorID, 0)
|
||||
ON DUPLICATE KEY UPDATE SortOrder = 0
|
||||
", {
|
||||
|
|
@ -138,14 +138,14 @@ try {
|
|||
|
||||
arrayAppend(response.steps, "Created template link: Shake -> Choose Flavor");
|
||||
|
||||
// Step 6: Set ItemRequiresChildSelection on shake
|
||||
// Step 6: Set RequiresChildSelection on shake
|
||||
queryExecute("
|
||||
UPDATE Items
|
||||
SET ItemRequiresChildSelection = 1
|
||||
SET RequiresChildSelection = 1
|
||||
WHERE ItemID = :shakeItemID
|
||||
", { shakeItemID: shakeItemID }, { datasource: "payfrit" });
|
||||
|
||||
arrayAppend(response.steps, "Set ItemRequiresChildSelection=1 on Shake item");
|
||||
arrayAppend(response.steps, "Set RequiresChildSelection=1 on Shake item");
|
||||
|
||||
response["OK"] = true;
|
||||
response["chooseFlavorID"] = chooseFlavorID;
|
||||
|
|
|
|||
|
|
@ -75,17 +75,17 @@ function buildAddressString(line1, line2, city, zipCode) {
|
|||
<cfif structKeyExists(url, "geocode") AND structKeyExists(url, "addressId")>
|
||||
<cfset addressId = val(url.addressId)>
|
||||
<cfquery name="addr" datasource="payfrit">
|
||||
SELECT AddressLine1, AddressLine2, AddressCity, AddressZIPCode
|
||||
FROM Addresses WHERE AddressID = <cfqueryparam value="#addressId#" cfsqltype="cf_sql_integer">
|
||||
SELECT Line1, Line2, City, ZIPCode
|
||||
FROM Addresses WHERE ID = <cfqueryparam value="#addressId#" cfsqltype="cf_sql_integer">
|
||||
</cfquery>
|
||||
<cfif addr.recordCount GT 0>
|
||||
<cfset fullAddress = buildAddressString(addr.AddressLine1, addr.AddressLine2, addr.AddressCity, addr.AddressZIPCode)>
|
||||
<cfset fullAddress = buildAddressString(addr.Line1, addr.Line2, addr.City, addr.ZIPCode)>
|
||||
<cfset geo = geocodeAddress(fullAddress)>
|
||||
<cfif geo.success>
|
||||
<cfquery datasource="payfrit">
|
||||
UPDATE Addresses SET AddressLat = <cfqueryparam value="#geo.lat#" cfsqltype="cf_sql_decimal">,
|
||||
AddressLng = <cfqueryparam value="#geo.lng#" cfsqltype="cf_sql_decimal">
|
||||
WHERE AddressID = <cfqueryparam value="#addressId#" cfsqltype="cf_sql_integer">
|
||||
UPDATE Addresses SET Latitude = <cfqueryparam value="#geo.lat#" cfsqltype="cf_sql_decimal">,
|
||||
Longitude = <cfqueryparam value="#geo.lng#" cfsqltype="cf_sql_decimal">
|
||||
WHERE ID = <cfqueryparam value="#addressId#" cfsqltype="cf_sql_integer">
|
||||
</cfquery>
|
||||
<cfoutput><div class="success">Geocoded Address ID #addressId#: #geo.lat#, #geo.lng#</div></cfoutput>
|
||||
<cfelse>
|
||||
|
|
@ -96,21 +96,21 @@ function buildAddressString(line1, line2, city, zipCode) {
|
|||
|
||||
<cfif structKeyExists(url, "geocodeAll")>
|
||||
<cfquery name="missing" datasource="payfrit">
|
||||
SELECT AddressID, AddressLine1, AddressLine2, AddressCity, AddressZIPCode
|
||||
SELECT ID, Line1, Line2, City, ZIPCode
|
||||
FROM Addresses
|
||||
WHERE (AddressLat IS NULL OR AddressLat = 0)
|
||||
AND AddressLine1 IS NOT NULL AND AddressLine1 != ''
|
||||
WHERE (Latitude IS NULL OR Latitude = 0)
|
||||
AND Line1 IS NOT NULL AND Line1 != ''
|
||||
</cfquery>
|
||||
<cfset successCount = 0>
|
||||
<cfset failCount = 0>
|
||||
<cfloop query="missing">
|
||||
<cfset fullAddress = buildAddressString(missing.AddressLine1, missing.AddressLine2, missing.AddressCity, missing.AddressZIPCode)>
|
||||
<cfset fullAddress = buildAddressString(missing.Line1, missing.Line2, missing.City, missing.ZIPCode)>
|
||||
<cfset geo = geocodeAddress(fullAddress)>
|
||||
<cfif geo.success>
|
||||
<cfquery datasource="payfrit">
|
||||
UPDATE Addresses SET AddressLat = <cfqueryparam value="#geo.lat#" cfsqltype="cf_sql_decimal">,
|
||||
AddressLng = <cfqueryparam value="#geo.lng#" cfsqltype="cf_sql_decimal">
|
||||
WHERE AddressID = <cfqueryparam value="#missing.AddressID#" cfsqltype="cf_sql_integer">
|
||||
UPDATE Addresses SET Latitude = <cfqueryparam value="#geo.lat#" cfsqltype="cf_sql_decimal">,
|
||||
Longitude = <cfqueryparam value="#geo.lng#" cfsqltype="cf_sql_decimal">
|
||||
WHERE ID = <cfqueryparam value="#missing.ID#" cfsqltype="cf_sql_integer">
|
||||
</cfquery>
|
||||
<cfset successCount = successCount + 1>
|
||||
<cfelse>
|
||||
|
|
@ -123,23 +123,23 @@ function buildAddressString(line1, line2, city, zipCode) {
|
|||
|
||||
<cfquery name="addresses" datasource="payfrit">
|
||||
SELECT
|
||||
b.BusinessID,
|
||||
b.BusinessName,
|
||||
a.AddressID,
|
||||
a.AddressLine1,
|
||||
a.AddressLine2,
|
||||
a.AddressCity,
|
||||
a.AddressZIPCode,
|
||||
a.AddressLat,
|
||||
a.AddressLng
|
||||
b.ID,
|
||||
b.Name,
|
||||
a.ID,
|
||||
a.Line1,
|
||||
a.Line2,
|
||||
a.City,
|
||||
a.ZIPCode,
|
||||
a.Latitude,
|
||||
a.Longitude
|
||||
FROM Businesses b
|
||||
LEFT JOIN Addresses a ON b.BusinessAddressID = a.AddressID
|
||||
ORDER BY b.BusinessName
|
||||
LEFT JOIN Addresses a ON b.AddressID = a.ID
|
||||
ORDER BY b.Name
|
||||
</cfquery>
|
||||
|
||||
<cfset missingCount = 0>
|
||||
<cfloop query="addresses">
|
||||
<cfif (NOT len(addresses.AddressLat) OR val(addresses.AddressLat) EQ 0) AND len(addresses.AddressLine1)>
|
||||
<cfif (NOT len(addresses.Latitude) OR val(addresses.Latitude) EQ 0) AND len(addresses.Line1)>
|
||||
<cfset missingCount = missingCount + 1>
|
||||
</cfif>
|
||||
</cfloop>
|
||||
|
|
@ -166,31 +166,31 @@ function buildAddressString(line1, line2, city, zipCode) {
|
|||
<cfloop query="addresses">
|
||||
<tr>
|
||||
<td>
|
||||
#addresses.BusinessName#
|
||||
<cfif len(addresses.AddressLat) AND val(addresses.AddressLat) NEQ 0>
|
||||
#addresses.Name#
|
||||
<cfif len(addresses.Latitude) AND val(addresses.Latitude) NEQ 0>
|
||||
<span class="has-coords">#chr(10003)#</span>
|
||||
<cfelseif len(addresses.AddressLine1)>
|
||||
<cfelseif len(addresses.Line1)>
|
||||
<span class="no-coords">#chr(9679)#</span>
|
||||
</cfif>
|
||||
</td>
|
||||
<td class="address">
|
||||
<cfif len(addresses.AddressLine1)>
|
||||
#addresses.AddressLine1#<cfif len(addresses.AddressLine2)>, #addresses.AddressLine2#</cfif><br>
|
||||
#addresses.AddressCity# #addresses.AddressZIPCode#
|
||||
<cfif len(addresses.Line1)>
|
||||
#addresses.Line1#<cfif len(addresses.Line2)>, #addresses.Line2#</cfif><br>
|
||||
#addresses.City# #addresses.ZIPCode#
|
||||
<cfelse>
|
||||
<em style="color:##666;">No address</em>
|
||||
</cfif>
|
||||
</td>
|
||||
<td class="coords">
|
||||
<cfif len(addresses.AddressLat) AND val(addresses.AddressLat) NEQ 0>
|
||||
#numberFormat(addresses.AddressLat, "_.______")#<br>
|
||||
#numberFormat(addresses.AddressLng, "_.______")#
|
||||
<cfif len(addresses.Latitude) AND val(addresses.Latitude) NEQ 0>
|
||||
#numberFormat(addresses.Latitude, "_.______")#<br>
|
||||
#numberFormat(addresses.Longitude, "_.______")#
|
||||
<cfelse>
|
||||
-
|
||||
</cfif>
|
||||
</td>
|
||||
<td>
|
||||
<cfif len(addresses.AddressLine1) AND len(addresses.AddressID)>
|
||||
<cfif len(addresses.Line1) AND len(addresses.AddressID)>
|
||||
<a href="?geocode=1&addressId=#addresses.AddressID#"><button class="btn-lookup">Lookup</button></a>
|
||||
</cfif>
|
||||
</td>
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ try {
|
|||
response["ERROR"] = "ChildBusinessID required";
|
||||
} else {
|
||||
queryExecute("
|
||||
UPDATE Businesses SET BusinessParentBusinessID = :parentId WHERE BusinessID = :childId
|
||||
UPDATE Businesses SET ParentBusinessID = :parentId WHERE ID = :childId
|
||||
", {
|
||||
parentId: { value = parentID > 0 ? parentID : javaCast("null", ""), cfsqltype = "cf_sql_integer", null = parentID == 0 },
|
||||
childId: childID
|
||||
|
|
|
|||
|
|
@ -26,13 +26,13 @@ try {
|
|||
|
||||
// Step 1: Get all parent items (burgers, combos, etc.)
|
||||
qParentItems = queryExecute("
|
||||
SELECT i.ItemID, i.ItemName
|
||||
SELECT i.ID, i.Name
|
||||
FROM Items i
|
||||
INNER JOIN Categories c ON c.CategoryID = i.ItemCategoryID
|
||||
WHERE c.CategoryBusinessID = :businessID
|
||||
AND i.ItemParentItemID = 0
|
||||
AND i.ItemIsActive = 1
|
||||
ORDER BY i.ItemName
|
||||
INNER JOIN Categories c ON c.ID = i.CategoryID
|
||||
WHERE c.BusinessID = :businessID
|
||||
AND i.ParentItemID = 0
|
||||
AND i.IsActive = 1
|
||||
ORDER BY i.Name
|
||||
", { businessID: businessID }, { datasource: "payfrit" });
|
||||
|
||||
arrayAppend(response.steps, "Found " & qParentItems.recordCount & " parent items");
|
||||
|
|
@ -41,20 +41,20 @@ try {
|
|||
qModifiers = queryExecute("
|
||||
SELECT
|
||||
m.ItemID,
|
||||
m.ItemName,
|
||||
m.ItemParentItemID,
|
||||
m.ItemPrice,
|
||||
m.ItemIsCheckedByDefault,
|
||||
m.ItemSortOrder,
|
||||
p.ItemName as ParentName
|
||||
m.Name,
|
||||
m.ParentItemID,
|
||||
m.Price,
|
||||
m.IsCheckedByDefault,
|
||||
m.SortOrder,
|
||||
p.Name as ParentName
|
||||
FROM Items m
|
||||
INNER JOIN Items p ON p.ItemID = m.ItemParentItemID
|
||||
INNER JOIN Categories c ON c.CategoryID = p.ItemCategoryID
|
||||
WHERE c.CategoryBusinessID = :businessID
|
||||
AND m.ItemParentItemID > 0
|
||||
AND m.ItemIsActive = 1
|
||||
AND p.ItemParentItemID = 0
|
||||
ORDER BY m.ItemName, m.ItemID
|
||||
INNER JOIN Items p ON p.ItemID = m.ParentItemID
|
||||
INNER JOIN Categories c ON c.ID = p.CategoryID
|
||||
WHERE c.BusinessID = :businessID
|
||||
AND m.ParentItemID > 0
|
||||
AND m.IsActive = 1
|
||||
AND p.ParentItemID = 0
|
||||
ORDER BY m.Name, m.ItemID
|
||||
", { businessID: businessID }, { datasource: "payfrit" });
|
||||
|
||||
arrayAppend(response.steps, "Found " & qModifiers.recordCount & " level-1 modifiers");
|
||||
|
|
@ -62,17 +62,17 @@ try {
|
|||
// Step 3: Group modifiers by name to find duplicates
|
||||
modifiersByName = {};
|
||||
for (mod in qModifiers) {
|
||||
modName = mod.ItemName;
|
||||
modName = mod.Name;
|
||||
if (!structKeyExists(modifiersByName, modName)) {
|
||||
modifiersByName[modName] = [];
|
||||
}
|
||||
arrayAppend(modifiersByName[modName], {
|
||||
"ItemID": mod.ItemID,
|
||||
"ParentItemID": mod.ItemParentItemID,
|
||||
"ParentItemID": mod.ParentItemID,
|
||||
"ParentName": mod.ParentName,
|
||||
"Price": mod.ItemPrice,
|
||||
"IsDefault": mod.ItemIsCheckedByDefault,
|
||||
"SortOrder": mod.ItemSortOrder
|
||||
"Price": mod.Price,
|
||||
"IsDefault": mod.IsCheckedByDefault,
|
||||
"SortOrder": mod.SortOrder
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -91,7 +91,7 @@ try {
|
|||
|
||||
// Mark as template
|
||||
queryExecute("
|
||||
UPDATE Items SET ItemIsModifierTemplate = 1 WHERE ItemID = :itemID
|
||||
UPDATE Items SET IsModifierTemplate = 1 WHERE ItemID = :itemID
|
||||
", { itemID: templateItemID }, { datasource: "payfrit" });
|
||||
|
||||
templateMap[modName] = templateItemID;
|
||||
|
|
@ -111,7 +111,7 @@ try {
|
|||
// Insert link (ignore duplicates)
|
||||
try {
|
||||
queryExecute("
|
||||
INSERT INTO ItemTemplateLinks (ItemID, TemplateItemID, SortOrder)
|
||||
INSERT INTO lt_ItemID_TemplateItemID (ItemID, TemplateItemID, SortOrder)
|
||||
VALUES (:itemID, :templateID, :sortOrder)
|
||||
ON DUPLICATE KEY UPDATE SortOrder = :sortOrder
|
||||
", {
|
||||
|
|
@ -134,7 +134,7 @@ try {
|
|||
if (i > 1) {
|
||||
arrayAppend(orphanItems, {
|
||||
"ItemID": inst.ItemID,
|
||||
"ItemName": modName,
|
||||
"Name": modName,
|
||||
"WasUnder": inst.ParentName
|
||||
});
|
||||
}
|
||||
|
|
@ -143,12 +143,12 @@ try {
|
|||
// Single instance - still mark as template for consistency
|
||||
singleItem = instances[1];
|
||||
queryExecute("
|
||||
UPDATE Items SET ItemIsModifierTemplate = 1 WHERE ItemID = :itemID
|
||||
UPDATE Items SET IsModifierTemplate = 1 WHERE ItemID = :itemID
|
||||
", { itemID: singleItem.ItemID }, { datasource: "payfrit" });
|
||||
|
||||
// Create link
|
||||
queryExecute("
|
||||
INSERT INTO ItemTemplateLinks (ItemID, TemplateItemID, SortOrder)
|
||||
INSERT INTO lt_ItemID_TemplateItemID (ItemID, TemplateItemID, SortOrder)
|
||||
VALUES (:itemID, :templateID, :sortOrder)
|
||||
ON DUPLICATE KEY UPDATE SortOrder = :sortOrder
|
||||
", {
|
||||
|
|
|
|||
|
|
@ -27,20 +27,20 @@ try {
|
|||
// Find all businesses with items in unified schema
|
||||
if (len(businessFilter)) {
|
||||
qBusinesses = queryExecute("
|
||||
SELECT DISTINCT ItemBusinessID as BusinessID
|
||||
SELECT DISTINCT BusinessID as BusinessID
|
||||
FROM Items
|
||||
WHERE ItemBusinessID = :bid AND ItemBusinessID > 0
|
||||
WHERE BusinessID = :bid AND BusinessID > 0
|
||||
", { bid: businessFilter }, { datasource: "payfrit" });
|
||||
} else {
|
||||
qBusinesses = queryExecute("
|
||||
SELECT DISTINCT ItemBusinessID as BusinessID
|
||||
SELECT DISTINCT BusinessID as BusinessID
|
||||
FROM Items
|
||||
WHERE ItemBusinessID > 0
|
||||
WHERE BusinessID > 0
|
||||
", {}, { datasource: "payfrit" });
|
||||
}
|
||||
|
||||
for (biz in qBusinesses) {
|
||||
bizId = biz.BusinessID;
|
||||
bizId = biz.ID;
|
||||
bizResult = { "BusinessID": bizId, "CategoriesCreated": 0, "ItemsUpdated": 0 };
|
||||
|
||||
try {
|
||||
|
|
@ -48,26 +48,26 @@ try {
|
|||
qCategoryItems = queryExecute("
|
||||
SELECT DISTINCT
|
||||
p.ItemID,
|
||||
p.ItemName,
|
||||
p.ItemSortOrder
|
||||
p.Name,
|
||||
p.SortOrder
|
||||
FROM Items p
|
||||
INNER JOIN Items c ON c.ItemParentItemID = p.ItemID
|
||||
WHERE p.ItemBusinessID = :bizId
|
||||
AND p.ItemParentItemID = 0
|
||||
AND (p.ItemIsCollapsible = 0 OR p.ItemIsCollapsible IS NULL)
|
||||
INNER JOIN Items c ON c.ParentItemID = p.ItemID
|
||||
WHERE p.BusinessID = :bizId
|
||||
AND p.ParentItemID = 0
|
||||
AND (p.IsCollapsible = 0 OR p.IsCollapsible IS NULL)
|
||||
AND NOT EXISTS (
|
||||
SELECT 1 FROM ItemTemplateLinks tl WHERE tl.TemplateItemID = p.ItemID
|
||||
SELECT 1 FROM lt_ItemID_TemplateItemID tl WHERE tl.TemplateItemID = p.ItemID
|
||||
)
|
||||
ORDER BY p.ItemSortOrder, p.ItemName
|
||||
ORDER BY p.SortOrder, p.Name
|
||||
", { bizId: bizId }, { datasource: "payfrit" });
|
||||
|
||||
sortOrder = 0;
|
||||
for (catItem in qCategoryItems) {
|
||||
// Check if category already exists for this business with same name
|
||||
qExisting = queryExecute("
|
||||
SELECT CategoryID FROM Categories
|
||||
WHERE CategoryBusinessID = :bizId AND CategoryName = :name
|
||||
", { bizId: bizId, name: left(catItem.ItemName, 30) }, { datasource: "payfrit" });
|
||||
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
|
||||
|
|
@ -79,12 +79,12 @@ try {
|
|||
// Create new category with explicit ID
|
||||
queryExecute("
|
||||
INSERT INTO Categories
|
||||
(CategoryID, CategoryBusinessID, CategoryParentCategoryID, CategoryName, CategorySortOrder, CategoryAddedOn)
|
||||
(CategoryID, BusinessID, ParentCategoryID, Name, SortOrder, AddedOn)
|
||||
VALUES (:catId, :bizId, 0, :name, :sortOrder, NOW())
|
||||
", {
|
||||
catId: newCatId,
|
||||
bizId: bizId,
|
||||
name: left(catItem.ItemName, 30),
|
||||
name: left(catItem.Name, 30),
|
||||
sortOrder: sortOrder
|
||||
}, { datasource: "payfrit" });
|
||||
|
||||
|
|
@ -96,9 +96,9 @@ try {
|
|||
// Update all children of this category Item to have the new CategoryID
|
||||
queryExecute("
|
||||
UPDATE Items
|
||||
SET ItemCategoryID = :catId
|
||||
WHERE ItemParentItemID = :parentId
|
||||
AND ItemBusinessID = :bizId
|
||||
SET CategoryID = :catId
|
||||
WHERE ParentItemID = :parentId
|
||||
AND BusinessID = :bizId
|
||||
", {
|
||||
catId: newCatId,
|
||||
parentId: catItem.ItemID,
|
||||
|
|
|
|||
299
api/admin/perf-dashboard.cfm
Normal file
299
api/admin/perf-dashboard.cfm
Normal file
|
|
@ -0,0 +1,299 @@
|
|||
<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; }
|
||||
|
||||
.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 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') +
|
||||
card('Data Since', s.FirstLog || 'none', '');
|
||||
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 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>
|
||||
|
|
@ -40,7 +40,7 @@ try {
|
|||
MAX(TotalMs) as MaxMs,
|
||||
ROUND(AVG(QueryCount), 1) as AvgQueries,
|
||||
ROUND(AVG(ResponseBytes)) as AvgBytes
|
||||
FROM api_perf_log
|
||||
FROM ApiPerfLogs
|
||||
WHERE LoggedAt > DATE_SUB(NOW(), INTERVAL :hours HOUR)
|
||||
GROUP BY Endpoint
|
||||
ORDER BY Calls DESC
|
||||
|
|
@ -76,7 +76,7 @@ try {
|
|||
ROUND(AVG(AppMs)) as AvgAppMs,
|
||||
MAX(TotalMs) as MaxMs,
|
||||
ROUND(AVG(QueryCount), 1) as AvgQueries
|
||||
FROM api_perf_log
|
||||
FROM ApiPerfLogs
|
||||
WHERE LoggedAt > DATE_SUB(NOW(), INTERVAL :hours HOUR)
|
||||
GROUP BY Endpoint
|
||||
HAVING Calls >= 3
|
||||
|
|
@ -106,7 +106,7 @@ try {
|
|||
q = queryExecute("
|
||||
SELECT Endpoint, TotalMs, DbMs, AppMs, QueryCount, ResponseBytes,
|
||||
BusinessID, UserID, LoggedAt
|
||||
FROM api_perf_log
|
||||
FROM ApiPerfLogs
|
||||
WHERE LoggedAt > DATE_SUB(NOW(), INTERVAL :hours HOUR)
|
||||
ORDER BY TotalMs DESC
|
||||
LIMIT :lim
|
||||
|
|
@ -144,7 +144,7 @@ try {
|
|||
ROUND(AVG(QueryCount), 1) as OverallAvgQueries,
|
||||
MIN(LoggedAt) as FirstLog,
|
||||
MAX(LoggedAt) as LastLog
|
||||
FROM api_perf_log
|
||||
FROM ApiPerfLogs
|
||||
WHERE LoggedAt > DATE_SUB(NOW(), INTERVAL :hours HOUR)
|
||||
", {
|
||||
hours: { value: hours, cfsqltype: "cf_sql_integer" }
|
||||
|
|
|
|||
|
|
@ -2,25 +2,25 @@
|
|||
<cfcontent type="application/json; charset=utf-8" reset="true">
|
||||
|
||||
<cfscript>
|
||||
// Add QuickTaskTemplateTypeID column to QuickTaskTemplates table if it doesn't exist
|
||||
// Add TaskTypeID column to QuickTaskTemplates table if it doesn't exist
|
||||
try {
|
||||
// Check if column exists
|
||||
qCheck = queryExecute("
|
||||
SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE TABLE_SCHEMA = 'payfrit'
|
||||
AND TABLE_NAME = 'QuickTaskTemplates'
|
||||
AND COLUMN_NAME = 'QuickTaskTemplateTypeID'
|
||||
AND COLUMN_NAME = 'TaskTypeID'
|
||||
", [], { datasource: "payfrit" });
|
||||
|
||||
if (qCheck.recordCount == 0) {
|
||||
queryExecute("
|
||||
ALTER TABLE QuickTaskTemplates
|
||||
ADD COLUMN QuickTaskTemplateTypeID INT NULL AFTER QuickTaskTemplateCategoryID
|
||||
ADD COLUMN TaskTypeID INT NULL AFTER TaskCategoryID
|
||||
", [], { datasource: "payfrit" });
|
||||
|
||||
writeOutput(serializeJSON({
|
||||
"OK": true,
|
||||
"MESSAGE": "Column QuickTaskTemplateTypeID added to QuickTaskTemplates"
|
||||
"MESSAGE": "Column TaskTypeID added to QuickTaskTemplates"
|
||||
}));
|
||||
} else {
|
||||
writeOutput(serializeJSON({
|
||||
|
|
|
|||
|
|
@ -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 TaskID IN (30, 31, 32)", [], { datasource: "payfrit" });
|
||||
queryExecute("DELETE FROM Tasks WHERE ID IN (30, 31, 32)", [], { datasource: "payfrit" });
|
||||
|
||||
writeOutput(serializeJSON({
|
||||
"OK": true,
|
||||
|
|
|
|||
|
|
@ -50,13 +50,13 @@ try {
|
|||
// Get template details
|
||||
qTemplate = queryExecute("
|
||||
SELECT
|
||||
QuickTaskTemplateTitle as Title,
|
||||
QuickTaskTemplateDetails as Details,
|
||||
QuickTaskTemplateCategoryID as CategoryID
|
||||
Title as Title,
|
||||
Details as Details,
|
||||
TaskCategoryID as CategoryID
|
||||
FROM QuickTaskTemplates
|
||||
WHERE QuickTaskTemplateID = :id
|
||||
AND QuickTaskTemplateBusinessID = :businessID
|
||||
AND QuickTaskTemplateIsActive = 1
|
||||
WHERE ID = :id
|
||||
AND BusinessID = :businessID
|
||||
AND IsActive = 1
|
||||
", {
|
||||
id: { value: templateID, cfsqltype: "cf_sql_integer" },
|
||||
businessID: { value: businessID, cfsqltype: "cf_sql_integer" }
|
||||
|
|
@ -66,11 +66,11 @@ try {
|
|||
apiAbort({ "OK": false, "ERROR": "not_found", "MESSAGE": "Template not found" });
|
||||
}
|
||||
|
||||
// Create the task (TaskClaimedByUserID=0 means unclaimed/pending)
|
||||
// Create the task (ClaimedByUserID=0 means unclaimed/pending)
|
||||
queryExecute("
|
||||
INSERT INTO Tasks (
|
||||
TaskBusinessID, TaskCategoryID, TaskTypeID,
|
||||
TaskTitle, TaskDetails, TaskAddedOn, TaskClaimedByUserID
|
||||
BusinessID, CategoryID, TaskTypeID,
|
||||
Title, Details, CreatedOn, ClaimedByUserID
|
||||
) VALUES (
|
||||
:businessID, :categoryID, :typeID,
|
||||
:title, :details, NOW(), 0
|
||||
|
|
|
|||
|
|
@ -5,23 +5,23 @@
|
|||
<cfscript>
|
||||
try {
|
||||
q = queryExecute("
|
||||
SELECT TaskID, TaskTitle, TaskDetails, TaskCategoryID, TaskClaimedByUserID, TaskCompletedOn, TaskAddedOn
|
||||
SELECT ID, Title, Details, TaskCategoryID, ClaimedByUserID, CompletedOn, CreatedOn
|
||||
FROM Tasks
|
||||
WHERE TaskBusinessID = 47
|
||||
ORDER BY TaskID DESC
|
||||
WHERE BusinessID = 47
|
||||
ORDER BY ID DESC
|
||||
LIMIT 20
|
||||
", [], { datasource: "payfrit" });
|
||||
|
||||
tasks = [];
|
||||
for (row in q) {
|
||||
arrayAppend(tasks, {
|
||||
"TaskID": row.TaskID,
|
||||
"Title": row.TaskTitle,
|
||||
"Details": isNull(row.TaskDetails) ? "" : row.TaskDetails,
|
||||
"CategoryID": row.TaskCategoryID,
|
||||
"ClaimedByUserID": row.TaskClaimedByUserID,
|
||||
"CompletedOn": isNull(row.TaskCompletedOn) ? "" : dateTimeFormat(row.TaskCompletedOn, "yyyy-mm-dd HH:nn:ss"),
|
||||
"AddedOn": isNull(row.TaskAddedOn) ? "" : dateTimeFormat(row.TaskAddedOn, "yyyy-mm-dd HH:nn:ss")
|
||||
"TaskID": row.ID,
|
||||
"Title": row.Title,
|
||||
"Details": isNull(row.Details) ? "" : row.Details,
|
||||
"CategoryID": row.ID,
|
||||
"ClaimedByUserID": row.ClaimedByUserID,
|
||||
"CompletedOn": isNull(row.CompletedOn) ? "" : dateTimeFormat(row.CompletedOn, "yyyy-mm-dd HH:nn:ss"),
|
||||
"AddedOn": isNull(row.CreatedOn) ? "" : dateTimeFormat(row.CreatedOn, "yyyy-mm-dd HH:nn:ss")
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ try {
|
|||
// Verify template exists and belongs to this business
|
||||
qCheck = queryExecute("
|
||||
SELECT QuickTaskTemplateID FROM QuickTaskTemplates
|
||||
WHERE QuickTaskTemplateID = :id AND QuickTaskTemplateBusinessID = :businessID
|
||||
WHERE ID = :id AND BusinessID = :businessID
|
||||
", {
|
||||
id: { value: templateID, cfsqltype: "cf_sql_integer" },
|
||||
businessID: { value: businessID, cfsqltype: "cf_sql_integer" }
|
||||
|
|
@ -62,8 +62,8 @@ try {
|
|||
|
||||
// Soft delete by setting IsActive to 0
|
||||
queryExecute("
|
||||
UPDATE QuickTaskTemplates SET QuickTaskTemplateIsActive = 0
|
||||
WHERE QuickTaskTemplateID = :id
|
||||
UPDATE QuickTaskTemplates SET IsActive = 0
|
||||
WHERE ID = :id
|
||||
", {
|
||||
id: { value: templateID, cfsqltype: "cf_sql_integer" }
|
||||
}, { datasource: "payfrit" });
|
||||
|
|
|
|||
|
|
@ -45,22 +45,22 @@ try {
|
|||
// Get quick task templates for this business
|
||||
q = queryExecute("
|
||||
SELECT
|
||||
qt.QuickTaskTemplateID,
|
||||
qt.QuickTaskTemplateName as Name,
|
||||
qt.QuickTaskTemplateCategoryID as CategoryID,
|
||||
qt.QuickTaskTemplateTitle as Title,
|
||||
qt.QuickTaskTemplateDetails as Details,
|
||||
qt.QuickTaskTemplateIcon as Icon,
|
||||
qt.QuickTaskTemplateColor as Color,
|
||||
qt.QuickTaskTemplateSortOrder as SortOrder,
|
||||
qt.QuickTaskTemplateIsActive as IsActive,
|
||||
tc.TaskCategoryName as CategoryName,
|
||||
tc.TaskCategoryColor as CategoryColor
|
||||
qt.ID,
|
||||
qt.Name as Name,
|
||||
qt.TaskCategoryID as CategoryID,
|
||||
qt.Title as Title,
|
||||
qt.Details as Details,
|
||||
qt.Icon as Icon,
|
||||
qt.Color as Color,
|
||||
qt.SortOrder as SortOrder,
|
||||
qt.IsActive as IsActive,
|
||||
tc.Name as Name,
|
||||
tc.Color as CategoryColor
|
||||
FROM QuickTaskTemplates qt
|
||||
LEFT JOIN TaskCategories tc ON qt.QuickTaskTemplateCategoryID = tc.TaskCategoryID
|
||||
WHERE qt.QuickTaskTemplateBusinessID = :businessID
|
||||
AND qt.QuickTaskTemplateIsActive = 1
|
||||
ORDER BY qt.QuickTaskTemplateSortOrder, qt.QuickTaskTemplateID
|
||||
LEFT JOIN TaskCategories tc ON qt.TaskCategoryID = tc.ID
|
||||
WHERE qt.BusinessID = :businessID
|
||||
AND qt.IsActive = 1
|
||||
ORDER BY qt.SortOrder, qt.ID
|
||||
", {
|
||||
businessID: { value: businessID, cfsqltype: "cf_sql_integer" }
|
||||
}, { datasource: "payfrit" });
|
||||
|
|
@ -68,7 +68,7 @@ try {
|
|||
templates = [];
|
||||
for (row in q) {
|
||||
arrayAppend(templates, {
|
||||
"QuickTaskTemplateID": row.QuickTaskTemplateID,
|
||||
"QuickTaskTemplateID": row.ID,
|
||||
"Name": row.Name,
|
||||
"CategoryID": isNull(row.CategoryID) ? "" : row.CategoryID,
|
||||
"Title": row.Title,
|
||||
|
|
@ -77,7 +77,7 @@ try {
|
|||
"Color": isNull(row.Color) ? "##6366f1" : row.Color,
|
||||
"SortOrder": row.SortOrder,
|
||||
"IsActive": row.IsActive,
|
||||
"CategoryName": isNull(row.CategoryName) ? "" : row.CategoryName,
|
||||
"Name": isNull(row.Name) ? "" : row.Name,
|
||||
"CategoryColor": isNull(row.CategoryColor) ? "" : row.CategoryColor
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
<cfscript>
|
||||
try {
|
||||
// Delete all Quick Task templates for business 1
|
||||
queryExecute("DELETE FROM QuickTaskTemplates WHERE QuickTaskTemplateBusinessID = 1", [], { datasource: "payfrit" });
|
||||
queryExecute("DELETE FROM QuickTaskTemplates WHERE BusinessID = 1", [], { datasource: "payfrit" });
|
||||
|
||||
writeOutput(serializeJSON({
|
||||
"OK": true,
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ try {
|
|||
// UPDATE existing template
|
||||
qCheck = queryExecute("
|
||||
SELECT QuickTaskTemplateID FROM QuickTaskTemplates
|
||||
WHERE QuickTaskTemplateID = :id AND QuickTaskTemplateBusinessID = :businessID
|
||||
WHERE ID = :id AND BusinessID = :businessID
|
||||
", {
|
||||
id: { value: templateID, cfsqltype: "cf_sql_integer" },
|
||||
businessID: { value: businessID, cfsqltype: "cf_sql_integer" }
|
||||
|
|
@ -82,13 +82,13 @@ try {
|
|||
|
||||
queryExecute("
|
||||
UPDATE QuickTaskTemplates SET
|
||||
QuickTaskTemplateName = :name,
|
||||
QuickTaskTemplateTitle = :title,
|
||||
QuickTaskTemplateDetails = :details,
|
||||
QuickTaskTemplateCategoryID = :categoryID,
|
||||
QuickTaskTemplateIcon = :icon,
|
||||
QuickTaskTemplateColor = :color
|
||||
WHERE QuickTaskTemplateID = :id
|
||||
Name = :name,
|
||||
Title = :title,
|
||||
Details = :details,
|
||||
TaskCategoryID = :categoryID,
|
||||
Icon = :icon,
|
||||
Color = :color
|
||||
WHERE ID = :id
|
||||
", {
|
||||
name: { value: templateName, cfsqltype: "cf_sql_varchar" },
|
||||
title: { value: templateTitle, cfsqltype: "cf_sql_varchar" },
|
||||
|
|
@ -109,8 +109,8 @@ try {
|
|||
// INSERT new template
|
||||
// Get next sort order
|
||||
qSort = queryExecute("
|
||||
SELECT COALESCE(MAX(QuickTaskTemplateSortOrder), 0) + 1 as nextSort
|
||||
FROM QuickTaskTemplates WHERE QuickTaskTemplateBusinessID = :businessID
|
||||
SELECT COALESCE(MAX(SortOrder), 0) + 1 as nextSort
|
||||
FROM QuickTaskTemplates WHERE BusinessID = :businessID
|
||||
", {
|
||||
businessID: { value: businessID, cfsqltype: "cf_sql_integer" }
|
||||
}, { datasource: "payfrit" });
|
||||
|
|
@ -119,9 +119,9 @@ try {
|
|||
|
||||
queryExecute("
|
||||
INSERT INTO QuickTaskTemplates (
|
||||
QuickTaskTemplateBusinessID, QuickTaskTemplateName, QuickTaskTemplateTitle,
|
||||
QuickTaskTemplateDetails, QuickTaskTemplateCategoryID,
|
||||
QuickTaskTemplateIcon, QuickTaskTemplateColor, QuickTaskTemplateSortOrder
|
||||
BusinessID, Name, Title,
|
||||
Details, TaskCategoryID,
|
||||
Icon, Color, SortOrder
|
||||
) VALUES (
|
||||
:businessID, :name, :title, :details, :categoryID, :icon, :color, :sortOrder
|
||||
)
|
||||
|
|
|
|||
|
|
@ -15,20 +15,20 @@ try {
|
|||
// Create QuickTaskTemplates table
|
||||
queryExecute("
|
||||
CREATE TABLE IF NOT EXISTS QuickTaskTemplates (
|
||||
QuickTaskTemplateID INT AUTO_INCREMENT PRIMARY KEY,
|
||||
QuickTaskTemplateBusinessID INT NOT NULL,
|
||||
QuickTaskTemplateName VARCHAR(100) NOT NULL,
|
||||
QuickTaskTemplateCategoryID INT NULL,
|
||||
QuickTaskTemplateTypeID INT NULL,
|
||||
QuickTaskTemplateTitle VARCHAR(255) NOT NULL,
|
||||
QuickTaskTemplateDetails TEXT NULL,
|
||||
QuickTaskTemplateIcon VARCHAR(30) DEFAULT 'add_box',
|
||||
QuickTaskTemplateColor VARCHAR(20) DEFAULT '##6366f1',
|
||||
QuickTaskTemplateSortOrder INT DEFAULT 0,
|
||||
QuickTaskTemplateIsActive BIT(1) DEFAULT b'1',
|
||||
QuickTaskTemplateCreatedOn DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
INDEX idx_business_active (QuickTaskTemplateBusinessID, QuickTaskTemplateIsActive),
|
||||
INDEX idx_sort (QuickTaskTemplateBusinessID, QuickTaskTemplateSortOrder)
|
||||
ID INT AUTO_INCREMENT PRIMARY KEY,
|
||||
BusinessID INT NOT NULL,
|
||||
Name VARCHAR(100) NOT NULL,
|
||||
TaskCategoryID INT NULL,
|
||||
TaskTypeID INT NULL,
|
||||
Title VARCHAR(255) NOT NULL,
|
||||
Details TEXT NULL,
|
||||
Icon VARCHAR(30) DEFAULT 'add_box',
|
||||
Color VARCHAR(20) DEFAULT '##6366f1',
|
||||
SortOrder INT DEFAULT 0,
|
||||
IsActive BIT(1) DEFAULT b'1',
|
||||
CreatedOn DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
INDEX idx_business_active (BusinessID, IsActive),
|
||||
INDEX idx_sort (BusinessID, SortOrder)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
|
||||
", [], { datasource: "payfrit" });
|
||||
|
||||
|
|
|
|||
|
|
@ -5,42 +5,42 @@
|
|||
<cfscript>
|
||||
businessId = 27; // Big Dean's
|
||||
|
||||
// Categories are items with ItemParentItemID=0 AND ItemIsCollapsible=0
|
||||
// Modifier templates are items with ItemParentItemID=0 AND ItemIsCollapsible=1
|
||||
// Categories are items with ParentItemID=0 AND IsCollapsible=0
|
||||
// Modifier templates are items with ParentItemID=0 AND IsCollapsible=1
|
||||
// Menu items are children of categories
|
||||
// Modifiers are children of menu items or modifier templates
|
||||
|
||||
// Get category IDs (NOT modifier templates)
|
||||
categoryIds = queryExecute("
|
||||
SELECT ItemID
|
||||
SELECT ID
|
||||
FROM Items
|
||||
WHERE ItemBusinessID = :bizId
|
||||
AND ItemParentItemID = 0
|
||||
AND ItemIsCollapsible = 0
|
||||
WHERE BusinessID = :bizId
|
||||
AND ParentItemID = 0
|
||||
AND IsCollapsible = 0
|
||||
", { bizId: businessId }, { datasource: "payfrit" });
|
||||
|
||||
catIdList = "";
|
||||
for (cat in categoryIds) {
|
||||
catIdList = listAppend(catIdList, cat.ItemID);
|
||||
catIdList = listAppend(catIdList, cat.ID);
|
||||
}
|
||||
|
||||
// Now get actual menu items (direct children of categories)
|
||||
// Exclude items that are template options (their parent is a collapsible modifier group)
|
||||
items = queryExecute("
|
||||
SELECT i.ItemID, i.ItemName
|
||||
SELECT i.ID, i.Name
|
||||
FROM Items i
|
||||
WHERE i.ItemBusinessID = :bizId
|
||||
AND i.ItemParentItemID IN (#catIdList#)
|
||||
AND i.ItemIsCollapsible = 0
|
||||
WHERE i.BusinessID = :bizId
|
||||
AND i.ParentItemID IN (#catIdList#)
|
||||
AND i.IsCollapsible = 0
|
||||
AND NOT EXISTS (
|
||||
SELECT 1 FROM ItemTemplateLinks tl WHERE tl.TemplateItemID = i.ItemID
|
||||
SELECT 1 FROM lt_ItemID_TemplateItemID tl WHERE tl.TemplateItemID = i.ID
|
||||
)
|
||||
", { bizId: businessId }, { datasource: "payfrit" });
|
||||
|
||||
updated = [];
|
||||
|
||||
for (item in items) {
|
||||
itemName = lcase(item.ItemName);
|
||||
itemName = lcase(item.Name);
|
||||
newPrice = 0;
|
||||
|
||||
// Drinks - $3-6
|
||||
|
|
@ -99,13 +99,13 @@ for (item in items) {
|
|||
|
||||
queryExecute("
|
||||
UPDATE Items
|
||||
SET ItemPrice = :price
|
||||
SET Price = :price
|
||||
WHERE ItemID = :itemId
|
||||
", { price: newPrice, itemId: item.ItemID }, { datasource: "payfrit" });
|
||||
", { price: newPrice, itemId: item.ID }, { datasource: "payfrit" });
|
||||
|
||||
arrayAppend(updated, {
|
||||
"ItemID": item.ItemID,
|
||||
"ItemName": item.ItemName,
|
||||
"ItemID": item.ID,
|
||||
"Name": item.Name,
|
||||
"NewPrice": newPrice
|
||||
});
|
||||
}
|
||||
|
|
@ -113,15 +113,15 @@ 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("
|
||||
SELECT ItemID, ItemName
|
||||
SELECT ID, Name
|
||||
FROM Items
|
||||
WHERE ItemBusinessID = :bizId
|
||||
AND ItemParentItemID > 0
|
||||
AND ItemParentItemID NOT IN (#catIdList#)
|
||||
WHERE BusinessID = :bizId
|
||||
AND ParentItemID > 0
|
||||
AND ParentItemID NOT IN (#catIdList#)
|
||||
", { bizId: businessId }, { datasource: "payfrit" });
|
||||
|
||||
for (mod in modifiers) {
|
||||
modName = lcase(mod.ItemName);
|
||||
modName = lcase(mod.Name);
|
||||
modPrice = 0;
|
||||
|
||||
// Proteins are expensive add-ons
|
||||
|
|
@ -150,7 +150,7 @@ for (mod in modifiers) {
|
|||
|
||||
queryExecute("
|
||||
UPDATE Items
|
||||
SET ItemPrice = :price
|
||||
SET Price = :price
|
||||
WHERE ItemID = :itemId
|
||||
", { price: modPrice, itemId: mod.ItemID }, { datasource: "payfrit" });
|
||||
}
|
||||
|
|
@ -158,17 +158,17 @@ for (mod in modifiers) {
|
|||
// Reset category prices to $0 (shouldn't have prices for reporting)
|
||||
queryExecute("
|
||||
UPDATE Items
|
||||
SET ItemPrice = 0
|
||||
WHERE ItemBusinessID = :bizId
|
||||
AND ItemParentItemID = 0
|
||||
SET Price = 0
|
||||
WHERE BusinessID = :bizId
|
||||
AND ParentItemID = 0
|
||||
", { bizId: businessId }, { datasource: "payfrit" });
|
||||
|
||||
// Reset modifier group prices to $0 (only options have prices)
|
||||
queryExecute("
|
||||
UPDATE Items
|
||||
SET ItemPrice = 0
|
||||
WHERE ItemBusinessID = :bizId
|
||||
AND ItemIsCollapsible = 1
|
||||
SET Price = 0
|
||||
WHERE BusinessID = :bizId
|
||||
AND IsCollapsible = 1
|
||||
", { bizId: businessId }, { datasource: "payfrit" });
|
||||
|
||||
writeOutput(serializeJSON({
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ try {
|
|||
// Verify exists and belongs to business
|
||||
qCheck = queryExecute("
|
||||
SELECT ScheduledTaskID FROM ScheduledTaskDefinitions
|
||||
WHERE ScheduledTaskID = :id AND ScheduledTaskBusinessID = :businessID
|
||||
WHERE ID = :id AND BusinessID = :businessID
|
||||
", {
|
||||
id: { value: taskID, cfsqltype: "cf_sql_integer" },
|
||||
businessID: { value: businessID, cfsqltype: "cf_sql_integer" }
|
||||
|
|
@ -62,7 +62,7 @@ try {
|
|||
|
||||
// Hard delete the definition
|
||||
queryExecute("
|
||||
DELETE FROM ScheduledTaskDefinitions WHERE ScheduledTaskID = :id
|
||||
DELETE FROM ScheduledTaskDefinitions WHERE ID = :id
|
||||
", {
|
||||
id: { value: taskID, cfsqltype: "cf_sql_integer" }
|
||||
}, { datasource: "payfrit" });
|
||||
|
|
|
|||
|
|
@ -45,24 +45,24 @@ try {
|
|||
// Get scheduled task definitions for this business
|
||||
q = queryExecute("
|
||||
SELECT
|
||||
st.ScheduledTaskID,
|
||||
st.ScheduledTaskName as Name,
|
||||
st.ScheduledTaskCategoryID as CategoryID,
|
||||
st.ScheduledTaskTitle as Title,
|
||||
st.ScheduledTaskDetails as Details,
|
||||
st.ScheduledTaskCronExpression as CronExpression,
|
||||
COALESCE(st.ScheduledTaskScheduleType, 'cron') as ScheduleType,
|
||||
st.ScheduledTaskIntervalMinutes as IntervalMinutes,
|
||||
st.ScheduledTaskIsActive as IsActive,
|
||||
st.ScheduledTaskLastRunOn as LastRunOn,
|
||||
st.ScheduledTaskNextRunOn as NextRunOn,
|
||||
st.ScheduledTaskCreatedOn as CreatedOn,
|
||||
tc.TaskCategoryName as CategoryName,
|
||||
tc.TaskCategoryColor as CategoryColor
|
||||
st.ID,
|
||||
st.Name as Name,
|
||||
st.TaskCategoryID as CategoryID,
|
||||
st.Title as Title,
|
||||
st.Details as Details,
|
||||
st.CronExpression as CronExpression,
|
||||
COALESCE(st.ScheduleType, 'cron') as ScheduleType,
|
||||
st.IntervalMinutes as IntervalMinutes,
|
||||
st.IsActive as IsActive,
|
||||
st.LastRunOn as LastRunOn,
|
||||
st.NextRunOn as NextRunOn,
|
||||
st.CreatedOn as CreatedOn,
|
||||
tc.Name as Name,
|
||||
tc.Color as CategoryColor
|
||||
FROM ScheduledTaskDefinitions st
|
||||
LEFT JOIN TaskCategories tc ON st.ScheduledTaskCategoryID = tc.TaskCategoryID
|
||||
WHERE st.ScheduledTaskBusinessID = :businessID
|
||||
ORDER BY st.ScheduledTaskIsActive DESC, st.ScheduledTaskName
|
||||
LEFT JOIN TaskCategories tc ON st.TaskCategoryID = tc.ID
|
||||
WHERE st.BusinessID = :businessID
|
||||
ORDER BY st.IsActive DESC, st.Name
|
||||
", {
|
||||
businessID: { value: businessID, cfsqltype: "cf_sql_integer" }
|
||||
}, { datasource: "payfrit" });
|
||||
|
|
@ -70,7 +70,7 @@ try {
|
|||
scheduledTasks = [];
|
||||
for (row in q) {
|
||||
arrayAppend(scheduledTasks, {
|
||||
"ScheduledTaskID": row.ScheduledTaskID,
|
||||
"ScheduledTaskID": row.ID,
|
||||
"Name": row.Name,
|
||||
"CategoryID": isNull(row.CategoryID) ? "" : row.CategoryID,
|
||||
"Title": row.Title,
|
||||
|
|
@ -82,7 +82,7 @@ try {
|
|||
"LastRunOn": isNull(row.LastRunOn) ? "" : dateTimeFormat(row.LastRunOn, "yyyy-mm-dd HH:nn:ss"),
|
||||
"NextRunOn": isNull(row.NextRunOn) ? "" : dateTimeFormat(row.NextRunOn, "yyyy-mm-dd HH:nn:ss"),
|
||||
"CreatedOn": dateTimeFormat(row.CreatedOn, "yyyy-mm-dd HH:nn:ss"),
|
||||
"CategoryName": isNull(row.CategoryName) ? "" : row.CategoryName,
|
||||
"Name": isNull(row.Name) ? "" : row.Name,
|
||||
"CategoryColor": isNull(row.CategoryColor) ? "" : row.CategoryColor
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,11 +51,11 @@ try {
|
|||
// Get scheduled task definition
|
||||
qDef = queryExecute("
|
||||
SELECT
|
||||
ScheduledTaskTitle as Title,
|
||||
ScheduledTaskDetails as Details,
|
||||
ScheduledTaskCategoryID as CategoryID
|
||||
Title as Title,
|
||||
Details as Details,
|
||||
TaskCategoryID as CategoryID
|
||||
FROM ScheduledTaskDefinitions
|
||||
WHERE ScheduledTaskID = :id AND ScheduledTaskBusinessID = :businessID
|
||||
WHERE ID = :id AND BusinessID = :businessID
|
||||
", {
|
||||
id: { value: scheduledTaskID, cfsqltype: "cf_sql_integer" },
|
||||
businessID: { value: businessID, cfsqltype: "cf_sql_integer" }
|
||||
|
|
@ -65,11 +65,11 @@ try {
|
|||
apiAbort({ "OK": false, "ERROR": "not_found", "MESSAGE": "Scheduled task not found" });
|
||||
}
|
||||
|
||||
// Create the task (TaskClaimedByUserID=0 means unclaimed/pending)
|
||||
// Create the task (ClaimedByUserID=0 means unclaimed/pending)
|
||||
queryExecute("
|
||||
INSERT INTO Tasks (
|
||||
TaskBusinessID, TaskCategoryID, TaskTypeID,
|
||||
TaskTitle, TaskDetails, TaskAddedOn, TaskClaimedByUserID
|
||||
BusinessID, CategoryID, TaskTypeID,
|
||||
Title, Details, CreatedOn, ClaimedByUserID
|
||||
) VALUES (
|
||||
:businessID, :categoryID, :typeID,
|
||||
:title, :details, NOW(), 0
|
||||
|
|
|
|||
|
|
@ -68,26 +68,26 @@ try {
|
|||
dueTasks = queryExecute("
|
||||
SELECT
|
||||
ScheduledTaskID,
|
||||
ScheduledTaskBusinessID as BusinessID,
|
||||
ScheduledTaskCategoryID as CategoryID,
|
||||
ScheduledTaskTitle as Title,
|
||||
ScheduledTaskDetails as Details,
|
||||
ScheduledTaskCronExpression as CronExpression,
|
||||
COALESCE(ScheduledTaskScheduleType, 'cron') as ScheduleType,
|
||||
ScheduledTaskIntervalMinutes as IntervalMinutes
|
||||
BusinessID as BusinessID,
|
||||
TaskCategoryID as CategoryID,
|
||||
Title as Title,
|
||||
Details as Details,
|
||||
CronExpression as CronExpression,
|
||||
COALESCE(ScheduleType, 'cron') as ScheduleType,
|
||||
IntervalMinutes as IntervalMinutes
|
||||
FROM ScheduledTaskDefinitions
|
||||
WHERE ScheduledTaskIsActive = 1
|
||||
AND ScheduledTaskNextRunOn <= NOW()
|
||||
WHERE IsActive = 1
|
||||
AND NextRunOn <= NOW()
|
||||
", {}, { datasource: "payfrit" });
|
||||
|
||||
createdTasks = [];
|
||||
|
||||
for (task in dueTasks) {
|
||||
// Create the actual task (TaskClaimedByUserID=0 means unclaimed/pending)
|
||||
// Create the actual task (ClaimedByUserID=0 means unclaimed/pending)
|
||||
queryExecute("
|
||||
INSERT INTO Tasks (
|
||||
TaskBusinessID, TaskCategoryID, TaskTypeID,
|
||||
TaskTitle, TaskDetails, TaskAddedOn, TaskClaimedByUserID
|
||||
BusinessID, CategoryID, TaskTypeID,
|
||||
Title, Details, CreatedOn, ClaimedByUserID
|
||||
) VALUES (
|
||||
:businessID, :categoryID, :typeID,
|
||||
:title, :details, NOW(), 0
|
||||
|
|
@ -117,16 +117,16 @@ try {
|
|||
|
||||
queryExecute("
|
||||
UPDATE ScheduledTaskDefinitions SET
|
||||
ScheduledTaskLastRunOn = NOW(),
|
||||
ScheduledTaskNextRunOn = :nextRun
|
||||
WHERE ScheduledTaskID = :id
|
||||
LastRunOn = NOW(),
|
||||
NextRunOn = :nextRun
|
||||
WHERE ID = :id
|
||||
", {
|
||||
nextRun: { value: nextRun, cfsqltype: "cf_sql_timestamp", null: isNull(nextRun) },
|
||||
id: { value: task.ScheduledTaskID, cfsqltype: "cf_sql_integer" }
|
||||
id: { value: task.ID, cfsqltype: "cf_sql_integer" }
|
||||
}, { datasource: "payfrit" });
|
||||
|
||||
arrayAppend(createdTasks, {
|
||||
"ScheduledTaskID": task.ScheduledTaskID,
|
||||
"ScheduledTaskID": task.ID,
|
||||
"TaskID": qNew.newID,
|
||||
"BusinessID": task.BusinessID,
|
||||
"Title": task.Title
|
||||
|
|
|
|||
|
|
@ -158,7 +158,7 @@ try {
|
|||
// UPDATE existing
|
||||
qCheck = queryExecute("
|
||||
SELECT ScheduledTaskID FROM ScheduledTaskDefinitions
|
||||
WHERE ScheduledTaskID = :id AND ScheduledTaskBusinessID = :businessID
|
||||
WHERE ID = :id AND BusinessID = :businessID
|
||||
", {
|
||||
id: { value: taskID, cfsqltype: "cf_sql_integer" },
|
||||
businessID: { value: businessID, cfsqltype: "cf_sql_integer" }
|
||||
|
|
@ -170,16 +170,16 @@ try {
|
|||
|
||||
queryExecute("
|
||||
UPDATE ScheduledTaskDefinitions SET
|
||||
ScheduledTaskName = :name,
|
||||
ScheduledTaskTitle = :title,
|
||||
ScheduledTaskDetails = :details,
|
||||
ScheduledTaskCategoryID = :categoryID,
|
||||
ScheduledTaskCronExpression = :cron,
|
||||
ScheduledTaskScheduleType = :scheduleType,
|
||||
ScheduledTaskIntervalMinutes = :intervalMinutes,
|
||||
ScheduledTaskIsActive = :isActive,
|
||||
ScheduledTaskNextRunOn = :nextRun
|
||||
WHERE ScheduledTaskID = :id
|
||||
Name = :name,
|
||||
Title = :title,
|
||||
Details = :details,
|
||||
TaskCategoryID = :categoryID,
|
||||
CronExpression = :cron,
|
||||
ScheduleType = :scheduleType,
|
||||
IntervalMinutes = :intervalMinutes,
|
||||
IsActive = :isActive,
|
||||
NextRunOn = :nextRun
|
||||
WHERE ID = :id
|
||||
", {
|
||||
name: { value: taskName, cfsqltype: "cf_sql_varchar" },
|
||||
title: { value: taskTitle, cfsqltype: "cf_sql_varchar" },
|
||||
|
|
@ -204,10 +204,10 @@ try {
|
|||
// INSERT new
|
||||
queryExecute("
|
||||
INSERT INTO ScheduledTaskDefinitions (
|
||||
ScheduledTaskBusinessID, ScheduledTaskName, ScheduledTaskTitle,
|
||||
ScheduledTaskDetails, ScheduledTaskCategoryID,
|
||||
ScheduledTaskCronExpression, ScheduledTaskScheduleType, ScheduledTaskIntervalMinutes,
|
||||
ScheduledTaskIsActive, ScheduledTaskNextRunOn
|
||||
BusinessID, Name, Title,
|
||||
Details, TaskCategoryID,
|
||||
CronExpression, ScheduleType, IntervalMinutes,
|
||||
IsActive, NextRunOn
|
||||
) VALUES (
|
||||
:businessID, :name, :title, :details, :categoryID, :cron, :scheduleType, :intervalMinutes, :isActive, :nextRun
|
||||
)
|
||||
|
|
@ -230,8 +230,8 @@ try {
|
|||
// Create the first task immediately
|
||||
queryExecute("
|
||||
INSERT INTO Tasks (
|
||||
TaskBusinessID, TaskCategoryID, TaskTypeID,
|
||||
TaskTitle, TaskDetails, TaskAddedOn, TaskClaimedByUserID
|
||||
BusinessID, CategoryID, TaskTypeID,
|
||||
Title, Details, CreatedOn, ClaimedByUserID
|
||||
) VALUES (
|
||||
:businessID, :categoryID, :typeID,
|
||||
:title, :details, NOW(), 0
|
||||
|
|
@ -262,9 +262,9 @@ try {
|
|||
|
||||
queryExecute("
|
||||
UPDATE ScheduledTaskDefinitions
|
||||
SET ScheduledTaskLastRunOn = NOW(),
|
||||
ScheduledTaskNextRunOn = :nextRun
|
||||
WHERE ScheduledTaskID = :id
|
||||
SET LastRunOn = NOW(),
|
||||
NextRunOn = :nextRun
|
||||
WHERE ID = :id
|
||||
", {
|
||||
nextRun: { value: actualNextRun, cfsqltype: "cf_sql_timestamp", null: isNull(actualNextRun) },
|
||||
id: { value: newScheduledTaskID, cfsqltype: "cf_sql_integer" }
|
||||
|
|
|
|||
|
|
@ -15,23 +15,23 @@ try {
|
|||
// Create ScheduledTaskDefinitions table
|
||||
queryExecute("
|
||||
CREATE TABLE IF NOT EXISTS ScheduledTaskDefinitions (
|
||||
ScheduledTaskID INT AUTO_INCREMENT PRIMARY KEY,
|
||||
ScheduledTaskBusinessID INT NOT NULL,
|
||||
ScheduledTaskName VARCHAR(100) NOT NULL,
|
||||
ScheduledTaskCategoryID INT NULL,
|
||||
ScheduledTaskTypeID INT NULL,
|
||||
ScheduledTaskTitle VARCHAR(255) NOT NULL,
|
||||
ScheduledTaskDetails TEXT NULL,
|
||||
ScheduledTaskCronExpression VARCHAR(100) NOT NULL,
|
||||
ScheduledTaskScheduleType VARCHAR(20) DEFAULT 'cron',
|
||||
ScheduledTaskIntervalMinutes INT NULL,
|
||||
ScheduledTaskIsActive BIT(1) DEFAULT b'1',
|
||||
ScheduledTaskLastRunOn DATETIME NULL,
|
||||
ScheduledTaskNextRunOn DATETIME NULL,
|
||||
ScheduledTaskCreatedOn DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
ScheduledTaskCreatedByUserID INT NULL,
|
||||
INDEX idx_business (ScheduledTaskBusinessID),
|
||||
INDEX idx_active_next (ScheduledTaskIsActive, ScheduledTaskNextRunOn)
|
||||
ID INT AUTO_INCREMENT PRIMARY KEY,
|
||||
BusinessID INT NOT NULL,
|
||||
Name VARCHAR(100) NOT NULL,
|
||||
TaskCategoryID INT NULL,
|
||||
TaskTypeID INT NULL,
|
||||
Title VARCHAR(255) NOT NULL,
|
||||
Details TEXT NULL,
|
||||
CronExpression VARCHAR(100) NOT NULL,
|
||||
ScheduleType VARCHAR(20) DEFAULT 'cron',
|
||||
IntervalMinutes INT NULL,
|
||||
IsActive BIT(1) DEFAULT b'1',
|
||||
LastRunOn DATETIME NULL,
|
||||
NextRunOn DATETIME NULL,
|
||||
CreatedOn DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
CreatedByUserID INT NULL,
|
||||
INDEX idx_business (BusinessID),
|
||||
INDEX idx_active_next (IsActive, NextRunOn)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
|
||||
", [], { datasource: "payfrit" });
|
||||
|
||||
|
|
@ -39,7 +39,7 @@ try {
|
|||
try {
|
||||
queryExecute("
|
||||
ALTER TABLE ScheduledTaskDefinitions
|
||||
ADD COLUMN ScheduledTaskScheduleType VARCHAR(20) DEFAULT 'cron' AFTER ScheduledTaskCronExpression
|
||||
ADD COLUMN ScheduleType VARCHAR(20) DEFAULT 'cron' AFTER CronExpression
|
||||
", [], { datasource: "payfrit" });
|
||||
} catch (any e) {
|
||||
// Column likely already exists
|
||||
|
|
@ -48,7 +48,7 @@ try {
|
|||
try {
|
||||
queryExecute("
|
||||
ALTER TABLE ScheduledTaskDefinitions
|
||||
ADD COLUMN ScheduledTaskIntervalMinutes INT NULL AFTER ScheduledTaskScheduleType
|
||||
ADD COLUMN IntervalMinutes INT NULL AFTER ScheduleType
|
||||
", [], { datasource: "payfrit" });
|
||||
} catch (any e) {
|
||||
// Column likely already exists
|
||||
|
|
|
|||
|
|
@ -99,11 +99,11 @@ try {
|
|||
|
||||
// Verify exists and get cron expression and schedule type
|
||||
qCheck = queryExecute("
|
||||
SELECT ScheduledTaskID, ScheduledTaskCronExpression as CronExpression,
|
||||
COALESCE(ScheduledTaskScheduleType, 'cron') as ScheduleType,
|
||||
ScheduledTaskIntervalMinutes as IntervalMinutes
|
||||
SELECT ScheduledTaskID, CronExpression as CronExpression,
|
||||
COALESCE(ScheduleType, 'cron') as ScheduleType,
|
||||
IntervalMinutes as IntervalMinutes
|
||||
FROM ScheduledTaskDefinitions
|
||||
WHERE ScheduledTaskID = :id AND ScheduledTaskBusinessID = :businessID
|
||||
WHERE ID = :id AND BusinessID = :businessID
|
||||
", {
|
||||
id: { value: taskID, cfsqltype: "cf_sql_integer" },
|
||||
businessID: { value: businessID, cfsqltype: "cf_sql_integer" }
|
||||
|
|
@ -123,16 +123,16 @@ try {
|
|||
// Cron-based: use cron parser
|
||||
nextRunOn = calculateNextRun(qCheck.CronExpression);
|
||||
}
|
||||
nextRunUpdate = ", ScheduledTaskNextRunOn = :nextRun";
|
||||
nextRunUpdate = ", NextRunOn = :nextRun";
|
||||
}
|
||||
|
||||
// Update status
|
||||
if (isActive) {
|
||||
queryExecute("
|
||||
UPDATE ScheduledTaskDefinitions SET
|
||||
ScheduledTaskIsActive = :isActive,
|
||||
ScheduledTaskNextRunOn = :nextRun
|
||||
WHERE ScheduledTaskID = :id
|
||||
IsActive = :isActive,
|
||||
NextRunOn = :nextRun
|
||||
WHERE ID = :id
|
||||
", {
|
||||
isActive: { value: isActive, cfsqltype: "cf_sql_bit" },
|
||||
nextRun: { value: nextRunOn, cfsqltype: "cf_sql_timestamp" },
|
||||
|
|
@ -140,8 +140,8 @@ try {
|
|||
}, { datasource: "payfrit" });
|
||||
} else {
|
||||
queryExecute("
|
||||
UPDATE ScheduledTaskDefinitions SET ScheduledTaskIsActive = :isActive
|
||||
WHERE ScheduledTaskID = :id
|
||||
UPDATE ScheduledTaskDefinitions SET IsActive = :isActive
|
||||
WHERE ID = :id
|
||||
", {
|
||||
isActive: { value: isActive, cfsqltype: "cf_sql_bit" },
|
||||
id: { value: taskID, cfsqltype: "cf_sql_integer" }
|
||||
|
|
|
|||
|
|
@ -21,8 +21,8 @@ if (businessId <= 0 || userId <= 0) {
|
|||
try {
|
||||
// Update employee record
|
||||
queryExecute("
|
||||
UPDATE lt_Users_Businesses_Employees
|
||||
SET EmployeeIsActive = ?
|
||||
UPDATE Employees
|
||||
SET IsActive = ?
|
||||
WHERE BusinessID = ? AND UserID = ?
|
||||
", [
|
||||
{ value: isActive, cfsqltype: "cf_sql_bit" },
|
||||
|
|
@ -32,12 +32,12 @@ try {
|
|||
|
||||
// Get updated record
|
||||
q = queryExecute("
|
||||
SELECT e.EmployeeID, e.BusinessID, e.UserID, e.EmployeeStatusID,
|
||||
CAST(e.EmployeeIsActive AS UNSIGNED) AS EmployeeIsActive,
|
||||
b.BusinessName, u.UserFirstName, u.UserLastName
|
||||
FROM lt_Users_Businesses_Employees e
|
||||
JOIN Businesses b ON e.BusinessID = b.BusinessID
|
||||
JOIN Users u ON e.UserID = u.UserID
|
||||
SELECT e.ID, e.BusinessID, e.UserID, e.StatusID,
|
||||
CAST(e.IsActive AS UNSIGNED) AS IsActive,
|
||||
b.Name, u.FirstName, u.LastName
|
||||
FROM Employees e
|
||||
JOIN Businesses b ON e.BusinessID = b.ID
|
||||
JOIN Users u ON e.UserID = u.ID
|
||||
WHERE e.BusinessID = ? AND e.UserID = ?
|
||||
", [
|
||||
{ value: businessId, cfsqltype: "cf_sql_integer" },
|
||||
|
|
@ -49,13 +49,13 @@ try {
|
|||
"OK": true,
|
||||
"MESSAGE": "Employee updated",
|
||||
"EMPLOYEE": {
|
||||
"EmployeeID": q.EmployeeID,
|
||||
"EmployeeID": q.ID,
|
||||
"BusinessID": q.BusinessID,
|
||||
"BusinessName": q.BusinessName,
|
||||
"Name": q.Name,
|
||||
"UserID": q.UserID,
|
||||
"UserName": trim(q.UserFirstName & " " & q.UserLastName),
|
||||
"StatusID": q.EmployeeStatusID,
|
||||
"IsActive": q.EmployeeIsActive
|
||||
"UserName": trim(q.FirstName & " " & q.LastName),
|
||||
"StatusID": q.StatusID,
|
||||
"IsActive": q.IsActive
|
||||
}
|
||||
}));
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -7,11 +7,11 @@ response = { "OK": false };
|
|||
|
||||
try {
|
||||
queryExecute("
|
||||
UPDATE Businesses SET BusinessHeaderImageExtension = 'jpg' WHERE BusinessID = 37
|
||||
UPDATE Businesses SET HeaderImageExtension = 'jpg' WHERE ID = 37
|
||||
", {}, { datasource: "payfrit" });
|
||||
|
||||
response.OK = true;
|
||||
response.message = "Set BusinessHeaderImageExtension to 'jpg' for business 37";
|
||||
response.message = "Set HeaderImageExtension to 'jpg' for business 37";
|
||||
} catch (any e) {
|
||||
response.error = e.message;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
<cfscript>
|
||||
/**
|
||||
* Setup Lazy Daisy Beacons
|
||||
* Creates a beacon for each service point and links them
|
||||
* Creates a beacon for each service point and assigns them
|
||||
*/
|
||||
response = { "OK": false, "steps": [] };
|
||||
|
||||
|
|
@ -14,10 +14,10 @@ try {
|
|||
|
||||
// Get all service points for Lazy Daisy
|
||||
qServicePoints = queryExecute("
|
||||
SELECT ServicePointID, ServicePointName
|
||||
SELECT ID, Name
|
||||
FROM ServicePoints
|
||||
WHERE ServicePointBusinessID = :bizID AND ServicePointIsActive = 1
|
||||
ORDER BY ServicePointID
|
||||
WHERE BusinessID = :bizID AND IsActive = 1
|
||||
ORDER BY SortOrder, ID
|
||||
", { bizID: lazyDaisyID }, { datasource: "payfrit" });
|
||||
|
||||
response.steps.append("Found " & qServicePoints.recordCount & " service points for Lazy Daisy");
|
||||
|
|
@ -25,20 +25,20 @@ try {
|
|||
// Create a beacon for each service point
|
||||
beaconsCreated = 0;
|
||||
for (sp in qServicePoints) {
|
||||
beaconName = "Beacon - " & sp.ServicePointName;
|
||||
beaconName = "Beacon - " & sp.Name;
|
||||
|
||||
// Check if beacon already exists for this business with this name
|
||||
qExisting = queryExecute("
|
||||
SELECT BeaconID FROM Beacons
|
||||
WHERE BeaconBusinessID = :bizId AND BeaconName = :name
|
||||
SELECT ID FROM Beacons
|
||||
WHERE BusinessID = :bizId AND Name = :name
|
||||
", { bizId: lazyDaisyID, name: beaconName }, { datasource: "payfrit" });
|
||||
|
||||
if (qExisting.recordCount == 0) {
|
||||
// Generate a unique UUID for this beacon (32 hex chars, no dashes)
|
||||
beaconUUID = "PAYFRIT00037" & numberFormat(sp.ServicePointID, "0000000000000000000");
|
||||
beaconUUID = "PAYFRIT00037" & numberFormat(sp.ID, "0000000000000000000");
|
||||
|
||||
queryExecute("
|
||||
INSERT INTO Beacons (BeaconBusinessID, BeaconName, BeaconUUID, BeaconIsActive)
|
||||
INSERT INTO Beacons (BusinessID, Name, UUID, IsActive)
|
||||
VALUES (:bizId, :name, :uuid, 1)
|
||||
", {
|
||||
bizId: lazyDaisyID,
|
||||
|
|
@ -49,18 +49,18 @@ try {
|
|||
qNewBeacon = queryExecute("SELECT LAST_INSERT_ID() as id", {}, { datasource: "payfrit" });
|
||||
newBeaconId = qNewBeacon.id;
|
||||
|
||||
// Create assignment to service point
|
||||
// Assign beacon directly to service point
|
||||
queryExecute("
|
||||
INSERT INTO lt_Beacon_Businesses_ServicePoints
|
||||
(BeaconID, BusinessID, ServicePointID, lt_Beacon_Businesses_ServicePointAssignedByUserID)
|
||||
VALUES (:beaconId, :bizId, :spId, 1)
|
||||
UPDATE ServicePoints
|
||||
SET BeaconID = :beaconId, AssignedByUserID = 1
|
||||
WHERE ID = :spId AND BusinessID = :bizId
|
||||
", {
|
||||
beaconId: newBeaconId,
|
||||
bizId: lazyDaisyID,
|
||||
spId: sp.ServicePointID
|
||||
spId: sp.ID
|
||||
}, { datasource: "payfrit" });
|
||||
|
||||
response.steps.append("Created beacon '" & beaconName & "' (ID: " & newBeaconId & ") -> " & sp.ServicePointName);
|
||||
response.steps.append("Created beacon '" & beaconName & "' (ID: " & newBeaconId & ") -> " & sp.Name);
|
||||
beaconsCreated++;
|
||||
} else {
|
||||
response.steps.append("Beacon '" & beaconName & "' already exists, skipping");
|
||||
|
|
@ -69,13 +69,14 @@ try {
|
|||
|
||||
// Get final status
|
||||
qFinal = queryExecute("
|
||||
SELECT lt.BeaconID, b.BeaconUUID, b.BeaconName, lt.BusinessID, biz.BusinessName, lt.ServicePointID, sp.ServicePointName
|
||||
FROM lt_Beacon_Businesses_ServicePoints lt
|
||||
JOIN Beacons b ON b.BeaconID = lt.BeaconID
|
||||
JOIN Businesses biz ON biz.BusinessID = lt.BusinessID
|
||||
LEFT JOIN ServicePoints sp ON sp.ServicePointID = lt.ServicePointID
|
||||
WHERE lt.BusinessID = :bizId
|
||||
ORDER BY sp.ServicePointName
|
||||
SELECT sp.ID AS ServicePointID, sp.BeaconID, sp.BusinessID,
|
||||
b.Name AS BeaconName, b.UUID, sp.Name AS ServicePointName,
|
||||
biz.Name AS BusinessName
|
||||
FROM ServicePoints sp
|
||||
JOIN Beacons b ON b.ID = sp.BeaconID
|
||||
JOIN Businesses biz ON biz.ID = sp.BusinessID
|
||||
WHERE sp.BusinessID = :bizId AND sp.BeaconID IS NOT NULL
|
||||
ORDER BY sp.Name
|
||||
", { bizId: lazyDaisyID }, { datasource: "payfrit" });
|
||||
|
||||
beacons = [];
|
||||
|
|
@ -83,8 +84,9 @@ try {
|
|||
arrayAppend(beacons, {
|
||||
"BeaconID": qFinal.BeaconID[i],
|
||||
"BeaconName": qFinal.BeaconName[i],
|
||||
"UUID": qFinal.BeaconUUID[i],
|
||||
"UUID": qFinal.UUID[i],
|
||||
"BusinessName": qFinal.BusinessName[i],
|
||||
"ServicePointID": qFinal.ServicePointID[i],
|
||||
"ServicePointName": qFinal.ServicePointName[i]
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,19 +13,19 @@ try {
|
|||
// Hours: Mon-Thu: 11am-10pm, Fri-Sat: 11am-11pm, Sun: 11am-10pm
|
||||
|
||||
// Get California StateID
|
||||
qState = queryExecute("SELECT tt_StateID FROM tt_States WHERE tt_StateAbbreviation = 'CA' LIMIT 1");
|
||||
qState = queryExecute("SELECT tt_StateID FROM tt_States WHERE Abbreviation = 'CA' LIMIT 1");
|
||||
stateId = qState.recordCount > 0 ? qState.tt_StateID : 5; // Default to 5 if not found
|
||||
|
||||
// Check if Big Dean's already has an address
|
||||
existingAddr = queryExecute("
|
||||
SELECT AddressID FROM Addresses
|
||||
WHERE AddressBusinessID = :bizId AND AddressUserID = 0
|
||||
SELECT ID FROM Addresses
|
||||
WHERE BusinessID = :bizId AND UserID = 0
|
||||
", { bizId: businessId });
|
||||
|
||||
if (existingAddr.recordCount == 0) {
|
||||
// Insert new address
|
||||
queryExecute("
|
||||
INSERT INTO Addresses (AddressUserID, AddressBusinessID, AddressTypeID, AddressLine1, AddressCity, AddressStateID, AddressZIPCode, AddressIsDeleted, AddressAddedOn)
|
||||
INSERT INTO Addresses (UserID, BusinessID, AddressTypeID, Line1, City, StateID, ZIPCode, IsDeleted, AddedOn)
|
||||
VALUES (0, :bizId, '2', :line1, :city, :stateId, :zip, 0, NOW())
|
||||
", {
|
||||
bizId: businessId,
|
||||
|
|
@ -39,8 +39,8 @@ try {
|
|||
// Update existing address
|
||||
queryExecute("
|
||||
UPDATE Addresses
|
||||
SET AddressLine1 = :line1, AddressCity = :city, AddressStateID = :stateId, AddressZIPCode = :zip
|
||||
WHERE AddressBusinessID = :bizId AND AddressUserID = 0
|
||||
SET Line1 = :line1, City = :city, StateID = :stateId, ZIPCode = :zip
|
||||
WHERE BusinessID = :bizId AND UserID = 0
|
||||
", {
|
||||
bizId: businessId,
|
||||
line1: "1615 Ocean Front Walk",
|
||||
|
|
@ -53,7 +53,7 @@ try {
|
|||
|
||||
// Check existing hours for this business
|
||||
existingHours = queryExecute("
|
||||
SELECT COUNT(*) as cnt FROM Hours WHERE HoursBusinessID = :bizId
|
||||
SELECT COUNT(*) as cnt FROM Hours WHERE BusinessID = :bizId
|
||||
", { bizId: businessId });
|
||||
|
||||
if (existingHours.cnt == 0) {
|
||||
|
|
@ -64,39 +64,39 @@ try {
|
|||
// Sun: 11am-10pm (day 1)
|
||||
|
||||
// Sunday (1): 11am-10pm
|
||||
queryExecute("INSERT INTO Hours (HoursBusinessID, HoursDayID, HoursOpenTime, HoursClosingTime) VALUES (:bizId, 1, '11:00:00', '22:00:00')", { bizId: businessId });
|
||||
queryExecute("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 (HoursBusinessID, HoursDayID, HoursOpenTime, HoursClosingTime) VALUES (:bizId, 2, '11:00:00', '22:00:00')", { bizId: businessId });
|
||||
queryExecute("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 (HoursBusinessID, HoursDayID, HoursOpenTime, HoursClosingTime) VALUES (:bizId, 3, '11:00:00', '22:00:00')", { bizId: businessId });
|
||||
queryExecute("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 (HoursBusinessID, HoursDayID, HoursOpenTime, HoursClosingTime) VALUES (:bizId, 4, '11:00:00', '22:00:00')", { bizId: businessId });
|
||||
queryExecute("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 (HoursBusinessID, HoursDayID, HoursOpenTime, HoursClosingTime) VALUES (:bizId, 5, '11:00:00', '22:00:00')", { bizId: businessId });
|
||||
queryExecute("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 (HoursBusinessID, HoursDayID, HoursOpenTime, HoursClosingTime) VALUES (:bizId, 6, '11:00:00', '23:00:00')", { bizId: businessId });
|
||||
queryExecute("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 (HoursBusinessID, HoursDayID, HoursOpenTime, HoursClosingTime) VALUES (:bizId, 7, '11:00:00', '23:00:00')", { bizId: businessId });
|
||||
queryExecute("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 HoursOpenTime = '11:00:00', HoursClosingTime = '22:00:00' WHERE HoursBusinessID = :bizId AND HoursDayID IN (1, 2, 3, 4, 5)", { bizId: businessId });
|
||||
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 });
|
||||
// Fri-Sat: 11am-11pm
|
||||
queryExecute("UPDATE Hours SET HoursOpenTime = '11:00:00', HoursClosingTime = '23:00:00' WHERE HoursBusinessID = :bizId AND HoursDayID IN (6, 7)", { bizId: businessId });
|
||||
queryExecute("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 BusinessPhone = :phone WHERE BusinessID = :bizId", {
|
||||
queryExecute("UPDATE Businesses SET Phone = :phone WHERE ID = :bizId", {
|
||||
phone: "(310) 393-2666",
|
||||
bizId: businessId
|
||||
});
|
||||
|
|
@ -107,35 +107,35 @@ try {
|
|||
|
||||
// Verify the data
|
||||
address = queryExecute("
|
||||
SELECT a.*, s.tt_StateAbbreviation
|
||||
SELECT a.*, s.Abbreviation
|
||||
FROM Addresses a
|
||||
LEFT JOIN tt_States s ON s.tt_StateID = a.AddressStateID
|
||||
WHERE a.AddressBusinessID = :bizId AND a.AddressUserID = 0
|
||||
LEFT JOIN tt_States s ON s.ID = a.StateID
|
||||
WHERE a.BusinessID = :bizId AND a.UserID = 0
|
||||
", { bizId: businessId });
|
||||
|
||||
hours = queryExecute("
|
||||
SELECT h.*, d.tt_DayName
|
||||
FROM Hours h
|
||||
JOIN tt_Days d ON d.tt_DayID = h.HoursDayID
|
||||
WHERE h.HoursBusinessID = :bizId
|
||||
ORDER BY h.HoursDayID
|
||||
JOIN tt_Days d ON d.ID = h.DayID
|
||||
WHERE h.BusinessID = :bizId
|
||||
ORDER BY h.DayID
|
||||
", { bizId: businessId });
|
||||
|
||||
response["OK"] = true;
|
||||
response["BUSINESS_ID"] = businessId;
|
||||
response["ADDRESS"] = address.recordCount > 0 ? {
|
||||
"line1": address.AddressLine1,
|
||||
"city": address.AddressCity,
|
||||
"state": address.tt_StateAbbreviation,
|
||||
"zip": address.AddressZIPCode
|
||||
"line1": address.Line1,
|
||||
"city": address.City,
|
||||
"state": address.Abbreviation,
|
||||
"zip": address.ZIPCode
|
||||
} : "not found";
|
||||
|
||||
hoursArr = [];
|
||||
for (h in hours) {
|
||||
arrayAppend(hoursArr, {
|
||||
"day": h.tt_DayName,
|
||||
"open": timeFormat(h.HoursOpenTime, "h:mm tt"),
|
||||
"close": timeFormat(h.HoursClosingTime, "h:mm tt")
|
||||
"open": timeFormat(h.OpenTime, "h:mm tt"),
|
||||
"close": timeFormat(h.ClosingTime, "h:mm tt")
|
||||
});
|
||||
}
|
||||
response["HOURS"] = hoursArr;
|
||||
|
|
|
|||
|
|
@ -9,19 +9,19 @@ response = { "OK": false };
|
|||
try {
|
||||
// Check if Big Dean's already has stations
|
||||
existing = queryExecute("
|
||||
SELECT COUNT(*) as cnt FROM Stations WHERE StationBusinessID = :bizId
|
||||
SELECT COUNT(*) as cnt FROM Stations WHERE BusinessID = :bizId
|
||||
", { bizId: businessId });
|
||||
|
||||
if (existing.cnt == 0) {
|
||||
// Insert Kitchen station
|
||||
queryExecute("
|
||||
INSERT INTO Stations (StationBusinessID, StationName, StationColor, StationSortOrder, StationIsActive)
|
||||
INSERT INTO Stations (BusinessID, Name, Color, SortOrder, IsActive)
|
||||
VALUES (:bizId, 'Kitchen', :color1, 1, 1)
|
||||
", { bizId: businessId, color1: "##FF5722" });
|
||||
|
||||
// Insert Bar station
|
||||
queryExecute("
|
||||
INSERT INTO Stations (StationBusinessID, StationName, StationColor, StationSortOrder, StationIsActive)
|
||||
INSERT INTO Stations (BusinessID, Name, Color, SortOrder, IsActive)
|
||||
VALUES (:bizId, 'Bar', :color2, 2, 1)
|
||||
", { bizId: businessId, color2: "##2196F3" });
|
||||
|
||||
|
|
@ -32,18 +32,18 @@ try {
|
|||
|
||||
// Get current stations
|
||||
stations = queryExecute("
|
||||
SELECT StationID, StationName, StationColor, StationSortOrder
|
||||
SELECT ID, Name, Color, SortOrder
|
||||
FROM Stations
|
||||
WHERE StationBusinessID = :bizId AND StationIsActive = 1
|
||||
ORDER BY StationSortOrder
|
||||
WHERE BusinessID = :bizId AND IsActive = 1
|
||||
ORDER BY SortOrder
|
||||
", { bizId: businessId });
|
||||
|
||||
stationArr = [];
|
||||
for (s in stations) {
|
||||
arrayAppend(stationArr, {
|
||||
"StationID": s.StationID,
|
||||
"StationName": s.StationName,
|
||||
"StationColor": s.StationColor
|
||||
"StationID": s.ID,
|
||||
"Name": s.Name,
|
||||
"Color": s.Color
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,67 +9,62 @@ try {
|
|||
lazyDaisyID = 37;
|
||||
|
||||
// Get all beacons
|
||||
qBeacons = queryExecute("SELECT BeaconID, BeaconUUID FROM Beacons", {}, { datasource: "payfrit" });
|
||||
qBeacons = queryExecute("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("
|
||||
SELECT ServicePointID FROM ServicePoints
|
||||
WHERE ServicePointBusinessID = :bizID AND ServicePointName = 'Table 1'
|
||||
SELECT ID FROM ServicePoints
|
||||
WHERE BusinessID = :bizID AND Name = 'Table 1'
|
||||
", { bizID: lazyDaisyID }, { datasource: "payfrit" });
|
||||
|
||||
if (qSP.recordCount == 0) {
|
||||
queryExecute("
|
||||
INSERT INTO ServicePoints (ServicePointBusinessID, ServicePointName, ServicePointTypeID)
|
||||
VALUES (:bizID, 'Table 1', 1)
|
||||
INSERT INTO ServicePoints (BusinessID, Name)
|
||||
VALUES (:bizID, 'Table 1')
|
||||
", { bizID: lazyDaisyID }, { datasource: "payfrit" });
|
||||
qSP = queryExecute("SELECT LAST_INSERT_ID() as id", {}, { datasource: "payfrit" });
|
||||
servicePointID = qSP.id;
|
||||
response.steps.append("Created service point 'Table 1' (ID: " & servicePointID & ")");
|
||||
} else {
|
||||
servicePointID = qSP.ServicePointID;
|
||||
servicePointID = qSP.ID;
|
||||
response.steps.append("Found existing service point 'Table 1' (ID: " & servicePointID & ")");
|
||||
}
|
||||
|
||||
// Map all beacons to Lazy Daisy with Table 1
|
||||
// Assign all beacons to the Table 1 service point
|
||||
for (i = 1; i <= qBeacons.recordCount; i++) {
|
||||
beaconID = qBeacons.BeaconID[i];
|
||||
beaconID = qBeacons.ID[i];
|
||||
|
||||
// Check if mapping exists
|
||||
qMap = queryExecute("
|
||||
SELECT * FROM lt_Beacon_Businesses_ServicePoints WHERE BeaconID = :beaconID
|
||||
// Unassign this beacon from any other service point first
|
||||
queryExecute("
|
||||
UPDATE ServicePoints SET BeaconID = NULL, AssignedByUserID = NULL
|
||||
WHERE BeaconID = :beaconID
|
||||
", { beaconID: beaconID }, { datasource: "payfrit" });
|
||||
|
||||
if (qMap.recordCount == 0) {
|
||||
// Assign beacon to Table 1 service point
|
||||
queryExecute("
|
||||
INSERT INTO lt_Beacon_Businesses_ServicePoints (BeaconID, BusinessID, ServicePointID)
|
||||
VALUES (:beaconID, :bizID, :spID)
|
||||
UPDATE ServicePoints SET BeaconID = :beaconID, AssignedByUserID = 1
|
||||
WHERE ID = :spID AND BusinessID = :bizID
|
||||
", { beaconID: beaconID, bizID: lazyDaisyID, spID: servicePointID }, { datasource: "payfrit" });
|
||||
response.steps.append("Created mapping for beacon " & beaconID);
|
||||
} else {
|
||||
queryExecute("
|
||||
UPDATE lt_Beacon_Businesses_ServicePoints
|
||||
SET BusinessID = :bizID, ServicePointID = :spID
|
||||
WHERE BeaconID = :beaconID
|
||||
", { beaconID: beaconID, bizID: lazyDaisyID, spID: servicePointID }, { datasource: "payfrit" });
|
||||
response.steps.append("Updated mapping for beacon " & beaconID);
|
||||
}
|
||||
response.steps.append("Assigned beacon " & beaconID & " to Table 1");
|
||||
}
|
||||
|
||||
// Get final status
|
||||
qFinal = queryExecute("
|
||||
SELECT lt.BeaconID, b.BeaconUUID, lt.BusinessID, biz.BusinessName, lt.ServicePointID, sp.ServicePointName
|
||||
FROM lt_Beacon_Businesses_ServicePoints lt
|
||||
JOIN Beacons b ON b.BeaconID = lt.BeaconID
|
||||
JOIN Businesses biz ON biz.BusinessID = lt.BusinessID
|
||||
LEFT JOIN ServicePoints sp ON sp.ServicePointID = lt.ServicePointID
|
||||
SELECT sp.ID AS ServicePointID, sp.BeaconID, sp.BusinessID,
|
||||
b.Name AS BeaconName, b.UUID, sp.Name AS ServicePointName,
|
||||
biz.Name AS BusinessName
|
||||
FROM ServicePoints sp
|
||||
JOIN Beacons b ON b.ID = sp.BeaconID
|
||||
JOIN Businesses biz ON biz.ID = sp.BusinessID
|
||||
WHERE sp.BeaconID IS NOT NULL
|
||||
", {}, { datasource: "payfrit" });
|
||||
|
||||
beacons = [];
|
||||
for (i = 1; i <= qFinal.recordCount; i++) {
|
||||
arrayAppend(beacons, {
|
||||
"BeaconID": qFinal.BeaconID[i],
|
||||
"UUID": qFinal.BeaconUUID[i],
|
||||
"UUID": qFinal.UUID[i],
|
||||
"BusinessID": qFinal.BusinessID[i],
|
||||
"BusinessName": qFinal.BusinessName[i],
|
||||
"ServicePointID": qFinal.ServicePointID[i],
|
||||
|
|
|
|||
|
|
@ -11,32 +11,32 @@
|
|||
<cfscript>
|
||||
/**
|
||||
* Setup Modifier Templates system
|
||||
* 1. Add ItemIsModifierTemplate column to Items
|
||||
* 2. Create ItemTemplateLinks table
|
||||
* 1. Add IsModifierTemplate column to Items
|
||||
* 2. Create lt_ItemID_TemplateItemID table
|
||||
*/
|
||||
|
||||
response = { "OK": false, "steps": [] };
|
||||
|
||||
try {
|
||||
// Step 1: Add ItemIsModifierTemplate column if it doesn't exist
|
||||
// Step 1: Add IsModifierTemplate column if it doesn't exist
|
||||
try {
|
||||
queryExecute("
|
||||
ALTER TABLE Items ADD COLUMN ItemIsModifierTemplate TINYINT(1) DEFAULT 0
|
||||
ALTER TABLE Items ADD COLUMN IsModifierTemplate TINYINT(1) DEFAULT 0
|
||||
", {}, { datasource: "payfrit" });
|
||||
arrayAppend(response.steps, "Added ItemIsModifierTemplate column");
|
||||
arrayAppend(response.steps, "Added IsModifierTemplate column");
|
||||
} catch (any e) {
|
||||
if (findNoCase("Duplicate column", e.message)) {
|
||||
arrayAppend(response.steps, "ItemIsModifierTemplate column already exists");
|
||||
arrayAppend(response.steps, "IsModifierTemplate column already exists");
|
||||
} else {
|
||||
arrayAppend(response.steps, "Error adding column: " & e.message);
|
||||
}
|
||||
}
|
||||
|
||||
// Step 2: Create ItemTemplateLinks table if it doesn't exist
|
||||
// Step 2: Create lt_ItemID_TemplateItemID table if it doesn't exist
|
||||
try {
|
||||
queryExecute("
|
||||
CREATE TABLE IF NOT EXISTS ItemTemplateLinks (
|
||||
LinkID INT AUTO_INCREMENT PRIMARY KEY,
|
||||
CREATE TABLE IF NOT EXISTS lt_ItemID_TemplateItemID (
|
||||
ID INT AUTO_INCREMENT PRIMARY KEY,
|
||||
ItemID INT NOT NULL,
|
||||
TemplateItemID INT NOT NULL,
|
||||
SortOrder INT DEFAULT 0,
|
||||
|
|
@ -45,9 +45,9 @@ try {
|
|||
INDEX idx_template (TemplateItemID)
|
||||
)
|
||||
", {}, { datasource: "payfrit" });
|
||||
arrayAppend(response.steps, "Created ItemTemplateLinks table");
|
||||
arrayAppend(response.steps, "Created lt_ItemID_TemplateItemID table");
|
||||
} catch (any e) {
|
||||
arrayAppend(response.steps, "ItemTemplateLinks: " & e.message);
|
||||
arrayAppend(response.steps, "lt_ItemID_TemplateItemID: " & e.message);
|
||||
}
|
||||
|
||||
response["OK"] = true;
|
||||
|
|
|
|||
|
|
@ -13,20 +13,20 @@
|
|||
<cfset queryExecute("
|
||||
CREATE TABLE IF NOT EXISTS Stations (
|
||||
StationID INT AUTO_INCREMENT PRIMARY KEY,
|
||||
StationBusinessID INT NOT NULL,
|
||||
StationName VARCHAR(100) NOT NULL,
|
||||
StationColor VARCHAR(7) DEFAULT '##666666',
|
||||
StationSortOrder INT DEFAULT 0,
|
||||
StationIsActive TINYINT(1) DEFAULT 1,
|
||||
StationAddedOn DATETIME DEFAULT NOW(),
|
||||
FOREIGN KEY (StationBusinessID) REFERENCES Businesses(BusinessID)
|
||||
BusinessID INT NOT NULL,
|
||||
Name VARCHAR(100) NOT NULL,
|
||||
Color VARCHAR(7) DEFAULT '##666666',
|
||||
SortOrder INT DEFAULT 0,
|
||||
IsActive TINYINT(1) DEFAULT 1,
|
||||
AddedOn DATETIME DEFAULT NOW(),
|
||||
FOREIGN KEY (BusinessID) REFERENCES Businesses(BusinessID)
|
||||
)
|
||||
", [], { datasource = "payfrit" })>
|
||||
|
||||
<!--- Add ItemStationID column to Items table if it doesn't exist --->
|
||||
<!--- Add StationID column to Items table if it doesn't exist --->
|
||||
<cftry>
|
||||
<cfset queryExecute("
|
||||
ALTER TABLE Items ADD COLUMN ItemStationID INT DEFAULT NULL
|
||||
ALTER TABLE Items ADD COLUMN StationID INT DEFAULT NULL
|
||||
", [], { datasource = "payfrit" })>
|
||||
<cfset stationColumnAdded = true>
|
||||
<cfcatch>
|
||||
|
|
@ -39,7 +39,7 @@
|
|||
<cfif stationColumnAdded>
|
||||
<cftry>
|
||||
<cfset queryExecute("
|
||||
ALTER TABLE Items ADD FOREIGN KEY (ItemStationID) REFERENCES Stations(StationID)
|
||||
ALTER TABLE Items ADD FOREIGN KEY (StationID) REFERENCES Stations(StationID)
|
||||
", [], { datasource = "payfrit" })>
|
||||
<cfcatch></cfcatch>
|
||||
</cftry>
|
||||
|
|
@ -47,12 +47,12 @@
|
|||
|
||||
<!--- Create some default stations for business 1 (In and Out Burger) if none exist --->
|
||||
<cfset qCheck = queryExecute("
|
||||
SELECT COUNT(*) AS cnt FROM Stations WHERE StationBusinessID = 1
|
||||
SELECT COUNT(*) AS cnt FROM Stations WHERE BusinessID = 1
|
||||
", [], { datasource = "payfrit" })>
|
||||
|
||||
<cfif qCheck.cnt EQ 0>
|
||||
<cfset queryExecute("
|
||||
INSERT INTO Stations (StationBusinessID, StationName, StationColor, StationSortOrder) VALUES
|
||||
INSERT INTO Stations (BusinessID, Name, Color, SortOrder) VALUES
|
||||
(1, 'Grill', '##FF5722', 1),
|
||||
(1, 'Fry', '##FFC107', 2),
|
||||
(1, 'Drinks', '##2196F3', 3),
|
||||
|
|
|
|||
|
|
@ -3,30 +3,51 @@
|
|||
<cfcontent type="application/json; charset=utf-8" reset="true">
|
||||
|
||||
<cfscript>
|
||||
// Switch all beacons from one business to another
|
||||
// Switch beacon mapping from one business to another via join table.
|
||||
// Beacons.BusinessID (owner) is NOT touched.
|
||||
fromBiz = 17; // In-N-Out
|
||||
toBiz = 27; // Big Dean's
|
||||
|
||||
// Remove mapping for source business
|
||||
queryExecute("
|
||||
UPDATE lt_Beacon_Businesses_ServicePoints
|
||||
SET BusinessID = :toBiz
|
||||
DELETE FROM lt_BeaconsID_BusinessesID
|
||||
WHERE BusinessID = :fromBiz
|
||||
", { fromBiz: fromBiz }, { datasource: "payfrit" });
|
||||
|
||||
// Add mapping for target business (for beacons owned by source)
|
||||
queryExecute("
|
||||
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("
|
||||
UPDATE ServicePoints
|
||||
SET BeaconID = NULL, AssignedByUserID = NULL
|
||||
WHERE BusinessID = :fromBiz AND BeaconID IS NOT NULL
|
||||
", { fromBiz: fromBiz }, { datasource: "payfrit" });
|
||||
|
||||
// Get current state
|
||||
q = queryExecute("
|
||||
SELECT lt.*, b.BusinessName
|
||||
FROM lt_Beacon_Businesses_ServicePoints lt
|
||||
JOIN Businesses b ON b.BusinessID = lt.BusinessID
|
||||
SELECT sp.ID AS ServicePointID, sp.BeaconID, sp.BusinessID,
|
||||
b.Name AS BeaconName, biz.Name AS BusinessName,
|
||||
sp.Name AS ServicePointName
|
||||
FROM ServicePoints sp
|
||||
JOIN Beacons b ON b.ID = sp.BeaconID
|
||||
JOIN Businesses biz ON biz.ID = sp.BusinessID
|
||||
WHERE sp.BeaconID IS NOT NULL
|
||||
", {}, { datasource: "payfrit" });
|
||||
|
||||
rows = [];
|
||||
for (row in q) {
|
||||
arrayAppend(rows, {
|
||||
"BeaconID": row.BeaconID,
|
||||
"BeaconName": row.BeaconName,
|
||||
"BusinessID": row.BusinessID,
|
||||
"BusinessName": row.BusinessName,
|
||||
"ServicePointID": row.ServicePointID
|
||||
"ServicePointID": row.ServicePointID,
|
||||
"ServicePointName": row.ServicePointName
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,10 +7,10 @@
|
|||
<cfset queryExecute(
|
||||
"
|
||||
INSERT INTO Tasks (
|
||||
TaskBusinessID,
|
||||
TaskOrderID,
|
||||
TaskClaimedByUserID,
|
||||
TaskAddedOn
|
||||
BusinessID,
|
||||
OrderID,
|
||||
ClaimedByUserID,
|
||||
CreatedOn
|
||||
) VALUES (
|
||||
1,
|
||||
999,
|
||||
|
|
|
|||
|
|
@ -2,16 +2,16 @@
|
|||
<cfcontent type="application/json; charset=utf-8" reset="true">
|
||||
<cfscript>
|
||||
qTask = queryExecute("
|
||||
SELECT TaskID, TaskTypeID, TaskClaimedByUserID, TaskCompletedOn
|
||||
SELECT ID, TaskTypeID, ClaimedByUserID, CompletedOn
|
||||
FROM Tasks
|
||||
WHERE TaskID = 57
|
||||
WHERE ID = 57
|
||||
", [], { datasource: "payfrit" });
|
||||
|
||||
writeOutput(serializeJSON({
|
||||
"OK": true,
|
||||
"TaskID": qTask.TaskID,
|
||||
"TaskID": qTask.ID,
|
||||
"TaskTypeID": qTask.TaskTypeID,
|
||||
"TaskClaimedByUserID": qTask.TaskClaimedByUserID,
|
||||
"TaskCompletedOn": qTask.TaskCompletedOn
|
||||
"ClaimedByUserID": qTask.ClaimedByUserID,
|
||||
"CompletedOn": qTask.CompletedOn
|
||||
}));
|
||||
</cfscript>
|
||||
|
|
|
|||
|
|
@ -3,42 +3,57 @@
|
|||
<cfcontent type="application/json; charset=utf-8" reset="true">
|
||||
|
||||
<cfscript>
|
||||
// Update Beacon 2 to point to In-N-Out (BusinessID 17)
|
||||
// Update beacon mapping via join table. Owner (Beacons.BusinessID) is NOT changed.
|
||||
beaconId = 2;
|
||||
oldBusinessId = 37; // previous mapping
|
||||
newBusinessId = 17;
|
||||
|
||||
// Remove old mapping
|
||||
queryExecute("
|
||||
UPDATE lt_Beacon_Businesses_ServicePoints
|
||||
SET BusinessID = :newBizId
|
||||
WHERE BeaconID = :beaconId
|
||||
", { newBizId: newBusinessId, beaconId: beaconId }, { datasource: "payfrit" });
|
||||
DELETE FROM lt_BeaconsID_BusinessesID
|
||||
WHERE BeaconID = :beaconId AND BusinessID = :oldBizId
|
||||
", { beaconId: beaconId, oldBizId: oldBusinessId }, { datasource: "payfrit" });
|
||||
|
||||
// Add new mapping
|
||||
queryExecute("
|
||||
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("
|
||||
UPDATE ServicePoints
|
||||
SET BeaconID = NULL, AssignedByUserID = NULL
|
||||
WHERE BeaconID = :beaconId AND BusinessID = :oldBizId
|
||||
", { beaconId: beaconId, oldBizId: oldBusinessId }, { datasource: "payfrit" });
|
||||
|
||||
// Get current state
|
||||
q = queryExecute("
|
||||
SELECT
|
||||
b.BeaconID,
|
||||
b.BeaconUUID,
|
||||
b.BeaconName,
|
||||
lt.BusinessID,
|
||||
lt.ServicePointID,
|
||||
biz.BusinessName,
|
||||
sp.ServicePointName
|
||||
b.ID AS BeaconID,
|
||||
b.UUID,
|
||||
b.Name AS BeaconName,
|
||||
b.BusinessID AS BeaconBusinessID,
|
||||
sp.ID AS ServicePointID,
|
||||
sp.Name AS ServicePointName,
|
||||
sp.BusinessID AS ServicePointBusinessID,
|
||||
biz.Name AS BusinessName
|
||||
FROM Beacons b
|
||||
LEFT JOIN lt_Beacon_Businesses_ServicePoints lt ON lt.BeaconID = b.BeaconID
|
||||
LEFT JOIN Businesses biz ON biz.BusinessID = lt.BusinessID
|
||||
LEFT JOIN ServicePoints sp ON sp.ServicePointID = lt.ServicePointID
|
||||
WHERE b.BeaconIsActive = 1
|
||||
ORDER BY b.BeaconID
|
||||
LEFT JOIN ServicePoints sp ON sp.BeaconID = b.ID
|
||||
LEFT JOIN Businesses biz ON biz.ID = b.BusinessID
|
||||
WHERE b.IsActive = 1
|
||||
ORDER BY b.ID
|
||||
", {}, { datasource: "payfrit" });
|
||||
|
||||
rows = [];
|
||||
for (row in q) {
|
||||
arrayAppend(rows, {
|
||||
"BeaconID": row.BeaconID,
|
||||
"BeaconUUID": row.BeaconUUID,
|
||||
"BeaconName": row.BeaconName ?: "",
|
||||
"BusinessID": row.BusinessID ?: 0,
|
||||
"BusinessName": row.BusinessName ?: "",
|
||||
"UUID": row.UUID,
|
||||
"BeaconName": row.BeaconName,
|
||||
"BeaconBusinessID": row.BeaconBusinessID,
|
||||
"BusinessName": row.BusinessName,
|
||||
"ServicePointID": row.ServicePointID ?: 0,
|
||||
"ServicePointName": row.ServicePointName ?: ""
|
||||
});
|
||||
|
|
|
|||
|
|
@ -6,72 +6,68 @@
|
|||
// Update Big Dean's business info
|
||||
businessId = 27;
|
||||
|
||||
// Big Dean's actual address and hours
|
||||
address = "1615 Ocean Front Walk, Santa Monica, CA 90401";
|
||||
// Big Dean's actual info
|
||||
phone = "(310) 393-2666";
|
||||
hours = "Mon-Thu: 11am-10pm, Fri-Sat: 11am-11pm, Sun: 11am-10pm";
|
||||
|
||||
try {
|
||||
// First get column names from INFORMATION_SCHEMA
|
||||
cols = queryExecute("
|
||||
SELECT COLUMN_NAME
|
||||
FROM INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE TABLE_SCHEMA = 'payfrit' AND TABLE_NAME = 'Businesses'
|
||||
ORDER BY ORDINAL_POSITION
|
||||
");
|
||||
|
||||
colNames = [];
|
||||
for (c in cols) {
|
||||
arrayAppend(colNames, c.COLUMN_NAME);
|
||||
}
|
||||
|
||||
// Check if we have the columns we need
|
||||
hasAddress = arrayFindNoCase(colNames, "BusinessAddress") > 0;
|
||||
hasPhone = arrayFindNoCase(colNames, "BusinessPhone") > 0;
|
||||
hasHours = arrayFindNoCase(colNames, "BusinessHours") > 0;
|
||||
|
||||
// Add columns if missing
|
||||
if (!hasAddress) {
|
||||
queryExecute("ALTER TABLE Businesses ADD COLUMN BusinessAddress VARCHAR(255)");
|
||||
}
|
||||
if (!hasPhone) {
|
||||
queryExecute("ALTER TABLE Businesses ADD COLUMN BusinessPhone VARCHAR(50)");
|
||||
}
|
||||
if (!hasHours) {
|
||||
queryExecute("ALTER TABLE Businesses ADD COLUMN BusinessHours VARCHAR(255)");
|
||||
}
|
||||
|
||||
// Update with new info
|
||||
// Update phone and hours on Businesses table
|
||||
queryExecute("
|
||||
UPDATE Businesses
|
||||
SET BusinessAddress = :address,
|
||||
BusinessPhone = :phone,
|
||||
BusinessHours = :hours
|
||||
WHERE BusinessID = :bizId
|
||||
SET Phone = :phone,
|
||||
Hours = :hours
|
||||
WHERE ID = :bizId
|
||||
", {
|
||||
address: address,
|
||||
phone: phone,
|
||||
hours: hours,
|
||||
bizId: businessId
|
||||
});
|
||||
}, { datasource: "payfrit" });
|
||||
|
||||
// Update or insert address in Addresses table
|
||||
qAddr = queryExecute("
|
||||
SELECT ID FROM Addresses
|
||||
WHERE BusinessID = :bizId AND IsDeleted = 0
|
||||
LIMIT 1
|
||||
", { bizId: businessId }, { datasource: "payfrit" });
|
||||
|
||||
if (qAddr.recordCount > 0) {
|
||||
queryExecute("
|
||||
UPDATE Addresses
|
||||
SET Line1 = :line1, City = :city, ZIPCode = :zip
|
||||
WHERE ID = :addrId
|
||||
", {
|
||||
line1: "1615 Ocean Front Walk",
|
||||
city: "Santa Monica",
|
||||
zip: "90401",
|
||||
addrId: qAddr.ID
|
||||
}, { datasource: "payfrit" });
|
||||
} else {
|
||||
queryExecute("
|
||||
INSERT INTO Addresses (BusinessID, UserID, AddressTypeID, Line1, City, ZIPCode, AddedOn)
|
||||
VALUES (:bizId, 0, 'business', :line1, :city, :zip, NOW())
|
||||
", {
|
||||
bizId: businessId,
|
||||
line1: "1615 Ocean Front Walk",
|
||||
city: "Santa Monica",
|
||||
zip: "90401"
|
||||
}, { datasource: "payfrit" });
|
||||
}
|
||||
|
||||
// Get updated record
|
||||
updated = queryExecute("
|
||||
SELECT BusinessID, BusinessName, BusinessAddress, BusinessPhone, BusinessHours
|
||||
SELECT ID, Name, Phone, Hours
|
||||
FROM Businesses
|
||||
WHERE BusinessID = :bizId
|
||||
", { bizId: businessId });
|
||||
WHERE ID = :bizId
|
||||
", { bizId: businessId }, { datasource: "payfrit" });
|
||||
|
||||
writeOutput(serializeJSON({
|
||||
"OK": true,
|
||||
"MESSAGE": "Updated Big Dean's info",
|
||||
"COLUMNS_EXISTED": { "address": hasAddress, "phone": hasPhone, "hours": hasHours },
|
||||
"BUSINESS": {
|
||||
"BusinessID": updated.BusinessID,
|
||||
"BusinessName": updated.BusinessName,
|
||||
"BusinessAddress": updated.BusinessAddress,
|
||||
"BusinessPhone": updated.BusinessPhone,
|
||||
"BusinessHours": updated.BusinessHours
|
||||
"BusinessID": updated.ID,
|
||||
"Name": updated.Name,
|
||||
"Phone": updated.Phone,
|
||||
"Hours": updated.Hours
|
||||
}
|
||||
}));
|
||||
|
||||
|
|
|
|||
|
|
@ -34,28 +34,20 @@ if (!structKeyExists(request,"BusinessID") || !isNumeric(request.BusinessID) ||
|
|||
/* ---------- INPUT ---------- */
|
||||
data = readJsonBody();
|
||||
|
||||
if (
|
||||
!structKeyExists(data,"lt_Beacon_Businesses_ServicePointID")
|
||||
|| !isNumeric(data.lt_Beacon_Businesses_ServicePointID)
|
||||
|| int(data.lt_Beacon_Businesses_ServicePointID) LTE 0
|
||||
){
|
||||
apiAbort({OK=false,ERROR="missing_lt_Beacon_Businesses_ServicePointID"});
|
||||
if (!structKeyExists(data,"ServicePointID") || !isNumeric(data.ServicePointID) || int(data.ServicePointID) LTE 0){
|
||||
apiAbort({OK=false,ERROR="missing_ServicePointID"});
|
||||
}
|
||||
|
||||
RelID = int(data.lt_Beacon_Businesses_ServicePointID);
|
||||
ServicePointID = int(data.ServicePointID);
|
||||
</cfscript>
|
||||
|
||||
<!--- Confirm the row exists for this BusinessID (and capture what it was) --->
|
||||
<!--- Confirm the service point exists for this business and has a beacon assigned --->
|
||||
<cfquery name="qFind" datasource="payfrit">
|
||||
SELECT
|
||||
lt_Beacon_Businesses_ServicePointID,
|
||||
BeaconID,
|
||||
ServicePointID
|
||||
FROM lt_Beacon_Businesses_ServicePoints
|
||||
WHERE lt_Beacon_Businesses_ServicePointID =
|
||||
<cfqueryparam cfsqltype="cf_sql_integer" value="#RelID#">
|
||||
AND BusinessID =
|
||||
<cfqueryparam cfsqltype="cf_sql_integer" value="#request.BusinessID#">
|
||||
SELECT ID, BeaconID
|
||||
FROM ServicePoints
|
||||
WHERE ID = <cfqueryparam cfsqltype="cf_sql_integer" value="#ServicePointID#">
|
||||
AND BusinessID = <cfqueryparam cfsqltype="cf_sql_integer" value="#request.BusinessID#">
|
||||
AND BeaconID IS NOT NULL
|
||||
LIMIT 1
|
||||
</cfquery>
|
||||
|
||||
|
|
@ -63,28 +55,28 @@ RelID = int(data.lt_Beacon_Businesses_ServicePointID);
|
|||
<cfoutput>#serializeJSON({
|
||||
"OK"=false,
|
||||
"ERROR"="not_found",
|
||||
"lt_Beacon_Businesses_ServicePointID"=RelID,
|
||||
"ServicePointID"=ServicePointID,
|
||||
"BusinessID"=(request.BusinessID & "")
|
||||
})#</cfoutput>
|
||||
<cfabort>
|
||||
</cfif>
|
||||
|
||||
<!--- Delete it --->
|
||||
<cfset removedBeaconID = qFind.BeaconID>
|
||||
|
||||
<!--- Unassign beacon from service point --->
|
||||
<cfquery datasource="payfrit">
|
||||
DELETE FROM lt_Beacon_Businesses_ServicePoints
|
||||
WHERE lt_Beacon_Businesses_ServicePointID =
|
||||
<cfqueryparam cfsqltype="cf_sql_integer" value="#RelID#">
|
||||
AND BusinessID =
|
||||
<cfqueryparam cfsqltype="cf_sql_integer" value="#request.BusinessID#">
|
||||
LIMIT 1
|
||||
UPDATE ServicePoints
|
||||
SET BeaconID = NULL,
|
||||
AssignedByUserID = NULL
|
||||
WHERE ID = <cfqueryparam cfsqltype="cf_sql_integer" value="#ServicePointID#">
|
||||
AND BusinessID = <cfqueryparam cfsqltype="cf_sql_integer" value="#request.BusinessID#">
|
||||
</cfquery>
|
||||
|
||||
<cfoutput>#serializeJSON({
|
||||
"OK"=true,
|
||||
"ERROR"="",
|
||||
"ACTION"="deleted",
|
||||
"lt_Beacon_Businesses_ServicePointID"=RelID,
|
||||
"BeaconID"=qFind.BeaconID,
|
||||
"ServicePointID"=qFind.ServicePointID,
|
||||
"ACTION"="unassigned",
|
||||
"ServicePointID"=ServicePointID,
|
||||
"BeaconID"=removedBeaconID,
|
||||
"BusinessID"=(request.BusinessID & "")
|
||||
})#</cfoutput>
|
||||
|
|
|
|||
|
|
@ -17,32 +17,29 @@ if (!structKeyExists(request, "BusinessID") || !isNumeric(request.BusinessID) ||
|
|||
|
||||
<cfquery name="q" datasource="payfrit">
|
||||
SELECT
|
||||
lt.lt_Beacon_Businesses_ServicePointID,
|
||||
lt.BeaconID,
|
||||
lt.BusinessID,
|
||||
lt.ServicePointID,
|
||||
lt.lt_Beacon_Businesses_ServicePointNotes,
|
||||
b.BeaconName,
|
||||
b.BeaconUUID,
|
||||
sp.ServicePointName
|
||||
FROM lt_Beacon_Businesses_ServicePoints lt
|
||||
JOIN Beacons b ON b.BeaconID = lt.BeaconID
|
||||
LEFT JOIN ServicePoints sp ON sp.ServicePointID = lt.ServicePointID
|
||||
WHERE lt.BusinessID = <cfqueryparam cfsqltype="cf_sql_integer" value="#request.BusinessID#">
|
||||
ORDER BY b.BeaconName, sp.ServicePointName
|
||||
sp.ID AS ServicePointID,
|
||||
sp.BeaconID,
|
||||
sp.BusinessID,
|
||||
sp.AssignedByUserID,
|
||||
b.Name AS BeaconName,
|
||||
b.UUID,
|
||||
sp.Name AS ServicePointName
|
||||
FROM ServicePoints sp
|
||||
JOIN Beacons b ON b.ID = sp.BeaconID
|
||||
WHERE sp.BusinessID = <cfqueryparam cfsqltype="cf_sql_integer" value="#request.BusinessID#">
|
||||
AND sp.BeaconID IS NOT NULL
|
||||
ORDER BY b.Name, sp.Name
|
||||
</cfquery>
|
||||
|
||||
<cfset assignments = []>
|
||||
<cfloop query="q">
|
||||
<cfset arrayAppend(assignments, {
|
||||
"lt_Beacon_Businesses_ServicePointID" = q.lt_Beacon_Businesses_ServicePointID,
|
||||
"ServicePointID" = q.ServicePointID,
|
||||
"BeaconID" = q.BeaconID,
|
||||
"BusinessID" = q.BusinessID,
|
||||
"ServicePointID" = q.ServicePointID,
|
||||
"BeaconName" = q.BeaconName,
|
||||
"BeaconUUID" = q.BeaconUUID,
|
||||
"ServicePointName"= q.ServicePointName,
|
||||
"lt_Beacon_Businesses_ServicePointNotes" = q.lt_Beacon_Businesses_ServicePointNotes
|
||||
"UUID" = q.UUID,
|
||||
"ServicePointName"= q.ServicePointName
|
||||
})>
|
||||
</cfloop>
|
||||
|
||||
|
|
|
|||
|
|
@ -26,11 +26,6 @@ function readJsonBody(){
|
|||
return parsed;
|
||||
}
|
||||
|
||||
function normStr(v){
|
||||
if (isNull(v)) return "";
|
||||
return trim(toString(v));
|
||||
}
|
||||
|
||||
/* ---------- AUTH CONTEXT ---------- */
|
||||
if (!structKeyExists(request,"BusinessID") || !isNumeric(request.BusinessID) || request.BusinessID LTE 0){
|
||||
apiAbort({OK=false,ERROR="no_business_selected"});
|
||||
|
|
@ -48,43 +43,45 @@ if (!structKeyExists(data,"ServicePointID") || !isNumeric(data.ServicePointID) |
|
|||
|
||||
BeaconID = int(data.BeaconID);
|
||||
ServicePointID = int(data.ServicePointID);
|
||||
Notes = "";
|
||||
if (structKeyExists(data,"Notes")){
|
||||
Notes = left(normStr(data.Notes), 255);
|
||||
}
|
||||
</cfscript>
|
||||
|
||||
<!--- Validate Beacon belongs to Business OR to Business's parent --->
|
||||
<!--- Validate Beacon is allowed for this Business:
|
||||
Owner (Beacons.BusinessID) OR join table (lt_BeaconsID_BusinessesID) OR parent's owner --->
|
||||
<cfquery name="qBiz" datasource="payfrit">
|
||||
SELECT BusinessID, BusinessParentBusinessID
|
||||
SELECT ID, ParentBusinessID
|
||||
FROM Businesses
|
||||
WHERE BusinessID = <cfqueryparam cfsqltype="cf_sql_integer" value="#request.BusinessID#">
|
||||
WHERE ID = <cfqueryparam cfsqltype="cf_sql_integer" value="#request.BusinessID#">
|
||||
LIMIT 1
|
||||
</cfquery>
|
||||
|
||||
<cfquery name="qB" datasource="payfrit">
|
||||
SELECT BeaconID
|
||||
FROM Beacons
|
||||
WHERE BeaconID = <cfqueryparam cfsqltype="cf_sql_integer" value="#BeaconID#">
|
||||
SELECT b.ID
|
||||
FROM Beacons b
|
||||
WHERE b.ID = <cfqueryparam cfsqltype="cf_sql_integer" value="#BeaconID#">
|
||||
AND (
|
||||
BeaconBusinessID = <cfqueryparam cfsqltype="cf_sql_integer" value="#request.BusinessID#">
|
||||
<cfif qBiz.recordCount GT 0 AND len(trim(qBiz.BusinessParentBusinessID)) GT 0 AND isNumeric(qBiz.BusinessParentBusinessID) AND qBiz.BusinessParentBusinessID GT 0>
|
||||
OR BeaconBusinessID = <cfqueryparam cfsqltype="cf_sql_integer" value="#qBiz.BusinessParentBusinessID#">
|
||||
b.BusinessID = <cfqueryparam cfsqltype="cf_sql_integer" value="#request.BusinessID#">
|
||||
<cfif qBiz.recordCount GT 0 AND len(trim(qBiz.ParentBusinessID)) GT 0 AND isNumeric(qBiz.ParentBusinessID) AND qBiz.ParentBusinessID GT 0>
|
||||
OR b.BusinessID = <cfqueryparam cfsqltype="cf_sql_integer" value="#qBiz.ParentBusinessID#">
|
||||
</cfif>
|
||||
OR EXISTS (
|
||||
SELECT 1 FROM lt_BeaconsID_BusinessesID lt
|
||||
WHERE lt.BeaconID = b.ID
|
||||
AND lt.BusinessID = <cfqueryparam cfsqltype="cf_sql_integer" value="#request.BusinessID#">
|
||||
)
|
||||
)
|
||||
LIMIT 1
|
||||
</cfquery>
|
||||
<cfif qB.recordCount EQ 0>
|
||||
<cfoutput>#serializeJSON({OK=false,ERROR="beacon_not_found_for_business"})#</cfoutput>
|
||||
<cfoutput>#serializeJSON({OK=false,ERROR="beacon_not_allowed"})#</cfoutput>
|
||||
<cfabort>
|
||||
</cfif>
|
||||
|
||||
<!--- Validate ServicePoint belongs to Business --->
|
||||
<cfquery name="qS" datasource="payfrit">
|
||||
SELECT ServicePointID
|
||||
SELECT ID
|
||||
FROM ServicePoints
|
||||
WHERE ServicePointID = <cfqueryparam cfsqltype="cf_sql_integer" value="#ServicePointID#">
|
||||
AND ServicePointBusinessID = <cfqueryparam cfsqltype="cf_sql_integer" value="#request.BusinessID#">
|
||||
WHERE ID = <cfqueryparam cfsqltype="cf_sql_integer" value="#ServicePointID#">
|
||||
AND BusinessID = <cfqueryparam cfsqltype="cf_sql_integer" value="#request.BusinessID#">
|
||||
LIMIT 1
|
||||
</cfquery>
|
||||
<cfif qS.recordCount EQ 0>
|
||||
|
|
@ -92,14 +89,12 @@ if (structKeyExists(data,"Notes")){
|
|||
<cfabort>
|
||||
</cfif>
|
||||
|
||||
<!--- Check if THIS BUSINESS already has this exact beacon+servicepoint combo --->
|
||||
<!--- (Multiple businesses CAN share the same beacon, but one business shouldn't duplicate) --->
|
||||
<!--- Check if this ServicePoint already has this beacon assigned --->
|
||||
<cfquery name="qDuplicate" datasource="payfrit">
|
||||
SELECT lt_Beacon_Businesses_ServicePointID
|
||||
FROM lt_Beacon_Businesses_ServicePoints
|
||||
WHERE BusinessID = <cfqueryparam cfsqltype="cf_sql_integer" value="#request.BusinessID#">
|
||||
SELECT ID
|
||||
FROM ServicePoints
|
||||
WHERE ID = <cfqueryparam cfsqltype="cf_sql_integer" value="#ServicePointID#">
|
||||
AND BeaconID = <cfqueryparam cfsqltype="cf_sql_integer" value="#BeaconID#">
|
||||
AND ServicePointID = <cfqueryparam cfsqltype="cf_sql_integer" value="#ServicePointID#">
|
||||
LIMIT 1
|
||||
</cfquery>
|
||||
<cfif qDuplicate.recordCount GT 0>
|
||||
|
|
@ -107,31 +102,19 @@ if (structKeyExists(data,"Notes")){
|
|||
<cfabort>
|
||||
</cfif>
|
||||
|
||||
<!--- INSERT --->
|
||||
<!--- Assign beacon to service point --->
|
||||
<cfquery datasource="payfrit">
|
||||
INSERT INTO lt_Beacon_Businesses_ServicePoints
|
||||
(BusinessID, BeaconID, ServicePointID,
|
||||
lt_Beacon_Businesses_ServicePointAssignedByUserID,
|
||||
lt_Beacon_Businesses_ServicePointNotes)
|
||||
VALUES
|
||||
(
|
||||
<cfqueryparam cfsqltype="cf_sql_integer" value="#request.BusinessID#">,
|
||||
<cfqueryparam cfsqltype="cf_sql_integer" value="#BeaconID#">,
|
||||
<cfqueryparam cfsqltype="cf_sql_integer" value="#ServicePointID#">,
|
||||
<cfqueryparam cfsqltype="cf_sql_integer" value="1">,
|
||||
<cfqueryparam cfsqltype="cf_sql_varchar" value="#Notes#" null="#(len(Notes) EQ 0)#">
|
||||
)
|
||||
</cfquery>
|
||||
|
||||
<cfquery name="qID" datasource="payfrit">
|
||||
SELECT LAST_INSERT_ID() AS NewID
|
||||
UPDATE ServicePoints
|
||||
SET BeaconID = <cfqueryparam cfsqltype="cf_sql_integer" value="#BeaconID#">,
|
||||
AssignedByUserID = <cfqueryparam cfsqltype="cf_sql_integer" value="1">
|
||||
WHERE ID = <cfqueryparam cfsqltype="cf_sql_integer" value="#ServicePointID#">
|
||||
AND BusinessID = <cfqueryparam cfsqltype="cf_sql_integer" value="#request.BusinessID#">
|
||||
</cfquery>
|
||||
|
||||
<cfoutput>#serializeJSON({
|
||||
"OK"=true,
|
||||
"ACTION"="inserted",
|
||||
"lt_Beacon_Businesses_ServicePointID"=qID.NewID,
|
||||
"BeaconID"=BeaconID,
|
||||
"ACTION"="assigned",
|
||||
"ServicePointID"=ServicePointID,
|
||||
"BeaconID"=BeaconID,
|
||||
"BusinessID"=(request.BusinessID & "")
|
||||
})#</cfoutput>
|
||||
|
|
|
|||
|
|
@ -71,9 +71,9 @@ try {
|
|||
|
||||
// Check if email is already used by another verified account
|
||||
qEmailCheck = queryExecute("
|
||||
SELECT UserID FROM Users
|
||||
WHERE UserEmailAddress = :email
|
||||
AND UserIsEmailVerified = 1
|
||||
SELECT ID FROM Users
|
||||
WHERE EmailAddress = :email
|
||||
AND IsEmailVerified = 1
|
||||
AND UserID != :userId
|
||||
LIMIT 1
|
||||
", {
|
||||
|
|
@ -87,19 +87,19 @@ try {
|
|||
|
||||
// Get current user UUID for email confirmation link
|
||||
qUser = queryExecute("
|
||||
SELECT UserUUID FROM Users WHERE UserID = :userId
|
||||
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("
|
||||
UPDATE Users
|
||||
SET UserFirstName = :firstName,
|
||||
UserLastName = :lastName,
|
||||
UserEmailAddress = :email,
|
||||
UserIsEmailVerified = 0,
|
||||
UserIsContactVerified = 1,
|
||||
UserIsActive = 1
|
||||
SET FirstName = :firstName,
|
||||
LastName = :lastName,
|
||||
EmailAddress = :email,
|
||||
IsEmailVerified = 0,
|
||||
IsContactVerified = 1,
|
||||
IsActive = 1
|
||||
WHERE UserID = :userId
|
||||
", {
|
||||
firstName: { value: firstName, cfsqltype: "cf_sql_varchar" },
|
||||
|
|
@ -109,7 +109,7 @@ try {
|
|||
}, { datasource: "payfrit" });
|
||||
|
||||
// Send confirmation email (non-blocking - don't fail if mail fails)
|
||||
confirmLink = "https://biz.payfrit.com/confirm_email.cfm?UUID=" & qUser.UserUUID;
|
||||
confirmLink = "https://biz.payfrit.com/confirm_email.cfm?UUID=" & qUser.UUID;
|
||||
emailBody = "
|
||||
<p>Welcome to Payfrit, #firstName#!</p>
|
||||
<p>Please click the link below to confirm your email address:</p>
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
{ "username": "...", "password": "..." }
|
||||
|
||||
OUTPUT (JSON):
|
||||
{ OK:true, ERROR:"", UserID:123, UserFirstName:"...", Token:"..." }
|
||||
{ OK:true, ERROR:"", UserID:123, FirstName:"...", Token:"..." }
|
||||
|
||||
Uses existing UserTokens table:
|
||||
TokenID (auto), UserID, Token, CreatedAt (DEFAULT CURRENT_TIMESTAMP)
|
||||
|
|
@ -55,16 +55,16 @@ if (!len(username) || !len(password)) {
|
|||
try {
|
||||
q = queryExecute(
|
||||
"
|
||||
SELECT UserID, UserFirstName
|
||||
SELECT ID, FirstName
|
||||
FROM Users
|
||||
WHERE
|
||||
(
|
||||
(UserEmailAddress = ?) OR
|
||||
(UserContactNumber = ?)
|
||||
(EmailAddress = ?) OR
|
||||
(ContactNumber = ?)
|
||||
)
|
||||
AND UserPassword = ?
|
||||
AND UserIsEmailVerified = 1
|
||||
AND UserIsContactVerified > 0
|
||||
AND Password = ?
|
||||
AND IsEmailVerified = 1
|
||||
AND IsContactVerified > 0
|
||||
LIMIT 1
|
||||
",
|
||||
[
|
||||
|
|
@ -84,7 +84,7 @@ try {
|
|||
queryExecute(
|
||||
"INSERT INTO UserTokens (UserID, Token) VALUES (?, ?)",
|
||||
[
|
||||
{ value = q.UserID, cfsqltype = "cf_sql_integer" },
|
||||
{ value = q.ID, cfsqltype = "cf_sql_integer" },
|
||||
{ value = token, cfsqltype = "cf_sql_varchar" }
|
||||
],
|
||||
{ datasource = "payfrit" }
|
||||
|
|
@ -92,15 +92,15 @@ try {
|
|||
|
||||
// Optional: also set session for browser tools
|
||||
lock timeout="15" throwontimeout="yes" type="exclusive" scope="session" {
|
||||
session.UserID = q.UserID;
|
||||
session.UserID = q.ID;
|
||||
}
|
||||
request.UserID = q.UserID;
|
||||
request.UserID = q.ID;
|
||||
|
||||
writeOutput(serializeJSON({
|
||||
"OK": true,
|
||||
"ERROR": "",
|
||||
"UserID": q.UserID,
|
||||
"UserFirstName": q.UserFirstName,
|
||||
"UserID": q.ID,
|
||||
"FirstName": q.FirstName,
|
||||
"Token": token
|
||||
}));
|
||||
abort;
|
||||
|
|
|
|||
|
|
@ -53,10 +53,10 @@ try {
|
|||
|
||||
// Find verified account with this phone
|
||||
qUser = queryExecute("
|
||||
SELECT UserID, UserUUID
|
||||
SELECT ID, UUID
|
||||
FROM Users
|
||||
WHERE UserContactNumber = :phone
|
||||
AND UserIsContactVerified = 1
|
||||
WHERE ContactNumber = :phone
|
||||
AND IsContactVerified = 1
|
||||
LIMIT 1
|
||||
", { phone: { value: phone, cfsqltype: "cf_sql_varchar" } }, { datasource: "payfrit" });
|
||||
|
||||
|
|
@ -65,14 +65,14 @@ try {
|
|||
}
|
||||
|
||||
// If user has no UUID (legacy account), generate one
|
||||
userUUID = qUser.UserUUID;
|
||||
userUUID = qUser.UUID;
|
||||
if (!len(trim(userUUID))) {
|
||||
userUUID = replace(createUUID(), "-", "", "all");
|
||||
queryExecute("
|
||||
UPDATE Users SET UserUUID = :uuid WHERE UserID = :userId
|
||||
UPDATE Users SET UUID = :uuid WHERE UserID = :userId
|
||||
", {
|
||||
uuid: { value: userUUID, cfsqltype: "cf_sql_varchar" },
|
||||
userId: { value: qUser.UserID, cfsqltype: "cf_sql_integer" }
|
||||
userId: { value: qUser.ID, cfsqltype: "cf_sql_integer" }
|
||||
}, { datasource: "payfrit" });
|
||||
}
|
||||
|
||||
|
|
@ -80,11 +80,11 @@ try {
|
|||
otp = generateOTP();
|
||||
queryExecute("
|
||||
UPDATE Users
|
||||
SET UserMobileVerifyCode = :otp
|
||||
SET MobileVerifyCode = :otp
|
||||
WHERE UserID = :userId
|
||||
", {
|
||||
otp: { value: otp, cfsqltype: "cf_sql_varchar" },
|
||||
userId: { value: qUser.UserID, cfsqltype: "cf_sql_integer" }
|
||||
userId: { value: qUser.ID, cfsqltype: "cf_sql_integer" }
|
||||
}, { datasource: "payfrit" });
|
||||
|
||||
// Send OTP via Twilio (skip on dev server)
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Reference in a new issue