false, 'ERROR' => 'missing_business', 'MESSAGE' => 'BusinessID is required.']); } $rows = queryTimed(" SELECT t.ID AS TaskID, t.Title, t.CompletedOn, t.ClaimedByUserID, t.OrderID, u.FirstName AS WorkerFirstName, u.LastName AS WorkerLastName, cu.FirstName AS CustomerFirstName, cu.LastName AS CustomerLastName, sp.Name AS ServicePointName, (SELECT COUNT(*) FROM TaskRatings r WHERE r.TaskID = t.ID AND r.Direction = 'admin_rates_worker') AS HasAdminRating FROM Tasks t INNER JOIN Users u ON u.ID = t.ClaimedByUserID LEFT JOIN Orders o ON o.ID = t.OrderID LEFT JOIN Users cu ON cu.ID = o.UserID LEFT JOIN ServicePoints sp ON sp.ID = o.ServicePointID WHERE t.BusinessID = ? AND t.CompletedOn IS NOT NULL AND t.CompletedOn > DATE_SUB(NOW(), INTERVAL 7 DAY) AND t.ClaimedByUserID > 0 HAVING HasAdminRating = 0 ORDER BY t.CompletedOn DESC LIMIT 50 ", [$businessID]); $tasks = []; foreach ($rows as $r) { $taskTitle = $r['Title'] ?? ''; if ($taskTitle === '' && (int) ($r['OrderID'] ?? 0) > 0) $taskTitle = 'Order #' . $r['OrderID']; if ($taskTitle === '') $taskTitle = 'Task #' . $r['TaskID']; $tasks[] = [ 'TaskID' => (int) $r['TaskID'], 'Title' => $taskTitle, 'CompletedOn' => $r['CompletedOn'], 'WorkerUserID' => (int) $r['ClaimedByUserID'], 'WorkerName' => trim(($r['WorkerFirstName'] ?? '') . ' ' . ($r['WorkerLastName'] ?? '')), 'CustomerName' => !empty($r['CustomerFirstName']) ? trim($r['CustomerFirstName'] . ' ' . ($r['CustomerLastName'] ?? '')) : '', 'Name' => $r['ServicePointName'] ?? '', 'OrderID' => (int) ($r['OrderID'] ?? 0), ]; } jsonResponse(['OK' => true, 'TASKS' => $tasks]); } catch (Exception $e) { jsonResponse(['OK' => false, 'ERROR' => 'server_error', 'MESSAGE' => 'Error loading tasks', 'DETAIL' => $e->getMessage()]); }