Add beacon sharding support to lookup API

The lookup API now handles two formats:
1. Sharding: { "Beacons": [{ "UUID", "Major", "Minor" }] }
   Resolves via BeaconShards -> Businesses.BeaconMajor -> ServicePoints.BeaconMinor
2. Legacy: { "UUIDs": ["..."] }
   Resolves via old Beacons table

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
John Mizerek 2026-02-08 12:21:30 -08:00
parent 9ea3ec87f7
commit 2f35eb69eb

View file

@ -6,6 +6,90 @@
<cfset requestData = deserializeJSON(toString(getHttpRequestData().content))> <cfset requestData = deserializeJSON(toString(getHttpRequestData().content))>
<!--- ============================================================================
SHARDING FORMAT: { "Beacons": [{ "UUID": "...", "Major": 49, "Minor": 15 }] }
Resolves via BeaconShards -> Businesses (BeaconMajor) -> ServicePoints (BeaconMinor)
============================================================================ --->
<cfif structKeyExists(requestData, "Beacons") AND isArray(requestData.Beacons) AND arrayLen(requestData.Beacons) GT 0>
<cfset beacons = []>
<cfloop array="#requestData.Beacons#" index="beaconData">
<cfset uuid = "">
<cfset major = 0>
<cfset minor = -1>
<!--- Extract UUID (normalize: remove dashes, add back in standard format) --->
<cfif structKeyExists(beaconData, "UUID")>
<cfset rawUuid = uCase(reReplace(beaconData.UUID, "-", "", "all"))>
<cfif len(rawUuid) EQ 32>
<!--- Convert to standard UUID format with dashes for DB lookup --->
<cfset uuid = lCase(mid(rawUuid,1,8) & "-" & mid(rawUuid,9,4) & "-" & mid(rawUuid,13,4) & "-" & mid(rawUuid,17,4) & "-" & mid(rawUuid,21,12))>
</cfif>
</cfif>
<cfif structKeyExists(beaconData, "Major") AND isNumeric(beaconData.Major)>
<cfset major = int(beaconData.Major)>
</cfif>
<cfif structKeyExists(beaconData, "Minor") AND isNumeric(beaconData.Minor)>
<cfset minor = int(beaconData.Minor)>
</cfif>
<cfif len(uuid) EQ 0 OR major LTE 0 OR minor LT 0>
<cfcontinue>
</cfif>
<!--- Resolve via sharding: UUID -> Shard -> Business (Major) -> ServicePoint (Minor) --->
<cfquery name="qShard" datasource="payfrit">
SELECT
biz.ID AS BusinessID,
biz.Name AS BusinessName,
biz.ParentBusinessID,
COALESCE(parent.Name, '') AS ParentBusinessName,
sp.ID AS ServicePointID,
sp.Name AS ServicePointName,
(SELECT COUNT(*) FROM Businesses WHERE ParentBusinessID = biz.ID) AS ChildCount
FROM BeaconShards bs
JOIN Businesses biz ON biz.BeaconShardID = bs.ID AND biz.BeaconMajor = <cfqueryparam cfsqltype="cf_sql_smallint" value="#major#">
LEFT JOIN ServicePoints sp ON sp.BusinessID = biz.ID AND sp.BeaconMinor = <cfqueryparam cfsqltype="cf_sql_smallint" value="#minor#"> AND sp.IsActive = 1
LEFT JOIN Businesses parent ON biz.ParentBusinessID = parent.ID
WHERE bs.UUID = <cfqueryparam cfsqltype="cf_sql_varchar" value="#uuid#">
AND bs.IsActive = 1
AND biz.IsDemo = 0
AND biz.IsPrivate = 0
LIMIT 1
</cfquery>
<cfif qShard.recordCount GT 0>
<cfset arrayAppend(beacons, {
"UUID" = uCase(reReplace(uuid, "-", "", "all")),
"Major" = major,
"Minor" = minor,
"BeaconID" = 0,
"BeaconName" = qShard.ServicePointName,
"BusinessID" = qShard.BusinessID,
"BusinessName" = qShard.BusinessName,
"ServicePointID" = val(qShard.ServicePointID),
"ServicePointName" = qShard.ServicePointName,
"ParentBusinessID" = val(qShard.ParentBusinessID),
"ParentBusinessName" = qShard.ParentBusinessName,
"HasChildren" = qShard.ChildCount GT 0
})>
</cfif>
</cfloop>
<cfoutput>#serializeJSON({
"OK" = true,
"ERROR" = "",
"BEACONS" = beacons
})#</cfoutput>
<cfabort>
</cfif>
<!--- ============================================================================
LEGACY FORMAT: { "UUIDs": ["uuid1", "uuid2", ...] }
Resolves via old Beacons table
============================================================================ --->
<cfif NOT structKeyExists(requestData, "UUIDs") OR NOT isArray(requestData.UUIDs) OR arrayLen(requestData.UUIDs) EQ 0> <cfif NOT structKeyExists(requestData, "UUIDs") OR NOT isArray(requestData.UUIDs) OR arrayLen(requestData.UUIDs) EQ 0>
<cfoutput>#serializeJSON({ <cfoutput>#serializeJSON({
"OK" = true, "OK" = true,