From 66e441b29567aceec01e6fb5b3ed8802536407c0 Mon Sep 17 00:00:00 2001 From: John Mizerek Date: Tue, 17 Mar 2026 15:42:24 -0700 Subject: [PATCH] Add portal/getSettings and portal/updateSettings PHP endpoints Rewrites the last two production-critical CFM endpoints for the biz.payfrit.com Lucee removal project. Both endpoints follow the existing helpers.php patterns with queryTimed/queryOne and are added to PUBLIC_ROUTES. Co-Authored-By: Claude Opus 4.6 (1M context) --- api/helpers.php | 2 + api/portal/getSettings.php | 68 ++++++++++++++++ api/portal/updateSettings.php | 141 ++++++++++++++++++++++++++++++++++ 3 files changed, 211 insertions(+) create mode 100644 api/portal/getSettings.php create mode 100644 api/portal/updateSettings.php diff --git a/api/helpers.php b/api/helpers.php index aacab04..650a5e4 100644 --- a/api/helpers.php +++ b/api/helpers.php @@ -434,6 +434,8 @@ const PUBLIC_ROUTES = [ '/api/portal/searchUser.php', '/api/portal/addTeamMember.php', '/api/portal/reassign_employees.php', + '/api/portal/getSettings.php', + '/api/portal/updateSettings.php', // users '/api/users/search.php', // stations diff --git a/api/portal/getSettings.php b/api/portal/getSettings.php new file mode 100644 index 0000000..055fd4b --- /dev/null +++ b/api/portal/getSettings.php @@ -0,0 +1,68 @@ + false, 'ERROR' => 'no_business_selected']); +} + +try { + $biz = queryOne(" + SELECT ID, Name, TaxRate, Phone + FROM Businesses + WHERE ID = ? + LIMIT 1 + ", [$businessId]); + + if (!$biz) { + apiAbort(['OK' => false, 'ERROR' => 'business_not_found']); + } + + // Get address + $addr = queryOne(" + SELECT a.Line1, a.Line2, a.City, a.ZIPCode, s.Abbreviation AS State + FROM Addresses a + LEFT JOIN tt_States s ON s.ID = a.StateID + WHERE (a.BusinessID = ? OR a.ID = (SELECT AddressID FROM Businesses WHERE ID = ?)) + AND a.IsDeleted = 0 + LIMIT 1 + ", [$businessId, $businessId]); + + // Get owner email + $user = queryOne(" + SELECT ContactNumber, EmailAddress + FROM Users + WHERE ID = (SELECT UserID FROM Businesses WHERE ID = ?) + LIMIT 1 + ", [$businessId]); + + $taxRate = is_numeric($biz['TaxRate']) ? (float)$biz['TaxRate'] : 0; + + jsonResponse([ + 'OK' => true, + 'SETTINGS' => [ + 'BusinessID' => (int)$biz['ID'], + 'Name' => $biz['Name'], + 'TaxRate' => $taxRate, + 'TaxRatePercent' => $taxRate * 100, + 'Address' => $addr['Line1'] ?? '', + 'City' => $addr['City'] ?? '', + 'State' => $addr['State'] ?? '', + 'Zip' => $addr['ZIPCode'] ?? '', + 'Phone' => $biz['Phone'] ?? '', + 'Email' => $user['EmailAddress'] ?? '', + ], + ]); + +} catch (Throwable $e) { + apiAbort(['OK' => false, 'ERROR' => 'server_error', 'MESSAGE' => $e->getMessage()]); +} diff --git a/api/portal/updateSettings.php b/api/portal/updateSettings.php new file mode 100644 index 0000000..760a434 --- /dev/null +++ b/api/portal/updateSettings.php @@ -0,0 +1,141 @@ + false, 'ERROR' => 'no_business_selected']); +} + +try { + $data = readJsonBody(); + if (empty($data)) { + apiAbort(['OK' => false, 'ERROR' => 'missing_body']); + } + + $updates = []; + $params = []; + + // Handle tax rate (accept either percent or decimal) + if (isset($data['TaxRatePercent']) && is_numeric($data['TaxRatePercent'])) { + $taxRate = $data['TaxRatePercent'] / 100; + if ($taxRate < 0 || $taxRate > 0.5) { + apiAbort(['OK' => false, 'ERROR' => 'invalid_tax_rate', 'MESSAGE' => 'Tax rate must be between 0% and 50%']); + } + $updates[] = 'TaxRate = ?'; + $params[] = $taxRate; + } elseif (isset($data['TaxRate']) && is_numeric($data['TaxRate'])) { + $taxRate = (float)$data['TaxRate']; + if ($taxRate < 0 || $taxRate > 0.5) { + apiAbort(['OK' => false, 'ERROR' => 'invalid_tax_rate', 'MESSAGE' => 'Tax rate must be between 0 and 0.5']); + } + $updates[] = 'TaxRate = ?'; + $params[] = $taxRate; + } + + if (!empty($data['Name']) && trim($data['Name']) !== '') { + $updates[] = 'Name = ?'; + $params[] = substr(trim($data['Name']), 0, 100); + } + + if (array_key_exists('Phone', $data)) { + $updates[] = 'Phone = ?'; + $params[] = substr(trim($data['Phone']), 0, 20); + } + + // Address fields + $addrFields = []; + if (!empty($data['Address'])) $addrFields['Line1'] = substr(trim($data['Address']), 0, 100); + if (array_key_exists('City', $data)) $addrFields['City'] = substr(trim($data['City']), 0, 50); + if (array_key_exists('Zip', $data)) $addrFields['ZIPCode'] = substr(trim($data['Zip']), 0, 10); + + if (empty($updates) && empty($addrFields)) { + apiAbort(['OK' => false, 'ERROR' => 'no_fields', 'MESSAGE' => 'No valid fields to update']); + } + + // Update Businesses table + if (!empty($updates)) { + $params[] = $businessId; + $sql = 'UPDATE Businesses SET ' . implode(', ', $updates) . ' WHERE ID = ?'; + queryTimed($sql, $params); + } + + // Update address + if (!empty($addrFields)) { + $existingAddr = queryOne(" + SELECT ID FROM Addresses + WHERE (BusinessID = ? OR ID = (SELECT AddressID FROM Businesses WHERE ID = ?)) + AND IsDeleted = 0 + LIMIT 1 + ", [$businessId, $businessId]); + + if ($existingAddr) { + $addrUpdates = []; + $addrParams = []; + if (isset($addrFields['Line1'])) { $addrUpdates[] = 'Line1 = ?'; $addrParams[] = $addrFields['Line1']; } + if (isset($addrFields['City'])) { $addrUpdates[] = 'City = ?'; $addrParams[] = $addrFields['City']; } + if (isset($addrFields['ZIPCode'])) { $addrUpdates[] = 'ZIPCode = ?'; $addrParams[] = $addrFields['ZIPCode']; } + if (!empty($addrUpdates)) { + $addrParams[] = $existingAddr['ID']; + queryTimed('UPDATE Addresses SET ' . implode(', ', $addrUpdates) . ' WHERE ID = ?', $addrParams); + } + } + } + + // Return updated settings + $biz = queryOne(" + SELECT ID, Name, TaxRate, Phone + FROM Businesses + WHERE ID = ? + LIMIT 1 + ", [$businessId]); + + $addr = queryOne(" + SELECT a.Line1, a.City, a.ZIPCode, s.Abbreviation AS State + FROM Addresses a + LEFT JOIN tt_States s ON s.ID = a.StateID + WHERE (a.BusinessID = ? OR a.ID = (SELECT AddressID FROM Businesses WHERE ID = ?)) + AND a.IsDeleted = 0 + LIMIT 1 + ", [$businessId, $businessId]); + + $taxRate = is_numeric($biz['TaxRate']) ? (float)$biz['TaxRate'] : 0; + + jsonResponse([ + 'OK' => true, + 'MESSAGE' => 'Settings updated', + 'SETTINGS' => [ + 'BusinessID' => (int)$biz['ID'], + 'Name' => $biz['Name'], + 'TaxRate' => $taxRate, + 'TaxRatePercent' => $taxRate * 100, + 'Address' => $addr['Line1'] ?? '', + 'City' => $addr['City'] ?? '', + 'State' => $addr['State'] ?? '', + 'Zip' => $addr['ZIPCode'] ?? '', + 'Phone' => $biz['Phone'] ?? '', + 'Email' => '', + ], + ]); + +} catch (Throwable $e) { + apiAbort(['OK' => false, 'ERROR' => 'server_error', 'MESSAGE' => $e->getMessage()]); +}