false, 'ERROR' => 'missing_params', 'MESSAGE' => 'UserID is required.']); } try { $where = "t.ClaimedByUserID = ?"; $params = [$userID]; if ($businessID > 0) { $where .= " AND t.BusinessID = ?"; $params[] = $businessID; } switch ($filterType) { case 'active': $where .= " AND t.CompletedOn IS NULL"; break; case 'completed': $where .= " AND t.CompletedOn IS NOT NULL"; break; case 'today': $where .= " AND DATE(t.ClaimedOn) = CURDATE()"; break; case 'week': $where .= " AND t.ClaimedOn >= DATE_SUB(CURDATE(), INTERVAL 7 DAY)"; break; } $qTasks = queryTimed(" SELECT t.ID, t.BusinessID, t.OrderID, t.TaskTypeID, t.Title, t.Details, t.CreatedOn, t.ClaimedByUserID, t.ClaimedOn, t.CompletedOn, t.UserID, tt.Name AS TaskTypeName, tt.Icon AS TaskTypeIcon, tt.Color AS TaskTypeColor, b.Name AS BusinessName, t.ServicePointID, sp.Name AS ServicePointName, u.FirstName AS CustomerFirstName, u.LastName AS CustomerLastName FROM Tasks t LEFT JOIN tt_TaskTypes tt ON tt.ID = t.TaskTypeID LEFT JOIN Businesses b ON b.ID = t.BusinessID LEFT JOIN Orders o ON o.ID = t.OrderID LEFT JOIN ServicePoints sp ON sp.ID = COALESCE(t.ServicePointID, o.ServicePointID) LEFT JOIN Users u ON u.ID = t.UserID WHERE $where ORDER BY t.ClaimedOn DESC ", $params); $tasks = []; foreach ($qTasks as $row) { $taskTitle = !empty(trim($row['Title'] ?? '')) ? $row['Title'] : ((int) $row['OrderID'] > 0 ? "Order #" . $row['OrderID'] : "Task #" . $row['ID']); $customerName = ''; if (!empty(trim($row['CustomerFirstName'] ?? ''))) { $customerName = $row['CustomerFirstName']; if (!empty(trim($row['CustomerLastName'] ?? ''))) { $customerName .= ' ' . $row['CustomerLastName']; } } $tasks[] = [ 'TaskID' => (int) $row['ID'], 'BusinessID' => (int) $row['BusinessID'], 'BusinessName' => $row['BusinessName'] ?? '', 'TaskTypeID' => (int) $row['TaskTypeID'], 'Title' => $taskTitle, 'Details' => !empty(trim($row['Details'] ?? '')) ? $row['Details'] : '', 'CreatedOn' => toISO8601($row['CreatedOn']), 'ClaimedOn' => toISO8601($row['ClaimedOn'] ?? ''), 'CompletedOn' => toISO8601($row['CompletedOn'] ?? ''), 'StatusID' => empty(trim($row['CompletedOn'] ?? '')) ? 1 : 3, 'SourceType' => 'order', 'SourceID' => (int) $row['OrderID'], 'TaskTypeName' => !empty(trim($row['TaskTypeName'] ?? '')) ? $row['TaskTypeName'] : '', 'TaskTypeIcon' => !empty(trim($row['TaskTypeIcon'] ?? '')) ? $row['TaskTypeIcon'] : 'notifications', 'TaskTypeColor' => !empty(trim($row['TaskTypeColor'] ?? '')) ? $row['TaskTypeColor'] : '#9C27B0', 'ServicePointID' => (int) ($row['ServicePointID'] ?? 0), 'ServicePointName' => $row['ServicePointName'] ?? '', 'CustomerID' => (int) ($row['UserID'] ?? 0), 'CustomerName' => $customerName, 'OrderTotal' => 0, ]; } // Calculate OrderTotal for tasks with linked orders foreach ($tasks as &$task) { if ((int) $task['SourceID'] > 0) { $qOT = queryOne(" SELECT SUM(oli.Price * oli.Quantity) AS Subtotal, o.TipAmount, o.DeliveryFee, o.OrderTypeID, b.TaxRate, b.PayfritFee FROM Orders o INNER JOIN Businesses b ON b.ID = o.BusinessID LEFT JOIN OrderLineItems oli ON oli.OrderID = o.ID AND oli.IsDeleted = 0 WHERE o.ID = ? GROUP BY o.ID ", [$task['SourceID']]); if ($qOT) { $sub = (float) $qOT['Subtotal']; $feeRate = (is_numeric($qOT['PayfritFee']) && (float) $qOT['PayfritFee'] > 0) ? (float) $qOT['PayfritFee'] : 0.05; $total = $sub + ($sub * (float) $qOT['TaxRate']) + (float) $qOT['TipAmount'] + (((int) $qOT['OrderTypeID'] === 3) ? (float) $qOT['DeliveryFee'] : 0) + ($sub * $feeRate); $task['OrderTotal'] = number_format($total, 2, '.', ''); } } } unset($task); jsonResponse([ 'OK' => true, 'ERROR' => '', 'TASKS' => $tasks, 'COUNT' => count($tasks), ]); } catch (Exception $e) { jsonResponse(['OK' => false, 'ERROR' => 'server_error', 'MESSAGE' => 'Error loading tasks', 'DETAIL' => $e->getMessage()]); }