This repository has been archived on 2026-03-21. You can view files and clone it, but cannot push or open issues or pull requests.
payfrit-biz/api/orders/listForKDS.cfm
John Mizerek 453188d63f Fix KDS elapsed time by tagging SubmittedOn as UTC
DB stores timestamps in UTC but the API returned them without timezone
info, causing JS to parse them as local time. Append 'Z' suffix so
new Date() correctly interprets them as UTC.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 12:14:47 -08:00

225 lines
No EOL
7.2 KiB
Text

<cfsetting showdebugoutput="false">
<cfsetting enablecfoutputonly="true">
<cffunction name="apiAbort" access="public" returntype="void" output="true">
<cfargument name="payload" type="struct" required="true">
<cfcontent type="application/json; charset=utf-8">
<cfoutput>#serializeJSON(arguments.payload)#</cfoutput>
<cfabort>
</cffunction>
<cffunction name="readJsonBody" access="public" returntype="struct" output="false">
<cfset var raw = getHttpRequestData().content>
<cfif isNull(raw) OR len(trim(raw)) EQ 0>
<cfreturn {}>
</cfif>
<cftry>
<cfset var data = deserializeJSON(raw)>
<cfif isStruct(data)>
<cfreturn data>
<cfelse>
<cfreturn {}>
</cfif>
<cfcatch>
<cfreturn {}>
</cfcatch>
</cftry>
</cffunction>
<cfset data = readJsonBody()>
<cfset BusinessID = val( structKeyExists(data,"BusinessID") ? data.BusinessID : 0 )>
<cfset ServicePointID = val( structKeyExists(data,"ServicePointID") ? data.ServicePointID : 0 )>
<cfset StationID = val( structKeyExists(data,"StationID") ? data.StationID : 0 )>
<cfif BusinessID LTE 0>
<cfset apiAbort({ "OK": false, "ERROR": "missing_params", "MESSAGE": "BusinessID is required.", "DETAIL": "" })>
</cfif>
<cftry>
<!--- Build WHERE clause for filtering --->
<cfset whereClauses = ["o.BusinessID = ?"]>
<cfset params = [ { value = BusinessID, cfsqltype = "cf_sql_integer" } ]>
<!--- Filter by service point if provided --->
<cfif ServicePointID GT 0>
<cfset arrayAppend(whereClauses, "o.ServicePointID = ?")>
<cfset arrayAppend(params, { value = ServicePointID, cfsqltype = "cf_sql_integer" })>
</cfif>
<!--- Only show submitted orders (StatusID >= 1) --->
<cfset arrayAppend(whereClauses, "o.StatusID >= 1")>
<!--- Don't show completed orders (assuming StatusID 4 is completed) --->
<cfset arrayAppend(whereClauses, "o.StatusID < 4")>
<cfset whereSQL = arrayToList(whereClauses, " AND ")>
<!--- If filtering by station, only get orders that have items for that station --->
<cfif StationID GT 0>
<cfset stationParams = duplicate(params)>
<cfset arrayAppend(stationParams, { value = StationID, cfsqltype = "cf_sql_integer" })>
<cfset qOrders = queryTimed("
SELECT DISTINCT
o.ID,
o.UUID,
o.UserID,
o.BusinessID,
o.OrderTypeID,
o.StatusID,
o.ServicePointID,
o.Remarks,
o.SubmittedOn,
o.LastEditedOn,
sp.Name AS Name,
u.FirstName,
u.LastName
FROM Orders o
LEFT JOIN ServicePoints sp ON sp.ID = o.ServicePointID
LEFT JOIN Users u ON u.ID = o.UserID
INNER JOIN OrderLineItems oli ON oli.OrderID = o.ID
INNER JOIN Items i ON i.ID = oli.ItemID
WHERE #whereSQL#
AND i.StationID = ?
AND oli.IsDeleted = b'0'
ORDER BY o.SubmittedOn ASC, o.ID ASC
", stationParams, { datasource = "payfrit" })>
<cfelse>
<cfset qOrders = queryTimed("
SELECT
o.ID,
o.UUID,
o.UserID,
o.BusinessID,
o.OrderTypeID,
o.StatusID,
o.ServicePointID,
o.Remarks,
o.SubmittedOn,
o.LastEditedOn,
sp.Name AS Name,
u.FirstName,
u.LastName
FROM Orders o
LEFT JOIN ServicePoints sp ON sp.ID = o.ServicePointID
LEFT JOIN Users u ON u.ID = o.UserID
WHERE #whereSQL#
ORDER BY o.SubmittedOn ASC, o.ID ASC
", params, { datasource = "payfrit" })>
</cfif>
<cfset orders = []>
<cfloop query="qOrders">
<!--- Get line items for this order --->
<!--- If filtering by station, only show items for that station (plus modifiers) --->
<cfif StationID GT 0>
<cfset qLineItems = queryTimed("
SELECT
oli.ID,
oli.ParentOrderLineItemID,
oli.ItemID,
oli.Price,
oli.Quantity,
oli.Remark,
oli.IsDeleted,
i.Name,
i.ParentItemID,
i.IsCheckedByDefault,
i.StationID,
parent.Name AS ItemParentName
FROM OrderLineItems oli
INNER JOIN Items i ON i.ID = oli.ItemID
LEFT JOIN Items parent ON parent.ID = i.ParentItemID
WHERE oli.OrderID = ?
AND oli.IsDeleted = b'0'
AND (i.StationID = ? OR i.StationID = 0 OR i.StationID IS NULL OR oli.ParentOrderLineItemID > 0)
ORDER BY oli.ID
", [
{ value = qOrders.ID, cfsqltype = "cf_sql_integer" },
{ value = StationID, cfsqltype = "cf_sql_integer" }
], { datasource = "payfrit" })>
<cfelse>
<cfset qLineItems = queryTimed("
SELECT
oli.ID,
oli.ParentOrderLineItemID,
oli.ItemID,
oli.Price,
oli.Quantity,
oli.Remark,
oli.IsDeleted,
i.Name,
i.ParentItemID,
i.IsCheckedByDefault,
i.StationID,
parent.Name AS ItemParentName
FROM OrderLineItems oli
INNER JOIN Items i ON i.ID = oli.ItemID
LEFT JOIN Items parent ON parent.ID = i.ParentItemID
WHERE oli.OrderID = ?
AND oli.IsDeleted = b'0'
ORDER BY oli.ID
", [ { value = qOrders.ID, cfsqltype = "cf_sql_integer" } ], { datasource = "payfrit" })>
</cfif>
<cfset lineItems = []>
<cfloop query="qLineItems">
<cfset arrayAppend(lineItems, {
"OrderLineItemID": qLineItems.ID,
"ParentOrderLineItemID": qLineItems.ParentOrderLineItemID,
"ItemID": qLineItems.ID,
"Price": qLineItems.Price,
"Quantity": qLineItems.Quantity,
"Remark": qLineItems.Remark,
"Name": qLineItems.Name,
"ParentItemID": qLineItems.ParentItemID,
"ItemParentName": qLineItems.ItemParentName,
"IsCheckedByDefault": qLineItems.IsCheckedByDefault,
"StationID": qLineItems.StationID
})>
</cfloop>
<!--- Determine order type name --->
<cfset orderTypeName = "">
<cfswitch expression="#qOrders.OrderTypeID#">
<cfcase value="1"><cfset orderTypeName = "Dine-In"></cfcase>
<cfcase value="2"><cfset orderTypeName = "Takeaway"></cfcase>
<cfcase value="3"><cfset orderTypeName = "Delivery"></cfcase>
<cfdefaultcase><cfset orderTypeName = ""></cfdefaultcase>
</cfswitch>
<cfset arrayAppend(orders, {
"OrderID": qOrders.ID,
"UUID": qOrders.UUID,
"UserID": qOrders.UserID,
"BusinessID": qOrders.BusinessID,
"OrderTypeID": qOrders.OrderTypeID,
"OrderTypeName": orderTypeName,
"StatusID": qOrders.StatusID,
"ServicePointID": qOrders.ServicePointID,
"Remarks": qOrders.Remarks,
"SubmittedOn": isNull(qOrders.SubmittedOn) ? "" : dateTimeFormat(qOrders.SubmittedOn, "yyyy-MM-dd'T'HH:nn:ss'Z'"),
"LastEditedOn": isNull(qOrders.LastEditedOn) ? "" : dateTimeFormat(qOrders.LastEditedOn, "yyyy-MM-dd'T'HH:nn:ss'Z'"),
"Name": qOrders.Name,
"FirstName": qOrders.FirstName,
"LastName": qOrders.LastName,
"LineItems": lineItems
})>
</cfloop>
<cfset apiAbort({
"OK": true,
"ERROR": "",
"ORDERS": orders,
"STATION_FILTER": StationID
})>
<cfcatch>
<cfset apiAbort({
"OK": false,
"ERROR": "server_error",
"MESSAGE": "DB error loading orders for KDS",
"DETAIL": cfcatch.message
})>
</cfcatch>
</cftry>