This repository has been archived on 2026-03-21. You can view files and clone it, but cannot push or open issues or pull requests.
payfrit-biz/api/beacons/save.cfm
John Mizerek 1210249f54 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>
2026-01-30 15:39:12 -08:00

191 lines
5.9 KiB
Text

<cfsetting showdebugoutput="false">
<cfsetting enablecfoutputonly="true">
<cfcontent type="application/json; charset=utf-8" reset="true">
<cfheader name="Cache-Control" value="no-store">
<cftry>
<cfscript>
function apiAbort(obj) {
writeOutput(serializeJSON(obj));
abort;
}
function readJsonBody() {
raw = toString(getHttpRequestData().content);
if (isNull(raw) || len(trim(raw)) EQ 0) return {};
try {
parsed = deserializeJSON(raw);
} catch(any e) {
apiAbort({ OK=false, ERROR="bad_json", MESSAGE="Invalid JSON body" });
}
if (!isStruct(parsed)) return {};
return parsed;
}
function normStr(v) {
if (isNull(v)) return "";
return trim(toString(v));
}
data = readJsonBody();
if (!structKeyExists(request, "BusinessID") || !isNumeric(request.BusinessID) || request.BusinessID LTE 0) {
apiAbort({ OK=false, ERROR="no_business_selected" });
}
// Verify the business exists
qBiz = queryExecute(
"SELECT ID FROM Businesses WHERE ID = ? LIMIT 1",
[ { value=request.BusinessID, cfsqltype="cf_sql_integer" } ],
{ datasource="payfrit" }
);
if (qBiz.recordCount EQ 0) {
apiAbort({ OK=false, ERROR="invalid_business", MESSAGE="Business ID #request.BusinessID# does not exist. Please log out and log back in." });
}
if (!structKeyExists(data, "Name") || len(normStr(data.Name)) EQ 0) {
apiAbort({ OK=false, ERROR="missing_beacon_name", MESSAGE="Name is required" });
}
beaconId = 0;
if (structKeyExists(data, "BeaconID") && isNumeric(data.BeaconID) && int(data.BeaconID) GT 0) {
beaconId = int(data.BeaconID);
}
beaconName = normStr(data.Name);
uuid = structKeyExists(data, "UUID") ? normStr(data.UUID) : "";
isActive = 1;
if (structKeyExists(data, "IsActive")) {
if (isBoolean(data.IsActive)) isActive = (data.IsActive ? 1 : 0);
else if (isNumeric(data.IsActive)) isActive = int(data.IsActive);
else if (isSimpleValue(data.IsActive)) isActive = (lcase(trim(toString(data.IsActive))) EQ "true" ? 1 : 0);
}
// App is authoritative: if UUID exists, treat as update (overwrite)
if (beaconId EQ 0 && len(uuid) GT 0) {
qExisting = queryExecute(
"SELECT ID FROM Beacons WHERE UUID = ? LIMIT 1",
[ { value=uuid, cfsqltype="cf_sql_varchar" } ],
{ datasource="payfrit" }
);
if (qExisting.recordCount GT 0) {
beaconId = qExisting.ID;
}
}
</cfscript>
<cfif beaconId GT 0>
<!--- Update - app is authoritative, reassign to current business --->
<cfquery datasource="payfrit">
UPDATE Beacons
SET
BusinessID = <cfqueryparam cfsqltype="cf_sql_integer" value="#request.BusinessID#">,
Name = <cfqueryparam cfsqltype="cf_sql_varchar" value="#beaconName#">,
UUID = <cfqueryparam cfsqltype="cf_sql_varchar" value="#uuid#" null="#(len(uuid) EQ 0)#">,
IsActive = <cfqueryparam cfsqltype="cf_sql_tinyint" value="#isActive#">
WHERE ID = <cfqueryparam cfsqltype="cf_sql_integer" value="#beaconId#">
</cfquery>
<!--- Update associated service point if it exists, also reassign to current business --->
<cfquery name="qLink" datasource="payfrit">
SELECT ID FROM ServicePoints
WHERE BeaconID = <cfqueryparam cfsqltype="cf_sql_integer" value="#beaconId#">
LIMIT 1
</cfquery>
<cfif qLink.recordCount GT 0>
<cfquery datasource="payfrit">
UPDATE ServicePoints
SET Name = <cfqueryparam cfsqltype="cf_sql_varchar" value="#beaconName#">,
BusinessID = <cfqueryparam cfsqltype="cf_sql_integer" value="#request.BusinessID#">
WHERE BeaconID = <cfqueryparam cfsqltype="cf_sql_integer" value="#beaconId#">
</cfquery>
<cfelse>
<!--- No service point exists yet, create one linked to this beacon --->
<cfquery datasource="payfrit">
INSERT INTO ServicePoints (
BusinessID,
Name,
TypeID,
IsActive,
BeaconID
) VALUES (
<cfqueryparam cfsqltype="cf_sql_integer" value="#request.BusinessID#">,
<cfqueryparam cfsqltype="cf_sql_varchar" value="#beaconName#">,
1,
1,
<cfqueryparam cfsqltype="cf_sql_integer" value="#beaconId#">
)
</cfquery>
</cfif>
<cfelse>
<!--- Insert beacon --->
<cfquery datasource="payfrit">
INSERT INTO Beacons (
BusinessID,
Name,
UUID,
IsActive
) VALUES (
<cfqueryparam cfsqltype="cf_sql_integer" value="#request.BusinessID#">,
<cfqueryparam cfsqltype="cf_sql_varchar" value="#beaconName#">,
<cfqueryparam cfsqltype="cf_sql_varchar" value="#uuid#" null="#(len(uuid) EQ 0)#">,
<cfqueryparam cfsqltype="cf_sql_tinyint" value="#isActive#">
)
</cfquery>
<cfquery name="qId" datasource="payfrit">
SELECT LAST_INSERT_ID() AS ID
</cfquery>
<cfset beaconId = qId.ID>
<!--- Auto-create service point with same name, linked to beacon --->
<cfquery datasource="payfrit">
INSERT INTO ServicePoints (
BusinessID,
Name,
TypeID,
IsActive,
BeaconID
) VALUES (
<cfqueryparam cfsqltype="cf_sql_integer" value="#request.BusinessID#">,
<cfqueryparam cfsqltype="cf_sql_varchar" value="#beaconName#">,
1,
1,
<cfqueryparam cfsqltype="cf_sql_integer" value="#beaconId#">
)
</cfquery>
</cfif>
<!--- Return saved row --->
<cfquery name="qOut" datasource="payfrit">
SELECT
ID,
BusinessID,
Name,
UUID,
IsActive
FROM Beacons
WHERE ID = <cfqueryparam cfsqltype="cf_sql_integer" value="#beaconId#">
AND BusinessID = <cfqueryparam cfsqltype="cf_sql_integer" value="#request.BusinessID#">
LIMIT 1
</cfquery>
<cfset beacon = {
"BeaconID" = qOut.BeaconID,
"BusinessID" = qOut.BusinessID,
"Name" = qOut.Name,
"UUID" = qOut.UUID,
"IsActive" = qOut.IsActive
}>
<cfoutput>#serializeJSON({ OK=true, ERROR="", BEACON=beacon })#</cfoutput>
<cfcatch type="any">
<cfheader statuscode="200" statustext="OK">
<cfcontent type="application/json; charset=utf-8" reset="true">
<cfoutput>#serializeJSON({ OK=false, ERROR="server_error", MESSAGE=cfcatch.message, DETAIL=cfcatch.detail })#</cfoutput>
</cfcatch>
</cftry>