0.1) { log_event('DEBUG', "Чтение stdin заняло: " . round(($timeAfterStdin - $timePoint) * 1000, 2) . " мс"); } if (!empty($input)) { log_event('DEBUG', "Входные данные из stdin: " . $input); $data = json_decode($input, true); if (json_last_error() !== JSON_ERROR_NONE) { throw new Exception('Ошибка декодирования JSON: ' . json_last_error_msg()); } } else { // Для HTTP запросов: сначала пробуем php://input (для JSON) $timeBeforeInput = microtime(true); $rawInput = file_get_contents('php://input'); $timeAfterInput = microtime(true); $inputReadTime = ($timeAfterInput - $timeBeforeInput) * 1000; log_event('DEBUG', "Чтение php://input заняло: " . round($inputReadTime, 2) . " мс"); if (!empty($rawInput)) { log_event('DEBUG', "Входные данные из php://input (первые 200 символов): " . substr($rawInput, 0, 200)); $timeBeforeJson = microtime(true); $data = json_decode($rawInput, true); $timeAfterJson = microtime(true); $jsonDecodeTime = ($timeAfterJson - $timeBeforeJson) * 1000; log_event('DEBUG', "Декодирование JSON заняло: " . round($jsonDecodeTime, 2) . " мс"); if (json_last_error() !== JSON_ERROR_NONE) { // Если не JSON, пробуем как обычный POST parse_str($rawInput, $data); log_event('DEBUG', "Данные распарсены как form-data"); } else { log_event('DEBUG', "Данные распарсены как JSON"); } } else { // Если php://input пустой, используем $_POST (для form-data) $data = $_POST; log_event('DEBUG', "Используем \$_POST: " . json_encode($data, JSON_UNESCAPED_UNICODE)); } } $timeAfterParsing = microtime(true); log_event('DEBUG', "Время до парсинга данных: " . round(($timeAfterParsing - $scriptStartTime) * 1000, 2) . " мс"); // Распаковываем данные из last_event, если они там есть (для совместимости с n8n) if (isset($data['last_event']) && is_array($data['last_event'])) { log_event('DEBUG', "Обнаружен объект last_event, распаковываем данные"); $lastEvent = $data['last_event']; // Извлекаем данные события из last_event (приоритет) $eventName = $lastEvent['event_name'] ?? $lastEvent['Наименование'] ?? $data['event_name'] ?? 'Судебное заседание'; $eventDate = $lastEvent['event_date'] ?? $lastEvent['Дата'] ?? $data['event_date'] ?? ''; $eventTime = $lastEvent['event_time'] ?? $lastEvent['Время'] ?? $data['event_time'] ?? ''; $location = $lastEvent['location'] ?? $lastEvent['Место'] ?? $data['location'] ?? ''; $result = $lastEvent['event_result'] ?? $lastEvent['Результат'] ?? $data['result'] ?? ''; $basis = $lastEvent['event_basis'] ?? $lastEvent['Основание'] ?? $data['basis'] ?? ''; $note = $lastEvent['note'] ?? $lastEvent['Примечание'] ?? $data['note'] ?? ''; $publicationDate = $lastEvent['publication_date'] ?? $lastEvent['Дата размещения'] ?? $data['publication_date'] ?? ''; log_event('DEBUG', "Данные распакованы из last_event: event_name='$eventName', event_date='$eventDate'"); } else { // Данные уже в корне (обычный формат) $eventName = $data['event_name'] ?? 'Судебное заседание'; $eventDate = $data['event_date'] ?? ''; $eventTime = $data['event_time'] ?? ''; $location = $data['location'] ?? ''; $result = $data['result'] ?? ''; $basis = $data['basis'] ?? ''; $note = $data['note'] ?? ''; $publicationDate = $data['publication_date'] ?? ''; } // Проверяем обязательные параметры if (empty($data['project_id'])) { throw new Exception('Параметр project_id обязателен'); } $projectId = intval($data['project_id']); log_event('INFO', "Создаем событие для проекта: $projectId"); log_event('DEBUG', "Название: '$eventName', Дата: '$eventDate', Время: '$eventTime'"); log_event('DEBUG', "Полные входные данные: " . json_encode($data, JSON_UNESCAPED_UNICODE)); // Проверяем что дата не пустая if (empty($eventDate)) { throw new Exception('Дата события обязательна'); } // Подключаемся к базе данных $timeBeforeDb = microtime(true); // Устанавливаем таймауты для быстрого подключения ini_set('default_socket_timeout', 5); // Таймаут подключения 5 секунд $mysqli = new mysqli('localhost', 'ci20465_72new', 'EcY979Rn', 'ci20465_72new'); $timeAfterDbConnect = microtime(true); $dbConnectTime = ($timeAfterDbConnect - $timeBeforeDb) * 1000; log_event('DEBUG', "Подключение к БД заняло: " . round($dbConnectTime, 2) . " мс"); if ($mysqli->connect_error) { throw new Exception('Не удалось подключиться к БД: ' . $mysqli->connect_error); } $mysqli->set_charset('utf8mb4'); $mysqli->options(MYSQLI_OPT_CONNECT_TIMEOUT, 5); // Таймаут подключения 5 секунд $mysqli->options(MYSQLI_OPT_READ_TIMEOUT, 10); // Таймаут чтения 10 секунд // Получаем данные проекта $query = "SELECT e.smownerid, p.projectname, p.linktoaccountscontacts FROM vtiger_crmentity e JOIN vtiger_project p ON p.projectid = e.crmid WHERE e.crmid = ? AND e.deleted = 0"; $stmt = $mysqli->prepare($query); $stmt->bind_param('i', $projectId); $stmt->execute(); $result_query = $stmt->get_result(); if ($result_query->num_rows === 0) { throw new Exception("Проект $projectId не найден"); } $row = $result_query->fetch_assoc(); $ownerId = $row['smownerid']; $projectName = $row['projectname']; $contactId = $row['linktoaccountscontacts'] ?? null; log_event('DEBUG', "Владелец проекта: $ownerId, Название: $projectName, Контакт: " . ($contactId ?? 'нет')); // Форматируем дату и время для CRM $formattedDate = formatDateForCRM($eventDate); $formattedTime = formatTimeForCRM($eventTime); $formattedDateTime = $formattedDate . ' ' . $formattedTime; // Вычисляем время окончания (+1 час) $endDateTime = date('Y-m-d H:i:s', strtotime($formattedDateTime) + 3600); log_event('DEBUG', "Дата начала: $formattedDateTime, Дата окончания: $endDateTime"); // Определяем тип события и статус - используем настройки как в workflow 3 (блок 18) $activityType = 'судебное заседание'; $eventstatus = 'Planned'; // Запланировано (как в workflow) log_event('DEBUG', "Установлен тип 'судебное заседание' и статус 'Planned' (как в workflow 3)"); // Формируем тему события с названием проекта $eventSubject = $eventName; if (!empty($projectName)) { $eventSubject = "[$projectName] $eventName"; } log_event('DEBUG', "Тип события: $activityType, Статус: $eventstatus, Тема: $eventSubject"); // Формируем описание события $description = "Автоматически созданное событие из судебного дела\n\n"; if (!empty($location)) { $description .= "Место: $location\n"; } if (!empty($result)) { $description .= "Результат: $result\n"; } if (!empty($basis)) { $description .= "Основание: $basis\n"; } if (!empty($note)) { $description .= "Примечание: $note\n"; } if (!empty($publicationDate)) { $description .= "Дата размещения: $publicationDate\n"; } // Получаем следующий ID $result_id = $mysqli->query("SELECT MAX(crmid) as max_id FROM vtiger_crmentity"); $row_id = $result_id->fetch_assoc(); $eventId = ($row_id['max_id'] ?? 0) + 1; log_event('DEBUG', "Новый ID события: $eventId"); $created_time = date('Y-m-d H:i:s'); // Создаем запись в vtiger_crmentity $sql = "INSERT INTO vtiger_crmentity (crmid, smcreatorid, smownerid, modifiedby, setype, description, createdtime, modifiedtime, presence, deleted, label) VALUES (?, ?, ?, ?, 'Calendar', ?, ?, ?, 1, 0, ?)"; $stmt = $mysqli->prepare($sql); $stmt->bind_param('iiiissss', $eventId, $ownerId, $ownerId, $ownerId, $description, $created_time, $created_time, $eventSubject); $stmt->execute(); log_event('DEBUG', "Запись в vtiger_crmentity создана"); // Создаем запись в vtiger_activity $visibility = 'Public'; $endTime = date('H:i:s', strtotime($formattedDateTime) + 3600); $sql = "INSERT INTO vtiger_activity (activityid, subject, activitytype, date_start, time_start, due_date, time_end, location, visibility, eventstatus) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; $stmt = $mysqli->prepare($sql); $stmt->bind_param('isssssssss', $eventId, $eventSubject, $activityType, $formattedDate, $formattedTime, $formattedDate, $endTime, $location, $visibility, $eventstatus); $stmt->execute(); log_event('DEBUG', "Запись в vtiger_activity создана"); // Связываем событие с проектом (vtiger_seactivityrel) $sql = "INSERT INTO vtiger_seactivityrel (crmid, activityid) VALUES (?, ?)"; $stmt = $mysqli->prepare($sql); $stmt->bind_param('ii', $projectId, $eventId); $stmt->execute(); log_event('SUCCESS', "Событие привязано к проекту в vtiger_seactivityrel"); // Связываем событие с проектом через общую таблицу связей (vtiger_crmentityrel) // Это ключевая связь для отображения события в интерфейсе проекта! $sql = "INSERT INTO vtiger_crmentityrel (crmid, module, relcrmid, relmodule) VALUES (?, 'Project', ?, 'Calendar')"; $stmt = $mysqli->prepare($sql); $stmt->bind_param('ii', $projectId, $eventId); $stmt->execute(); log_event('SUCCESS', "Событие привязано к проекту в vtiger_crmentityrel (для отображения в UI)"); // Связываем событие с контактом (если контакт указан в проекте) if (!empty($contactId) && $contactId > 0) { $sql = "INSERT INTO vtiger_cntactivityrel (contactid, activityid) VALUES (?, ?)"; $stmt = $mysqli->prepare($sql); $stmt->bind_param('ii', $contactId, $eventId); $stmt->execute(); log_event('SUCCESS', "Событие привязано к контакту: $contactId"); } else { log_event('DEBUG', "Контакт не указан в проекте, пропускаем связывание"); } // Обновляем поля проекта с информацией о последнем событии try { // Формируем описание для cf_2496 $cf2496Description = $eventSubject; if (!empty($result) && trim($result) !== '') { // Очищаем результат от лишних пробелов и дефисов $cleanResult = trim($result); $cf2496Description .= " - $cleanResult"; } $sql = "UPDATE vtiger_projectcf SET cf_1682 = ?, cf_1684 = ?, cf_2496 = ? WHERE projectid = ?"; $stmt = $mysqli->prepare($sql); $stmt->bind_param('sssi', $formattedDate, $formattedTime, $cf2496Description, $projectId); $stmt->execute(); log_event('SUCCESS', "Поля проекта обновлены (cf_1682, cf_1684, cf_2496)"); log_event('DEBUG', "cf_2496 установлен: $cf2496Description"); } catch (Exception $e) { log_event('WARNING', "Не удалось обновить поля проекта: " . $e->getMessage()); } // Обновляем последовательность $mysqli->query("UPDATE vtiger_crmentity_seq SET id = $eventId"); $mysqli->close(); // Формируем успешный ответ $response = [ 'success' => true, 'event_id' => '4x' . $eventId, 'event_numeric_id' => $eventId, 'event_name' => $eventName, 'event_date' => $formattedDate, 'event_time' => $formattedTime, 'project_id' => $projectId, 'message' => 'Событие успешно создано и привязано к проекту' ]; $totalTime = (microtime(true) - $scriptStartTime) * 1000; log_event('SUCCESS', "=== ОБРАБОТКА ЗАВЕРШЕНА УСПЕШНО ==="); log_event('SUCCESS', "Событие создано: 4x$eventId"); log_event('INFO', "Общее время выполнения: " . round($totalTime, 2) . " мс"); // Отключаем буферизацию для немедленной отправки ответа if (ob_get_level()) { ob_end_clean(); } header('Content-Type: application/json; charset=utf-8'); $timeBeforeOutput = microtime(true); echo json_encode($response, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); $timeAfterOutput = microtime(true); log_event('DEBUG', "Отправка ответа заняла: " . round(($timeAfterOutput - $timeBeforeOutput) * 1000, 2) . " мс"); // Принудительно отправляем ответ и завершаем выполнение if (function_exists('fastcgi_finish_request')) { fastcgi_finish_request(); } exit(0); } catch (Exception $e) { $error_message = $e->getMessage(); log_event('ERROR', "Ошибка: $error_message"); $response = [ 'success' => false, 'error' => $error_message, 'timestamp' => date('Y-m-d H:i:s') ]; // Отключаем буферизацию для немедленной отправки ответа if (ob_get_level()) { ob_end_clean(); } header('Content-Type: application/json; charset=utf-8'); http_response_code(500); echo json_encode($response, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); // Принудительно отправляем ответ и завершаем выполнение if (function_exists('fastcgi_finish_request')) { fastcgi_finish_request(); } exit(1); } ?>