false, 'error' => 'Invalid JSON']); exit; } $answer = isset($data['answer']) ? trim($data['answer']) : (isset($data['message']) ? trim($data['message']) : ''); $contact_id = isset($data['contact_id']) ? (int) $data['contact_id'] : 0; $project_id = isset($data['project_id']) ? (int) $data['project_id'] : 0; $support_user_id = isset($data['support_user_id']) ? $data['support_user_id'] : null; // может быть "19x123" $channel = isset($data['channel']) ? trim($data['channel']) : 'Support'; if (empty($answer)) { file_put_contents($logFile, date('Y-m-d H:i:s') . ' Ошибка: не передан answer/message' . PHP_EOL, FILE_APPEND); header('Content-Type: application/json; charset=utf-8'); echo json_encode(['success' => false, 'error' => 'Missing answer or message']); exit; } if ($contact_id <= 0) { file_put_contents($logFile, date('Y-m-d H:i:s') . ' Ошибка: не передан или неверный contact_id' . PHP_EOL, FILE_APPEND); header('Content-Type: application/json; charset=utf-8'); echo json_encode(['success' => false, 'error' => 'Missing or invalid contact_id']); exit; } global $adb; if (empty($adb)) { $adb = PearDatabase::getInstance(); } file_put_contents($logFile, date('Y-m-d H:i:s') . ' $adb ok' . PHP_EOL, FILE_APPEND); // Проверяем, что контакт существует $check = $adb->pquery( 'SELECT c.contactid, e.smownerid FROM vtiger_contactdetails c INNER JOIN vtiger_crmentity e ON e.crmid = c.contactid WHERE e.deleted = 0 AND c.contactid = ?', array($contact_id) ); if ($adb->num_rows($check) === 0) { file_put_contents($logFile, date('Y-m-d H:i:s') . ' Ошибка: контакт с ID ' . $contact_id . ' не найден' . PHP_EOL, FILE_APPEND); header('Content-Type: application/json; charset=utf-8'); echo json_encode(['success' => false, 'error' => 'Contact not found']); exit; } file_put_contents($logFile, date('Y-m-d H:i:s') . ' Контакт ' . $contact_id . ' найден' . PHP_EOL, FILE_APPEND); $owner_id = $adb->query_result($check, 0, 'smownerid'); $crmid = '12x' . $contact_id; $setype = 'Contacts'; // Кто создаёт комментарий: переданный support_user_id, иначе ответственный по проекту, иначе по контакту, иначе админ $user = null; if (!empty($support_user_id)) { $user = (strpos($support_user_id, 'x') !== false) ? $support_user_id : ('19x' . $support_user_id); } elseif ($project_id > 0) { $proj = $adb->pquery( 'SELECT e.smownerid FROM vtiger_project p INNER JOIN vtiger_crmentity e ON e.crmid = p.projectid WHERE e.deleted = 0 AND p.projectid = ? AND p.linktoaccountscontacts = ?', array($project_id, $contact_id) ); if ($adb->num_rows($proj) > 0) { $uid = $adb->query_result($proj, 0, 'smownerid'); $user = '19x' . $uid; } } if (empty($user)) { $user = '19x' . $owner_id; } if (empty($user) || $user === '19x') { $user = Users::getActiveAdminUser(); } $owner_id_num = (strpos($user, 'x') !== false) ? (int) substr($user, strpos($user, 'x') + 1) : (int) $user; file_put_contents($logFile, date('Y-m-d H:i:s') . ' user=' . (string)$user . ' (owner_id_num=' . $owner_id_num . ')' . PHP_EOL, FILE_APPEND); // Запись комментария напрямую в БД (без vtws_create — тот падает внутри без выброса исключения) $commentCrmId = $adb->getUniqueID('vtiger_crmentity'); $date_var = date('Y-m-d H:i:s'); // deleted=0 обязательно — иначе запись не попадёт в выборку (WHERE vtiger_crmentity.deleted = 0) $sql_crmentity = "INSERT INTO vtiger_crmentity (crmid, smcreatorid, smownerid, smgroupid, setype, description, modifiedby, createdtime, modifiedtime, source, deleted) VALUES (?, ?, ?, 0, 'ModComments', '', ?, ?, ?, 'CRM', 0)"; $result1 = $adb->pquery($sql_crmentity, array($commentCrmId, $owner_id_num, $owner_id_num, $owner_id_num, $date_var, $date_var)); if (!$result1) { $error = $adb->database->ErrorMsg(); file_put_contents($logFile, date('Y-m-d H:i:s') . ' ❌ Ошибка INSERT vtiger_crmentity: ' . $error . PHP_EOL, FILE_APPEND); echo json_encode(['success' => false, 'error' => 'DB error: crmentity - ' . $error]); exit; } file_put_contents($logFile, date('Y-m-d H:i:s') . ' ✅ vtiger_crmentity OK' . PHP_EOL, FILE_APPEND); $sql_modcomments = "INSERT INTO vtiger_modcomments (modcommentsid, commentcontent, related_to, parent_comments, customer, userid, reasontoedit, is_private, filename, related_email_id, channel, messageid) VALUES (?, ?, ?, '', 0, 0, NULL, 0, NULL, NULL, ?, NULL)"; $result2 = $adb->pquery($sql_modcomments, array($commentCrmId, $answer, $contact_id, $channel)); if (!$result2) { $error = $adb->database->ErrorMsg(); file_put_contents($logFile, date('Y-m-d H:i:s') . ' ❌ Ошибка INSERT vtiger_modcomments: ' . $error . PHP_EOL, FILE_APPEND); echo json_encode(['success' => false, 'error' => 'DB error: modcomments - ' . $error]); exit; } file_put_contents($logFile, date('Y-m-d H:i:s') . ' ✅ vtiger_modcomments OK' . PHP_EOL, FILE_APPEND); // Без строки в vtiger_modcommentscf комментарий не попадёт в список (INNER JOIN в getListQuery) $result3 = $adb->pquery('INSERT INTO vtiger_modcommentscf (modcommentsid) VALUES (?)', array($commentCrmId)); if (!$result3) { $error = $adb->database->ErrorMsg(); file_put_contents($logFile, date('Y-m-d H:i:s') . ' ❌ Ошибка INSERT vtiger_modcommentscf: ' . $error . PHP_EOL, FILE_APPEND); echo json_encode(['success' => false, 'error' => 'DB error: modcommentscf - ' . $error]); exit; } file_put_contents($logFile, date('Y-m-d H:i:s') . ' ✅ vtiger_modcommentscf OK' . PHP_EOL, FILE_APPEND); file_put_contents($logFile, date('Y-m-d H:i:s') . ' ✅ Создан комментарий ID ' . $commentCrmId . ' для контакта ' . $contact_id . PHP_EOL, FILE_APPEND); $comment_id_ws = '20x' . $commentCrmId; // ModComments в vtiger обычно 20x // Уведомление ответственного (всплывашка) $notify_user_id = $owner_id; if ($project_id > 0) { $proj = $adb->pquery( 'SELECT e.smownerid FROM vtiger_project p INNER JOIN vtiger_crmentity e ON e.crmid = p.projectid WHERE e.deleted = 0 AND p.projectid = ? AND p.linktoaccountscontacts = ? AND p.projectstatus <> ?', array($project_id, $contact_id, 'completed') ); if ($adb->num_rows($proj) === 1) { $notify_user_id = $adb->query_result($proj, 0, 'smownerid'); } } $link = 'module=Contacts&view=Detail&record=' . $contact_id . '&app=MARKETING'; $title = 'Ответ поддержки добавлен'; $exist = $adb->pquery( 'SELECT id FROM vtiger_vdnotifierpro WHERE userid = ? AND crmid = ? AND title = ? AND status = 5', array($notify_user_id, $contact_id, $title) ); if ($adb->num_rows($exist) > 0) { $id = $adb->query_result($exist, 0, 'id'); $adb->pquery('UPDATE vtiger_vdnotifierpro SET modifiedtime = ? WHERE id = ?', array($date_var, $id)); } else { $adb->pquery( 'INSERT INTO vtiger_vdnotifierpro (userid, modulename, crmid, modiuserid, link, title, action, modifiedtime, status) VALUES (?, ?, ?, 0, ?, ?, "", ?, 5)', array($notify_user_id, $setype, $contact_id, $link, $title, $date_var) ); } header('Content-Type: application/json; charset=utf-8'); echo json_encode([ 'success' => true, 'comment_id' => $comment_id_ws, 'contact_id' => $contact_id ]);