'Cart', 1 => 'Submitted', 2 => 'In Progress', 3 => 'Ready', 4 => 'On the Way', 5 => 'Complete', 6 => 'Cancelled', 7 => 'Deleted', default => 'Unknown', }; } function getOrderTypeName(int $orderType): string { return match ($orderType) { 1 => 'Dine-in', 2 => 'Takeaway', 3 => 'Delivery', default => 'Unknown', }; } $response = ['OK' => false]; try { // Get OrderID from GET or POST $orderID = (int) ($_GET['OrderID'] ?? 0); if ($orderID === 0) { $data = readJsonBody(); $orderID = (int) ($data['OrderID'] ?? 0); } if ($orderID === 0) { $response['ERROR'] = 'missing_order_id'; $response['MESSAGE'] = 'OrderID is required'; jsonResponse($response); } $qOrder = queryOne(" SELECT o.ID, o.UUID, o.BusinessID, o.UserID, o.ServicePointID, o.StatusID, o.OrderTypeID, o.Remarks, o.AddedOn, o.LastEditedOn, o.SubmittedOn, o.TipAmount, o.PlatformFee, u.FirstName, u.LastName, u.ContactNumber, u.EmailAddress, sp.Name AS Name, sp.TypeID AS TypeID, b.Name AS BizName, b.TaxRate FROM Orders o LEFT JOIN Users u ON u.ID = o.UserID LEFT JOIN ServicePoints sp ON sp.ID = o.ServicePointID LEFT JOIN Businesses b ON b.ID = o.BusinessID WHERE o.ID = ? ", [$orderID]); if (!$qOrder) { $response['ERROR'] = 'order_not_found'; $response['MESSAGE'] = 'Order not found'; jsonResponse($response); } // Get line items $qItems = queryTimed(" SELECT oli.ID, oli.ItemID, oli.ParentOrderLineItemID, oli.Quantity, oli.Price, oli.Remark, i.Name, i.Price AS ItemPrice, i.IsCheckedByDefault FROM OrderLineItems oli INNER JOIN Items i ON i.ID = oli.ItemID WHERE oli.OrderID = ? AND oli.IsDeleted = 0 ORDER BY oli.ID ", [$orderID]); // Build hierarchy $itemsById = []; foreach ($qItems as $row) { $itemsById[(int) $row['ID']] = [ 'LineItemID' => (int) $row['ID'], 'ItemID' => (int) $row['ItemID'], 'ParentLineItemID' => (int) $row['ParentOrderLineItemID'], 'Name' => $row['Name'] ?? '', 'Quantity' => (int) $row['Quantity'], 'UnitPrice' => (float) $row['Price'], 'Remarks' => $row['Remark'] ?? '', 'IsDefault' => ((int) $row['IsCheckedByDefault'] === 1), 'Modifiers' => [], ]; } $lineItems = []; foreach ($qItems as $row) { $id = (int) $row['ID']; $parentID = (int) $row['ParentOrderLineItemID']; if ($parentID > 0 && isset($itemsById[$parentID])) { $itemsById[$parentID]['Modifiers'][] = &$itemsById[$id]; } else { $lineItems[] = &$itemsById[$id]; } } unset($id); // break reference // Calculate subtotal $subtotal = 0; foreach ($lineItems as $item) { $itemTotal = $item['UnitPrice'] * $item['Quantity']; foreach ($item['Modifiers'] as $mod) { $itemTotal += $mod['UnitPrice'] * $mod['Quantity']; } $subtotal += $itemTotal; } $taxRate = (is_numeric($qOrder['TaxRate']) && (float) $qOrder['TaxRate'] > 0) ? (float) $qOrder['TaxRate'] : 0; $tax = $subtotal * $taxRate; $tip = is_numeric($qOrder['TipAmount']) ? (float) $qOrder['TipAmount'] : 0; $platformFee = is_numeric($qOrder['PlatformFee']) ? (float) $qOrder['PlatformFee'] : 0; $total = $subtotal + $tax + $tip + $platformFee; // Get staff who worked on this order $qStaff = queryTimed(" SELECT DISTINCT u.ID, u.FirstName, (SELECT r.AccessToken FROM TaskRatings r INNER JOIN Tasks t2 ON t2.ID = r.TaskID WHERE t2.OrderID = ? AND r.ForUserID = u.ID AND r.Direction = 'customer_rates_worker' AND r.CompletedOn IS NULL AND r.ExpiresOn > NOW() LIMIT 1) AS RatingToken FROM Tasks t INNER JOIN Users u ON u.ID = t.ClaimedByUserID WHERE t.OrderID = ? AND t.ClaimedByUserID > 0 ", [$orderID, $orderID]); $staff = []; foreach ($qStaff as $row) { $staff[] = [ 'UserID' => (int) $row['ID'], 'FirstName' => $row['FirstName'], 'AvatarUrl' => baseUrl() . '/uploads/users/' . $row['ID'] . '.jpg', 'RatingToken' => $row['RatingToken'] ?? '', ]; } $statusID = (int) $qOrder['StatusID']; $orderTypeID = (int) ($qOrder['OrderTypeID'] ?? 0); $response['OK'] = true; $response['ORDER'] = [ 'OrderID' => (int) $qOrder['ID'], 'UUID' => $qOrder['UUID'] ?? '', 'BusinessID' => (int) $qOrder['BusinessID'], 'Name' => $qOrder['BizName'] ?? '', 'Status' => $statusID, 'StatusText' => getStatusText($statusID), 'OrderTypeID' => $orderTypeID, 'OrderTypeName' => getOrderTypeName($orderTypeID), 'Subtotal' => $subtotal, 'Tax' => $tax, 'Tip' => $tip, 'PlatformFee' => $platformFee, 'Total' => $total, 'Notes' => $qOrder['Remarks'], 'CreatedOn' => toISO8601($qOrder['AddedOn']), 'SubmittedOn' => !empty($qOrder['SubmittedOn']) ? toISO8601($qOrder['SubmittedOn']) : '', 'UpdatedOn' => !empty($qOrder['LastEditedOn']) ? toISO8601($qOrder['LastEditedOn']) : '', 'Customer' => [ 'UserID' => (int) $qOrder['UserID'], 'FirstName' => $qOrder['FirstName'], 'LastName' => $qOrder['LastName'], 'Phone' => $qOrder['ContactNumber'], 'Email' => $qOrder['EmailAddress'], ], 'ServicePoint' => [ 'ServicePointID' => (int) ($qOrder['ServicePointID'] ?? 0), 'Name' => $qOrder['Name'] ?? '', 'TypeID' => (int) ($qOrder['TypeID'] ?? 0), ], 'LineItems' => $lineItems, 'Staff' => $staff, ]; } catch (Exception $e) { $response['ERROR'] = 'server_error'; $response['MESSAGE'] = $e->getMessage(); } jsonResponse($response);