payfrit-api/api/tasks/createChat.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

172 lines
5.6 KiB
PHP

<?php
require_once __DIR__ . '/../helpers.php';
runAuth();
/**
* Customer initiates a chat with staff
* POST: { BusinessID, ServicePointID?, OrderID?, UserID?, Message?, ForceNew? }
*/
$data = readJsonBody();
$businessID = (int) ($data['BusinessID'] ?? 0);
$servicePointID = (int) ($data['ServicePointID'] ?? 0);
$orderID = (int) ($data['OrderID'] ?? 0);
$initialMessage = trim($data['Message'] ?? '');
$userID = (int) ($data['UserID'] ?? 0);
if ($businessID <= 0) {
apiAbort(['OK' => false, 'ERROR' => 'missing_params', 'MESSAGE' => 'BusinessID is required']);
}
try {
// If servicePointID not provided but orderID is, look it up
if ($servicePointID <= 0 && $orderID > 0) {
$qOrderSP = queryOne("SELECT ServicePointID FROM Orders WHERE ID = ?", [$orderID]);
if ($qOrderSP && (int) $qOrderSP['ServicePointID'] > 0) {
$servicePointID = (int) $qOrderSP['ServicePointID'];
}
}
// Look up "Chat" task type for this business
$ttQuery = queryOne("
SELECT ID FROM tt_TaskTypes
WHERE BusinessID = ? AND Name LIKE '%Chat%'
LIMIT 1
", [$businessID]);
$chatTaskTypeID = $ttQuery ? (int) $ttQuery['ID'] : 0;
// Check for existing open chat
$forceNew = !empty($data['ForceNew']) && $data['ForceNew'] === true;
if (!$forceNew) {
$existingChat = queryOne("
SELECT t.ID, t.CreatedOn,
(SELECT MAX(cm.CreatedOn) FROM ChatMessages cm WHERE cm.TaskID = t.ID) as LastMessageTime
FROM Tasks t
LEFT JOIN ChatMessages cm2 ON cm2.TaskID = t.ID AND cm2.SenderUserID = ?
WHERE t.BusinessID = ?
AND (t.TaskTypeID = ? OR t.Title LIKE 'Chat%')
AND t.CompletedOn IS NULL
AND (
(t.OrderID = ? AND ? > 0)
OR (t.SourceType = 'servicepoint' AND t.SourceID = ? AND ? > 0)
OR (t.SourceType = 'user' AND t.SourceID = ? AND ? > 0)
OR (cm2.SenderUserID = ? AND ? > 0)
)
ORDER BY t.CreatedOn DESC
LIMIT 1
", [
$userID, $businessID, $chatTaskTypeID,
$orderID, $orderID,
$servicePointID, $servicePointID,
$userID, $userID,
$userID, $userID,
]);
if ($existingChat) {
$lastActivity = $existingChat['LastMessageTime'];
if (empty($lastActivity)) {
$lastActivity = $existingChat['CreatedOn'];
}
$chatAge = (int) ((time() - strtotime($lastActivity)) / 60);
if ($chatAge > 30) {
// Auto-close stale chat
queryTimed("UPDATE Tasks SET CompletedOn = NOW() WHERE ID = ?", [$existingChat['ID']]);
} else {
jsonResponse([
'OK' => true,
'TaskID' => (int) $existingChat['ID'],
'MESSAGE' => 'Rejoined existing chat',
'EXISTING' => true,
]);
}
}
}
// Get service point info
$tableName = '';
if ($servicePointID > 0) {
$spQuery = queryOne("SELECT Name FROM ServicePoints WHERE ID = ?", [$servicePointID]);
$tableName = $spQuery ? $spQuery['Name'] : "Table #$servicePointID";
}
// Get user name
$userName = '';
if ($userID > 0) {
$userQuery = queryOne("SELECT FirstName FROM Users WHERE ID = ?", [$userID]);
if ($userQuery && !empty(trim($userQuery['FirstName']))) {
$userName = $userQuery['FirstName'];
}
}
// Create task title
if ($servicePointID > 0) {
$taskTitle = !empty($userName)
? "Chat - $userName ($tableName)"
: "Chat - $tableName";
} else {
$taskTitle = !empty($userName)
? "Chat - $userName (Remote)"
: "Remote Chat";
}
$taskDetails = !empty($initialMessage) ? $initialMessage : 'Customer initiated chat';
// Look up or create a "Chat" category
$catQuery = queryOne("
SELECT ID FROM TaskCategories
WHERE BusinessID = ? AND Name = 'Chat'
LIMIT 1
", [$businessID]);
if (!$catQuery) {
queryTimed("
INSERT INTO TaskCategories (BusinessID, Name, Color)
VALUES (?, 'Chat', '#2196F3')
", [$businessID]);
$categoryID = (int) lastInsertId();
} else {
$categoryID = (int) $catQuery['ID'];
}
// Determine source type and ID
$sourceType = $servicePointID > 0 ? 'servicepoint' : 'user';
$sourceID = $servicePointID > 0 ? $servicePointID : $userID;
// Insert task
queryTimed("
INSERT INTO Tasks (
BusinessID, CategoryID, OrderID, TaskTypeID,
Title, Details, ClaimedByUserID, SourceType, SourceID, CreatedOn
) VALUES (?, ?, ?, ?, ?, ?, 0, ?, ?, NOW())
", [
$businessID,
$categoryID,
$orderID > 0 ? $orderID : null,
$chatTaskTypeID > 0 ? $chatTaskTypeID : null,
$taskTitle,
$taskDetails,
$sourceType,
$sourceID,
]);
$taskID = (int) lastInsertId();
// If there's an initial message, save it
if (!empty($initialMessage) && $userID > 0) {
queryTimed("
INSERT INTO ChatMessages (TaskID, SenderUserID, SenderType, MessageBody)
VALUES (?, ?, 'customer', ?)
", [$taskID, $userID, $initialMessage]);
}
jsonResponse([
'OK' => true,
'TaskID' => $taskID,
'MESSAGE' => 'Chat started',
]);
} catch (Exception $e) {
jsonResponse(['OK' => false, 'ERROR' => 'server_error', 'MESSAGE' => $e->getMessage()]);
}