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()]); }