/** * Get Order Detail * Returns full order info including line items and customer details * * GET: ?OrderID=123 * POST: { OrderID: 123 } */ response = { "OK": false }; try { // Get OrderID from request orderID = 0; // Check URL params if (structKeyExists(url, "OrderID")) { orderID = val(url.OrderID); } // Check POST body if (orderID == 0) { requestBody = toString(getHttpRequestData().content); if (len(requestBody)) { requestData = deserializeJSON(requestBody); if (structKeyExists(requestData, "OrderID")) { orderID = val(requestData.OrderID); } } } if (orderID == 0) { response["ERROR"] = "missing_order_id"; response["MESSAGE"] = "OrderID is required"; writeOutput(serializeJSON(response)); abort; } // Get order details qOrder = queryExecute(" SELECT o.OrderID, o.OrderBusinessID, o.OrderUserID, o.OrderServicePointID, o.OrderStatusID, o.OrderRemarks, o.OrderAddedOn, o.OrderLastEditedOn, u.UserFirstName, u.UserLastName, u.UserContactNumber, u.UserEmailAddress, sp.ServicePointName, sp.ServicePointTypeID FROM Orders o LEFT JOIN Users u ON u.UserID = o.OrderUserID LEFT JOIN ServicePoints sp ON sp.ServicePointID = o.OrderServicePointID WHERE o.OrderID = :orderID ", { orderID: orderID }); if (qOrder.recordCount == 0) { response["ERROR"] = "order_not_found"; response["MESSAGE"] = "Order not found"; writeOutput(serializeJSON(response)); abort; } // Get line items qItems = queryExecute(" SELECT oli.OrderLineItemID, oli.OrderLineItemItemID, oli.OrderLineItemParentOrderLineItemID, oli.OrderLineItemQuantity, oli.OrderLineItemPrice, oli.OrderLineItemRemark, i.ItemName, i.ItemPrice FROM OrderLineItems oli INNER JOIN Items i ON i.ItemID = oli.OrderLineItemItemID WHERE oli.OrderLineItemOrderID = :orderID ORDER BY oli.OrderLineItemID ", { orderID: orderID }); // Build line items array with parent-child structure lineItems = []; itemsById = {}; // First pass: create all items for (row in qItems) { item = { "LineItemID": row.OrderLineItemID, "ItemID": row.OrderLineItemItemID, "ParentLineItemID": row.OrderLineItemParentOrderLineItemID, "ItemName": row.ItemName, "Quantity": row.OrderLineItemQuantity, "UnitPrice": row.OrderLineItemPrice, "Remarks": row.OrderLineItemRemark, "Modifiers": [] }; itemsById[row.OrderLineItemID] = item; } // Second pass: build hierarchy for (row in qItems) { item = itemsById[row.OrderLineItemID]; parentID = row.OrderLineItemParentOrderLineItemID; if (parentID > 0 && structKeyExists(itemsById, parentID)) { // This is a modifier - add to parent arrayAppend(itemsById[parentID].Modifiers, item); } else { // This is a top-level item arrayAppend(lineItems, item); } } // Calculate subtotal from root line items subtotal = 0; for (item in lineItems) { itemTotal = item.UnitPrice * item.Quantity; // Add modifier prices for (mod in item.Modifiers) { itemTotal += mod.UnitPrice * mod.Quantity; } subtotal += itemTotal; } // Calculate tax (assume 8.75% if not stored) taxRate = 0.0875; tax = subtotal * taxRate; // Look up tip from Payments table if exists tip = 0; try { qPayment = queryExecute(" SELECT PaymentTipAmount FROM Payments WHERE PaymentOrderID = :orderID LIMIT 1 ", { orderID: orderID }); if (qPayment.recordCount > 0 && !isNull(qPayment.PaymentTipAmount)) { tip = qPayment.PaymentTipAmount; } } catch (any e) { // Payments table may not exist or have this column, ignore } // Calculate total total = subtotal + tax + tip; // Build response order = { "OrderID": qOrder.OrderID, "BusinessID": qOrder.OrderBusinessID, "Status": qOrder.OrderStatusID, "StatusText": getStatusText(qOrder.OrderStatusID), "Subtotal": subtotal, "Tax": tax, "Tip": tip, "Total": total, "Notes": qOrder.OrderRemarks, "CreatedOn": dateTimeFormat(qOrder.OrderAddedOn, "yyyy-mm-dd HH:nn:ss"), "UpdatedOn": len(qOrder.OrderLastEditedOn) ? dateTimeFormat(qOrder.OrderLastEditedOn, "yyyy-mm-dd HH:nn:ss") : "", "Customer": { "UserID": qOrder.OrderUserID, "FirstName": qOrder.UserFirstName, "LastName": qOrder.UserLastName, "Phone": qOrder.UserContactNumber, "Email": qOrder.UserEmailAddress }, "ServicePoint": { "ServicePointID": qOrder.OrderServicePointID, "Name": qOrder.ServicePointName, "TypeID": qOrder.ServicePointTypeID }, "LineItems": lineItems }; response["OK"] = true; response["ORDER"] = order; } catch (any e) { response["ERROR"] = "server_error"; response["MESSAGE"] = e.message; } writeOutput(serializeJSON(response)); // Helper function function getStatusText(status) { switch (status) { case 0: return "Cart"; case 1: return "Submitted"; case 2: return "In Progress"; case 3: return "Ready"; case 4: return "Completed"; case 5: return "Cancelled"; default: return "Unknown"; } }