payfrit-api/api/beacons/save.php
John Mizerek 1f81d98c52 Initial PHP API migration from CFML
Complete port of all 163 API endpoints from Lucee/CFML to PHP 8.3.
Shared helpers in api/helpers.php (DB, auth, request/response, security).
PDO prepared statements throughout. Same JSON response shapes as CFML.
2026-03-14 14:26:59 -07:00

103 lines
3.1 KiB
PHP

<?php
require_once __DIR__ . '/../helpers.php';
runAuth();
global $businessId;
$data = readJsonBody();
if ($businessId <= 0) {
apiAbort(['OK' => false, 'ERROR' => 'no_business_selected']);
}
$qBiz = queryOne("
SELECT ID, Name, BeaconShardID, BeaconMajor FROM Businesses WHERE ID = ? LIMIT 1
", [$businessId]);
if (!$qBiz) {
apiAbort(['OK' => false, 'ERROR' => 'invalid_business', 'MESSAGE' => 'Business not found']);
}
$shardID = (int) ($qBiz['BeaconShardID'] ?? 0);
$major = (int) ($qBiz['BeaconMajor'] ?? 0);
// Auto-allocate shard if needed
if ($shardID <= 0) {
$qFreeShard = queryOne("
SELECT bs.ID FROM BeaconShards bs
WHERE bs.IsActive = 1
AND bs.ID NOT IN (SELECT BeaconShardID FROM Businesses WHERE BeaconShardID IS NOT NULL)
ORDER BY bs.ID LIMIT 1
", []);
if (!$qFreeShard) {
apiAbort(['OK' => false, 'ERROR' => 'no_shards_available', 'MESSAGE' => 'No beacon shards available']);
}
$shardID = (int) $qFreeShard['ID'];
$qMaxMajor = queryOne("
SELECT COALESCE(MAX(BeaconMajor), 0) AS MaxMajor FROM Businesses WHERE BeaconShardID = ?
", [$shardID]);
$major = (int) $qMaxMajor['MaxMajor'] + 1;
queryTimed("UPDATE Businesses SET BeaconShardID = ?, BeaconMajor = ? WHERE ID = ?",
[$shardID, $major, $businessId]);
}
$qShard = queryOne("SELECT UUID FROM BeaconShards WHERE ID = ?", [$shardID]);
$shardUUID = $qShard['UUID'];
// Service point handling
$spName = trim($data['Name'] ?? '');
if ($spName === '') {
apiAbort(['OK' => false, 'ERROR' => 'missing_name', 'MESSAGE' => 'Service point name is required']);
}
$servicePointID = (int) ($data['ServicePointID'] ?? 0);
if ($servicePointID > 0) {
$qSP = queryOne("
SELECT ID, BeaconMinor FROM ServicePoints WHERE ID = ? AND BusinessID = ? LIMIT 1
", [$servicePointID, $businessId]);
if (!$qSP) {
apiAbort(['OK' => false, 'ERROR' => 'invalid_service_point', 'MESSAGE' => 'Service point not found']);
}
$minor = $qSP['BeaconMinor'];
if ($minor === null) {
$qMaxMinor = queryOne("
SELECT COALESCE(MAX(BeaconMinor), 0) AS MaxMinor FROM ServicePoints WHERE BusinessID = ?
", [$businessId]);
$minor = (int) $qMaxMinor['MaxMinor'] + 1;
}
queryTimed("UPDATE ServicePoints SET Name = ?, BeaconMinor = ?, IsActive = 1 WHERE ID = ?",
[$spName, $minor, $servicePointID]);
} else {
$qMaxMinor = queryOne("
SELECT COALESCE(MAX(BeaconMinor), 0) AS MaxMinor FROM ServicePoints WHERE BusinessID = ?
", [$businessId]);
$minor = (int) $qMaxMinor['MaxMinor'] + 1;
queryTimed("
INSERT INTO ServicePoints (BusinessID, Name, TypeID, IsActive, BeaconMinor, SortOrder)
VALUES (?, ?, 1, 1, ?, ?)
", [$businessId, $spName, $minor, $minor]);
$servicePointID = (int) lastInsertId();
}
jsonResponse([
'OK' => true,
'ERROR' => '',
'ServicePointID' => $servicePointID,
'ServicePointName' => $spName,
'BusinessID' => $businessId,
'BusinessName' => $qBiz['Name'],
'ShardID' => $shardID,
'UUID' => $shardUUID,
'Major' => $major,
'Minor' => (int) $minor,
]);