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(); // Required fields hardwareId = normStr(structKeyExists(data, "HardwareId") ? data.HardwareId : ""); if (len(hardwareId) EQ 0) { apiAbort({ OK=false, ERROR="missing_hardware_id", MESSAGE="HardwareId is required" }); } beaconUUID = normStr(structKeyExists(data, "UUID") ? data.UUID : ""); if (len(beaconUUID) EQ 0) { apiAbort({ OK=false, ERROR="missing_uuid", MESSAGE="UUID is required" }); } major = 0; if (structKeyExists(data, "Major") && isNumeric(data.Major)) { major = int(data.Major); } minor = 0; if (structKeyExists(data, "Minor") && isNumeric(data.Minor)) { minor = int(data.Minor); } // Optional fields rssi = ""; if (structKeyExists(data, "RSSI") && isNumeric(data.RSSI)) { rssi = int(data.RSSI); } seenAt = now(); if (structKeyExists(data, "SeenAt") && len(data.SeenAt)) { try { seenAt = parseDateTime(data.SeenAt); } catch(any e) { // Use current time if parse fails } } SELECT ID, BusinessID, ServicePointID, ShardUUID, Major, Minor, Status FROM BeaconHardware WHERE HardwareId = LIMIT 1 UPDATE BeaconHardware SET Status = 'verified', VerifiedAt = , LastSeenAt = , LastRssi = , UpdatedAt = NOW() WHERE HardwareId = #serializeJSON({ OK = true, BeaconHardwareID = qHW.ID, HardwareId = hardwareId, BusinessID = qHW.BusinessID, ServicePointID = qHW.ServicePointID, Status = "verified", VerifiedAt = dateTimeFormat(seenAt, "yyyy-mm-dd'T'HH:nn:ss'Z'") })# #serializeJSON({ OK=false, ERROR="server_error", MESSAGE=cfcatch.message, DETAIL=cfcatch.detail })#