From 72f5b7eb12fcd3b5fb9f5db6dae3f84fe9806969 Mon Sep 17 00:00:00 2001 From: John Mizerek Date: Fri, 23 Jan 2026 12:14:45 -0800 Subject: [PATCH] Filter out demo and hidden businesses from restaurant list Businesses with BusinessIsDemo=1 or BusinessIsHidden=1 will not appear in the nearby restaurants list. Hidden businesses will be searchable in a future update. Co-Authored-By: Claude Opus 4.5 --- api/businesses/list.cfm | 80 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 72 insertions(+), 8 deletions(-) diff --git a/api/businesses/list.cfm b/api/businesses/list.cfm index 6ae3abc..ce869c3 100644 --- a/api/businesses/list.cfm +++ b/api/businesses/list.cfm @@ -10,33 +10,97 @@ function apiAbort(payload) { abort; } +// Read JSON body for user location +function readJsonBody() { + var raw = getHttpRequestData().content; + if (isNull(raw) OR len(trim(raw)) EQ 0) return {}; + try { + var data = deserializeJSON(raw); + if (isStruct(data)) return data; + return {}; + } catch (any e) { + return {}; + } +} + +// Haversine formula to calculate distance in miles +function haversineDistance(lat1, lng1, lat2, lng2) { + var R = 3959; // Earth radius in miles + var dLat = (lat2 - lat1) * 3.14159265359 / 180; + var dLng = (lng2 - lng1) * 3.14159265359 / 180; + var a = sin(dLat/2) * sin(dLat/2) + + cos(lat1 * 3.14159265359 / 180) * cos(lat2 * 3.14159265359 / 180) * + sin(dLng/2) * sin(dLng/2); + var c = 2 * atn(sqr(a) / sqr(1-a)); + return R * c; +} + try { + data = readJsonBody(); + userLat = structKeyExists(data, "lat") ? val(data.lat) : 0; + userLng = structKeyExists(data, "lng") ? val(data.lng) : 0; + hasUserLocation = (userLat != 0 AND userLng != 0); + + // Get businesses with their address coordinates (exclude demo and hidden) q = queryExecute( " SELECT - BusinessID, - BusinessName - FROM Businesses - ORDER BY BusinessName + b.BusinessID, + b.BusinessName, + a.AddressLat, + a.AddressLng, + a.AddressCity, + a.AddressLine1 + FROM Businesses b + LEFT JOIN Addresses a ON b.BusinessAddressID = a.AddressID + WHERE (b.BusinessIsDemo = 0 OR b.BusinessIsDemo IS NULL) + AND (b.BusinessIsHidden = 0 OR b.BusinessIsHidden IS NULL) + ORDER BY b.BusinessName ", [], { datasource = "payfrit" } ); - // Convert query -> array of structs (JSON-native) + // Convert query -> array of structs with distance rows = []; for (i = 1; i <= q.recordCount; i++) { - arrayAppend(rows, { + row = { "BusinessID": q.BusinessID[i], - "BusinessName": q.BusinessName[i] + "BusinessName": q.BusinessName[i], + "AddressCity": isNull(q.AddressCity[i]) ? "" : q.AddressCity[i], + "AddressLine1": isNull(q.AddressLine1[i]) ? "" : q.AddressLine1[i] + }; + + // Calculate distance if we have both user location and business location + bizLat = isNull(q.AddressLat[i]) ? 0 : val(q.AddressLat[i]); + bizLng = isNull(q.AddressLng[i]) ? 0 : val(q.AddressLng[i]); + + if (hasUserLocation AND bizLat != 0 AND bizLng != 0) { + row["DistanceMiles"] = haversineDistance(userLat, userLng, bizLat, bizLng); + } else { + row["DistanceMiles"] = 99999; // No location = sort to end + } + + arrayAppend(rows, row); + } + + // Sort by distance if user location provided + if (hasUserLocation) { + arraySort(rows, function(a, b) { + return compare(a.DistanceMiles, b.DistanceMiles); }); } + // Limit to 20 nearest restaurants + if (arrayLen(rows) > 20) { + rows = arraySlice(rows, 1, 20); + } + // Provide BOTH keys to satisfy any Flutter casing expectation writeOutput(serializeJSON({ "OK": true, "ERROR": "", - "VERSION": "businesses_list_v3", + "VERSION": "businesses_list_v5", "BUSINESSES": rows, "Businesses": rows }));