payfrit-api/api/orders/getDetail.php
John Mizerek 1f81d98c52 Initial PHP API migration from CFML
Complete port of all 163 API endpoints from Lucee/CFML to PHP 8.3.
Shared helpers in api/helpers.php (DB, auth, request/response, security).
PDO prepared statements throughout. Same JSON response shapes as CFML.
2026-03-14 14:26:59 -07:00

186 lines
6.3 KiB
PHP

<?php
require_once __DIR__ . '/../helpers.php';
runAuth();
/**
* Get Order Detail
* GET: ?OrderID=123
* POST: { OrderID: 123 }
*/
function getStatusText(int $status): string {
return match ($status) {
0 => '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,
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;
$total = $subtotal + $tax + $tip;
// 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,
'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);