false, 'ERROR' => 'missing_business_id', 'MESSAGE' => 'BusinessID is required']); } $action = strtolower($data['action'] ?? 'list'); try { switch ($action) { case 'list': $qMenus = queryTimed(" SELECT ID, Name, Description, DaysActive, StartTime, EndTime, SortOrder, IsActive FROM Menus WHERE BusinessID = ? AND IsActive = 1 ORDER BY SortOrder, Name ", [$businessID]); $menus = []; foreach ($qMenus as $m) { $catCount = queryOne(" SELECT COUNT(*) as cnt FROM Categories WHERE BusinessID = ? AND MenuID = ? ", [$businessID, $m['ID']]); $menus[] = [ 'MenuID' => (int) $m['ID'], 'Name' => $m['Name'], 'Description' => $m['Description'] ?? '', 'DaysActive' => (int) $m['DaysActive'], 'StartTime' => !empty($m['StartTime']) ? (new DateTime($m['StartTime']))->format('H:i') : '', 'EndTime' => !empty($m['EndTime']) ? (new DateTime($m['EndTime']))->format('H:i') : '', 'SortOrder' => (int) $m['SortOrder'], 'CategoryCount' => (int) $catCount['cnt'], ]; } jsonResponse(['OK' => true, 'MENUS' => $menus, 'COUNT' => count($menus)]); case 'get': $menuID = (int) ($data['MenuID'] ?? 0); if ($menuID === 0) { apiAbort(['OK' => false, 'ERROR' => 'missing_menu_id', 'MESSAGE' => 'MenuID is required']); } $menu = queryOne("SELECT * FROM Menus WHERE ID = ? AND BusinessID = ?", [$menuID, $businessID]); if (!$menu) { apiAbort(['OK' => false, 'ERROR' => 'menu_not_found', 'MESSAGE' => 'Menu not found']); } jsonResponse(['OK' => true, 'MENU' => [ 'MenuID' => (int) $menu['ID'], 'Name' => $menu['Name'], 'Description' => $menu['Description'] ?? '', 'DaysActive' => (int) $menu['DaysActive'], 'StartTime' => !empty($menu['StartTime']) ? (new DateTime($menu['StartTime']))->format('H:i') : '', 'EndTime' => !empty($menu['EndTime']) ? (new DateTime($menu['EndTime']))->format('H:i') : '', 'SortOrder' => (int) $menu['SortOrder'], 'IsActive' => (int) $menu['IsActive'], ]]); case 'save': $menuID = (int) ($data['MenuID'] ?? 0); $menuName = trim($data['Name'] ?? ''); $menuDescription = trim($data['Description'] ?? ''); $menuDaysActive = (int) ($data['DaysActive'] ?? 127); $menuStartTime = !empty($data['StartTime']) ? trim($data['StartTime']) : null; $menuEndTime = !empty($data['EndTime']) ? trim($data['EndTime']) : null; $menuSortOrder = (int) ($data['SortOrder'] ?? 0); if ($menuName === '') { apiAbort(['OK' => false, 'ERROR' => 'missing_menu_name', 'MESSAGE' => 'Menu name is required']); } if ($menuID > 0) { queryTimed(" UPDATE Menus SET Name = ?, Description = ?, DaysActive = ?, StartTime = ?, EndTime = ?, SortOrder = ? WHERE ID = ? AND BusinessID = ? ", [$menuName, $menuDescription, $menuDaysActive, $menuStartTime, $menuEndTime, $menuSortOrder, $menuID, $businessID]); jsonResponse(['OK' => true, 'MenuID' => $menuID, 'ACTION' => 'updated']); } else { queryTimed(" INSERT INTO Menus ( BusinessID, Name, Description, DaysActive, StartTime, EndTime, SortOrder, IsActive, AddedOn ) VALUES (?, ?, ?, ?, ?, ?, ?, 1, NOW()) ", [$businessID, $menuName, $menuDescription, $menuDaysActive, $menuStartTime, $menuEndTime, $menuSortOrder]); $newID = (int) lastInsertId(); jsonResponse(['OK' => true, 'MenuID' => $newID, 'ACTION' => 'created']); } case 'delete': $menuID = (int) ($data['MenuID'] ?? 0); if ($menuID === 0) { apiAbort(['OK' => false, 'ERROR' => 'missing_menu_id', 'MESSAGE' => 'MenuID is required']); } $catCheck = queryOne(" SELECT COUNT(*) as cnt FROM Categories WHERE MenuID = ? AND BusinessID = ? ", [$menuID, $businessID]); if ((int) $catCheck['cnt'] > 0) { queryTimed(" UPDATE Categories SET MenuID = 0 WHERE MenuID = ? AND BusinessID = ? ", [$menuID, $businessID]); } queryTimed(" UPDATE Menus SET IsActive = 0 WHERE ID = ? AND BusinessID = ? ", [$menuID, $businessID]); jsonResponse([ 'OK' => true, 'MenuID' => $menuID, 'ACTION' => 'deleted', 'CategoriesUnassigned' => (int) $catCheck['cnt'], ]); case 'reorder': $menuOrder = $data['MenuOrder'] ?? []; if (!is_array($menuOrder) || count($menuOrder) === 0) { apiAbort(['OK' => false, 'ERROR' => 'missing_menu_order', 'MESSAGE' => 'MenuOrder array is required']); } foreach ($menuOrder as $i => $id) { queryTimed(" UPDATE Menus SET SortOrder = ? WHERE ID = ? AND BusinessID = ? ", [$i, (int) $id, $businessID]); } jsonResponse(['OK' => true, 'ACTION' => 'reordered']); case 'setdefault': $menuID = (int) ($data['MenuID'] ?? 0); if ($menuID > 0) { $check = queryOne(" SELECT ID FROM Menus WHERE ID = ? AND BusinessID = ? AND IsActive = 1 ", [$menuID, $businessID]); if (!$check) { apiAbort(['OK' => false, 'ERROR' => 'invalid_menu', 'MESSAGE' => 'Menu not found or not active']); } } queryTimed(" UPDATE Businesses SET DefaultMenuID = ? WHERE ID = ? ", [$menuID === 0 ? null : $menuID, $businessID]); jsonResponse(['OK' => true, 'ACTION' => 'defaultSet', 'DefaultMenuID' => $menuID]); default: apiAbort(['OK' => false, 'ERROR' => 'invalid_action', 'MESSAGE' => 'Unknown action: ' . $action]); } } catch (Exception $e) { jsonResponse(['OK' => false, 'ERROR' => 'server_error', 'MESSAGE' => $e->getMessage(), 'DETAIL' => '']); }