false, 'ERROR' => 'missing_params', 'MESSAGE' => 'BusinessID is required.']); } try { // Get business name $qBusiness = queryOne("SELECT Name FROM Businesses WHERE ID = ?", [$businessID]); $businessName = $qBusiness ? $qBusiness['Name'] : ''; // Build WHERE clause $where = "t.BusinessID = ? AND t.ClaimedByUserID = 0 AND t.CompletedOn IS NULL"; $params = [$businessID]; if ($taskTypeID > 0) { $where .= " AND t.TaskTypeID = ?"; $params[] = $taskTypeID; } $qTasks = queryTimed(" SELECT t.ID, t.BusinessID, t.OrderID, t.TaskTypeID, t.Title, t.Details, t.CreatedOn, t.ClaimedByUserID, t.UserID, tt.Name AS TaskTypeName, tt.Icon AS TaskTypeIcon, tt.Color AS TaskTypeColor, 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 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.CreatedOn ASC ", $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'], 'TaskTypeID' => (int) $row['TaskTypeID'], 'Title' => $taskTitle, 'Details' => !empty(trim($row['Details'] ?? '')) ? $row['Details'] : '', 'CreatedOn' => toISO8601($row['CreatedOn']), 'StatusID' => (int) $row['ClaimedByUserID'] > 0 ? 1 : 0, '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), 'BUSINESS_NAME' => $businessName, ]); } catch (Exception $e) { jsonResponse(['OK' => false, 'ERROR' => 'server_error', 'MESSAGE' => 'Error loading tasks', 'DETAIL' => $e->getMessage()]); }