// Get chat messages for a task // Input: TaskID, AfterMessageID (optional - for pagination/polling) // Output: { OK: true, MESSAGES: [...] } function apiAbort(required struct payload) { writeOutput(serializeJSON(payload)); abort; } function readJsonBody() { var raw = getHttpRequestData().content; if (isNull(raw)) raw = ""; if (!len(trim(raw))) return {}; try { var data = deserializeJSON(raw); if (isStruct(data)) return data; } catch (any e) {} return {}; } try { data = readJsonBody(); taskID = val(structKeyExists(data, "TaskID") ? data.TaskID : 0); afterMessageID = val(structKeyExists(data, "AfterMessageID") ? data.AfterMessageID : 0); if (taskID == 0) { apiAbort({ "OK": false, "ERROR": "missing_params", "MESSAGE": "TaskID is required" }); } // Get messages if (afterMessageID > 0) { qMessages = queryExecute(" SELECT m.MessageID, m.TaskID, m.SenderUserID, m.SenderType, m.MessageText, m.IsRead, m.CreatedOn, u.UserFirstName as SenderName FROM ChatMessages m LEFT JOIN Users u ON u.UserID = m.SenderUserID WHERE m.TaskID = :taskID AND m.MessageID > :afterID ORDER BY m.CreatedOn ASC ", { taskID: { value: taskID, cfsqltype: "cf_sql_integer" }, afterID: { value: afterMessageID, cfsqltype: "cf_sql_integer" } }, { datasource: "payfrit" }); } else { qMessages = queryExecute(" SELECT m.MessageID, m.TaskID, m.SenderUserID, m.SenderType, m.MessageText, m.IsRead, m.CreatedOn, u.UserFirstName as SenderName FROM ChatMessages m LEFT JOIN Users u ON u.UserID = m.SenderUserID WHERE m.TaskID = :taskID ORDER BY m.CreatedOn ASC ", { taskID: { value: taskID, cfsqltype: "cf_sql_integer" } }, { datasource: "payfrit" }); } messages = []; for (msg in qMessages) { arrayAppend(messages, { "MessageID": msg.MessageID, "TaskID": msg.TaskID, "SenderUserID": msg.SenderUserID, "SenderType": msg.SenderType, "SenderName": len(trim(msg.SenderName)) ? msg.SenderName : (msg.SenderType == "customer" ? "Customer" : "Staff"), "Text": msg.MessageText, "IsRead": msg.IsRead == 1, "CreatedOn": dateFormat(msg.CreatedOn, "yyyy-mm-dd") & "T" & timeFormat(msg.CreatedOn, "HH:mm:ss") }); } // Check if chat/task is closed (completed) qTask = queryExecute(" SELECT TaskCompletedOn FROM Tasks WHERE TaskID = :taskID ", { taskID: { value: taskID, cfsqltype: "cf_sql_integer" } }, { datasource: "payfrit" }); chatClosed = false; if (qTask.recordCount > 0 && len(trim(qTask.TaskCompletedOn)) > 0) { chatClosed = true; } apiAbort({ "OK": true, "MESSAGES": messages, "COUNT": arrayLen(messages), "CHAT_CLOSED": chatClosed }); } catch (any e) { apiAbort({ "OK": false, "ERROR": "server_error", "MESSAGE": e.message }); }