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.
150 lines
5.4 KiB
PHP
150 lines
5.4 KiB
PHP
<?php
|
|
require_once __DIR__ . '/../helpers.php';
|
|
runAuth();
|
|
|
|
/**
|
|
* Get Business Details
|
|
* POST: { BusinessID: int }
|
|
*/
|
|
|
|
$data = readJsonBody();
|
|
$businessID = (int) ($data['BusinessID'] ?? 0);
|
|
|
|
if ($businessID <= 0) {
|
|
apiAbort(['OK' => false, 'ERROR' => 'BusinessID is required']);
|
|
}
|
|
|
|
try {
|
|
$q = queryOne("
|
|
SELECT
|
|
ID, Name, Phone, StripeAccountID, StripeOnboardingComplete,
|
|
IsHiring, HeaderImageExtension, TaxRate, BrandColor, BrandColorLight,
|
|
SessionEnabled, SessionLockMinutes, SessionPaymentStrategy,
|
|
TabMinAuthAmount, TabDefaultAuthAmount, TabMaxAuthAmount,
|
|
TabAutoIncreaseThreshold, TabMaxMembers, TabApprovalRequired,
|
|
OrderTypes
|
|
FROM Businesses
|
|
WHERE ID = ?
|
|
", [$businessID]);
|
|
|
|
if (!$q) {
|
|
apiAbort(['OK' => false, 'ERROR' => 'Business not found']);
|
|
}
|
|
|
|
// Get address
|
|
$qAddr = queryOne("
|
|
SELECT a.Line1 AS AddressLine1, a.Line2 AS AddressLine2,
|
|
a.City AS AddressCity, a.ZIPCode AS AddressZIPCode,
|
|
s.Abbreviation
|
|
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]);
|
|
|
|
$addressStr = '';
|
|
$addressLine1 = '';
|
|
$addressCity = '';
|
|
$addressState = '';
|
|
$addressZip = '';
|
|
|
|
if ($qAddr) {
|
|
$addressLine1 = $qAddr['AddressLine1'] ?? '';
|
|
$addressCity = $qAddr['AddressCity'] ?? '';
|
|
$addressState = $qAddr['Abbreviation'] ?? '';
|
|
$addressZip = $qAddr['AddressZIPCode'] ?? '';
|
|
|
|
$parts = [];
|
|
if (!empty($qAddr['AddressLine1'])) $parts[] = $qAddr['AddressLine1'];
|
|
if (!empty($qAddr['AddressLine2'])) $parts[] = $qAddr['AddressLine2'];
|
|
$csz = [];
|
|
if (!empty($qAddr['AddressCity'])) $csz[] = $qAddr['AddressCity'];
|
|
if (!empty($qAddr['Abbreviation'])) $csz[] = $qAddr['Abbreviation'];
|
|
if (!empty($qAddr['AddressZIPCode'])) $csz[] = $qAddr['AddressZIPCode'];
|
|
if ($csz) $parts[] = implode(', ', $csz);
|
|
$addressStr = implode(', ', $parts);
|
|
}
|
|
|
|
// Get hours
|
|
$qHours = queryTimed("
|
|
SELECT h.DayID, h.OpenTime, h.ClosingTime, d.Abbrev
|
|
FROM Hours h
|
|
JOIN tt_Days d ON d.ID = h.DayID
|
|
WHERE h.BusinessID = ?
|
|
ORDER BY h.DayID
|
|
", [$businessID]);
|
|
|
|
$hoursArr = [];
|
|
$hoursStr = '';
|
|
if ($qHours) {
|
|
foreach ($qHours as $h) {
|
|
$open = (new DateTime($h['OpenTime']))->format('g:i A');
|
|
$close = (new DateTime($h['ClosingTime']))->format('g:i A');
|
|
$hoursArr[] = [
|
|
'day' => $h['Abbrev'],
|
|
'dayId' => (int) $h['DayID'],
|
|
'open' => $open,
|
|
'close' => $close,
|
|
];
|
|
}
|
|
// Group similar hours
|
|
$hourGroups = [];
|
|
foreach ($hoursArr as $h) {
|
|
$key = $h['open'] . '-' . $h['close'];
|
|
$hourGroups[$key][] = $h['day'];
|
|
}
|
|
$hourStrParts = [];
|
|
foreach ($hourGroups as $key => $days) {
|
|
$hourStrParts[] = implode(',', $days) . ': ' . $key;
|
|
}
|
|
$hoursStr = implode(', ', $hourStrParts);
|
|
}
|
|
|
|
// Prefix hex colors with #
|
|
$brandColor = $q['BrandColor'] ?? '';
|
|
if ($brandColor !== '' && $brandColor[0] !== '#') $brandColor = '#' . $brandColor;
|
|
|
|
$brandColorLight = $q['BrandColorLight'] ?? '';
|
|
if ($brandColorLight !== '' && $brandColorLight[0] !== '#') $brandColorLight = '#' . $brandColorLight;
|
|
|
|
$taxRate = is_numeric($q['TaxRate']) ? (float) $q['TaxRate'] : 0;
|
|
|
|
$business = [
|
|
'BusinessID' => (int) $q['ID'],
|
|
'Name' => $q['Name'],
|
|
'Address' => $addressStr,
|
|
'Line1' => $addressLine1,
|
|
'City' => $addressCity,
|
|
'AddressState' => $addressState,
|
|
'AddressZip' => $addressZip,
|
|
'Phone' => $q['Phone'] ?? '',
|
|
'Hours' => $hoursStr,
|
|
'HoursDetail' => $hoursArr,
|
|
'StripeConnected' => (!empty($q['StripeAccountID']) && ($q['StripeOnboardingComplete'] ?? 0) == 1),
|
|
'IsHiring' => ($q['IsHiring'] ?? 0) == 1,
|
|
'TaxRate' => $taxRate,
|
|
'TaxRatePercent' => $taxRate * 100,
|
|
'BrandColor' => $brandColor,
|
|
'BrandColorLight' => $brandColorLight,
|
|
'SessionEnabled' => (int) ($q['SessionEnabled'] ?? 0),
|
|
'SessionLockMinutes' => (int) ($q['SessionLockMinutes'] ?? 30),
|
|
'SessionPaymentStrategy' => !empty($q['SessionPaymentStrategy']) ? $q['SessionPaymentStrategy'] : 'A',
|
|
'TabMinAuthAmount' => (float) ($q['TabMinAuthAmount'] ?? 50.00),
|
|
'TabDefaultAuthAmount' => (float) ($q['TabDefaultAuthAmount'] ?? 150.00),
|
|
'TabMaxAuthAmount' => (float) ($q['TabMaxAuthAmount'] ?? 1000.00),
|
|
'TabAutoIncreaseThreshold' => (float) ($q['TabAutoIncreaseThreshold'] ?? 0.80),
|
|
'TabMaxMembers' => (int) ($q['TabMaxMembers'] ?? 10),
|
|
'TabApprovalRequired' => (int) ($q['TabApprovalRequired'] ?? 1),
|
|
'OrderTypes' => !empty($q['OrderTypes']) ? $q['OrderTypes'] : '1',
|
|
];
|
|
|
|
if (!empty($q['HeaderImageExtension'])) {
|
|
$business['HeaderImageURL'] = '/uploads/headers/' . $q['ID'] . '.' . $q['HeaderImageExtension'];
|
|
}
|
|
|
|
jsonResponse(['OK' => true, 'BUSINESS' => $business]);
|
|
|
|
} catch (Exception $e) {
|
|
jsonResponse(['OK' => false, 'ERROR' => $e->getMessage()]);
|
|
}
|