Files
crm.clientright.ru/include/Webservices/UpdateWebClaimV2.php
Fedor 01c4fe80b5 chore: snapshot current working tree changes
Save all currently accumulated repository changes as a backup snapshot for Gitea so no local work is lost.
2026-03-26 14:19:01 +03:00

232 lines
11 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/*********************************************************************************
* API для обновления существующей Заявки (HelpDesk) из Web-формы (V2 - JSON)
* Принимает ticket_id + claim_json с полями для обновления (те же ключи, что в CreateWebClaimV2)
* Автор: Фёдор, 2026-01-23
********************************************************************************/
include_once 'include/Webservices/Query.php';
include_once 'modules/Users/Users.php';
require_once('include/Webservices/Utils.php');
require_once 'include/Webservices/Revise.php';
require_once 'includes/Loader.php';
vimport ('includes.runtime.Globals');
vimport ('includes.runtime.BaseModel');
vimport ('includes.runtime.LanguageHandler');
/**
* Обновление заявки (тикета) по ID
*
* @param string $ticket_id - ID заявки (число или 17x123)
* @param string $claim_json - JSON с полями для обновления (только переданные поля будут обновлены)
* @param object $user - пользователь (опционально)
* @return array - {"success": true, "ticket_id": "...", "ticket_number": "..."}
*/
function vtws_updatewebclaimv2($ticket_id, $claim_json, $user = false) {
$logstring = date("Y-m-d H:i:s").' REQUEST: ticket_id='.$ticket_id.' '.json_encode($_REQUEST);
file_put_contents('logs/UpdateWebClaimV2.log', $logstring.PHP_EOL, FILE_APPEND);
if (empty($ticket_id)) {
$logstring = date("Y-m-d H:i:s").' Не передан параметр ticket_id';
file_put_contents('logs/UpdateWebClaimV2.log', $logstring.PHP_EOL, FILE_APPEND);
throw new WebServiceException(WebServiceErrorCode::$INVALIDID, "Не передан параметр ticket_id");
}
if ($claim_json === '' || $claim_json === null) {
$logstring = date("Y-m-d H:i:s").' Не передан параметр claim_json';
file_put_contents('logs/UpdateWebClaimV2.log', $logstring.PHP_EOL, FILE_APPEND);
throw new WebServiceException(WebServiceErrorCode::$INVALIDID, "Не передан параметр claim_json");
}
// Параметр может прийти строкой (JSON) или уже массивом (тип encoded в БД)
if (is_array($claim_json)) {
$claimData = $claim_json;
} else {
$claimData = json_decode($claim_json, true);
if (json_last_error() !== JSON_ERROR_NONE) {
$cleanedJson = trim($claim_json);
$cleanedJson = preg_replace('/^[^{]*/', '', $cleanedJson);
$cleanedJson = preg_replace('/[^}]*$/', '', $cleanedJson);
$claimData = json_decode($cleanedJson, true);
if (json_last_error() !== JSON_ERROR_NONE) {
$logstring = date("Y-m-d H:i:s").' Ошибка парсинга JSON: '.json_last_error_msg();
file_put_contents('logs/UpdateWebClaimV2.log', $logstring.PHP_EOL, FILE_APPEND);
throw new WebServiceException(WebServiceErrorCode::$INVALIDID, "Ошибка парсинга JSON: ".json_last_error_msg());
}
}
}
$logstring = date("Y-m-d H:i:s").' claimData keys: '.implode(', ', array_keys($claimData)).PHP_EOL;
file_put_contents('logs/UpdateWebClaimV2.log', $logstring, FILE_APPEND);
global $adb, $current_user;
$ticketIdNumeric = preg_replace('/[^0-9]/', '', $ticket_id);
$ticketWsId = '17x' . $ticketIdNumeric;
// Проверяем, что запись существует и это HelpDesk
$check = $adb->pquery(
"SELECT e.crmid, e.setype FROM vtiger_crmentity e WHERE e.deleted = 0 AND e.crmid = ?",
array($ticketIdNumeric)
);
if (!$check || $adb->num_rows($check) === 0) {
$logstring = date("Y-m-d H:i:s").' Заявка с id='.$ticketIdNumeric.' не найдена';
file_put_contents('logs/UpdateWebClaimV2.log', $logstring.PHP_EOL, FILE_APPEND);
throw new WebServiceException(WebServiceErrorCode::$RECORDNOTFOUND, "Заявка не найдена");
}
$setype = $adb->query_result($check, 0, 'setype');
if ($setype !== 'HelpDesk') {
$logstring = date("Y-m-d H:i:s").' Запись '.$ticketIdNumeric.' не является заявкой (HelpDesk): '.$setype;
file_put_contents('logs/UpdateWebClaimV2.log', $logstring.PHP_EOL, FILE_APPEND);
throw new WebServiceException(WebServiceErrorCode::$INVALIDID, "Указанная запись не является заявкой");
}
$eventTypeMap = array(
'delay_flight' => 'Задержка рейса',
'cancel_flight' => 'Отмена рейса',
'miss_connection' => 'Пропуск стыковки',
'missed_connection' => 'Пропуск стыковки',
'delay_train' => 'Задержка поезда',
'cancel_train' => 'Отмена поезда',
'delay_ferry' => 'Задержка парома',
'cancel_ferry' => 'Отмена парома'
);
$element = array('id' => $ticketWsId);
// Маппинг полей из claim_json в поля CRM (только если ключ передан)
if (array_key_exists('ticket_title', $claimData)) {
$element['ticket_title'] = $claimData['ticket_title'];
}
if (array_key_exists('description', $claimData)) {
$element['description'] = $claimData['description'];
}
if (array_key_exists('ticketstatus', $claimData)) {
$element['ticketstatus'] = $claimData['ticketstatus'];
}
if (array_key_exists('project_id', $claimData) && $claimData['project_id'] !== '') {
$pid = preg_replace('/[^0-9]/', '', $claimData['project_id']);
$element['cf_2066'] = '33x' . $pid;
}
if (array_key_exists('contact_id', $claimData) && $claimData['contact_id'] !== '') {
$cid = preg_replace('/[^0-9]/', '', $claimData['contact_id']);
$element['contact_id'] = '12x' . $cid;
}
if (array_key_exists('cf_1726', $claimData)) {
$element['cf_1726'] = $claimData['cf_1726'];
$element['cf_2650'] = isset($eventTypeMap[$claimData['cf_1726']]) ? $eventTypeMap[$claimData['cf_1726']] : 'Цифровой адвокат ЕРВ';
}
if (array_key_exists('cf_2566', $claimData)) {
$element['cf_2566'] = $claimData['cf_2566'];
}
if (array_key_exists('cf_2568', $claimData)) {
$element['cf_2568'] = $claimData['cf_2568'];
}
if (array_key_exists('cf_departure_flight', $claimData)) {
$element['cf_2630'] = $claimData['cf_departure_flight'];
}
if (array_key_exists('cf_departure_date', $claimData)) {
$element['cf_2632'] = $claimData['cf_departure_date'];
}
if (array_key_exists('cf_1909', $claimData)) {
$element['cf_2636'] = $claimData['cf_1909'];
}
if (array_key_exists('cf_2502', $claimData)) {
$element['cf_2572'] = $claimData['cf_2502'];
}
if (array_key_exists('code', $claimData)) {
$element['cf_2574'] = $claimData['code'];
}
if (array_key_exists('cf_1885', $claimData)) {
$element['cf_2642'] = $claimData['cf_1885'];
}
if (array_key_exists('ip', $claimData)) {
$element['cf_2634'] = $claimData['ip'];
}
if (array_key_exists('region', $claimData)) {
$element['cf_2640'] = $claimData['region'];
}
if (array_key_exists('source', $claimData)) {
$element['cf_2638'] = $claimData['source'];
}
if (array_key_exists('cf_2508', $claimData)) {
$element['cf_2508'] = $claimData['cf_2508'];
}
if (array_key_exists('cf_2648', $claimData)) {
$element['cf_2648'] = $claimData['cf_2648'];
}
if (array_key_exists('currency_code', $claimData)) {
$element['cf_2652'] = $claimData['currency_code'];
}
if (array_key_exists('course', $claimData) && $claimData['course'] !== '' && $claimData['course'] !== null) {
$element['cf_2654'] = sprintf('%.4f', floatval($claimData['course']));
}
// Любое поле cf_XXXX из claim_json прокидываем в CRM как есть (в т.ч. cf_2662 и др.)
foreach ($claimData as $k => $v) {
if (preg_match('/^cf_\d+$/', $k) && !array_key_exists($k, $element)) {
$element[$k] = $v;
}
}
// Если передан только id — нет полей для обновления
if (count($element) === 1) {
$ticketNoRes = $adb->pquery("SELECT ticket_no FROM vtiger_troubletickets WHERE ticketid = ?", array($ticketIdNumeric));
$ticketNo = $ticketNoRes && $adb->num_rows($ticketNoRes) ? $adb->query_result($ticketNoRes, 0, 'ticket_no') : 'N/A';
$logstring = date("Y-m-d H:i:s").' В claim_json нет известных полей для обновления. Получены ключи: '.implode(', ', array_keys($claimData));
file_put_contents('logs/UpdateWebClaimV2.log', $logstring.PHP_EOL, FILE_APPEND);
return array(
'success' => true,
'ticket_id' => $ticketIdNumeric,
'ticket_number' => $ticketNo,
'updated' => false,
'message' => 'В claim_json не найдено полей для обновления. Проверьте логи UpdateWebClaimV2.log — там перечень полученных ключей.'
);
}
$logstring = date('Y-m-d H:i:s').' Элемент для revise: '.json_encode($element).PHP_EOL;
file_put_contents('logs/UpdateWebClaimV2.log', $logstring, FILE_APPEND);
try {
$entity = vtws_revise($element, $current_user);
} catch (WebServiceException $e) {
$logstring = date('Y-m-d H:i:s').' Ошибка revise: '.$e->getMessage().PHP_EOL;
file_put_contents('logs/UpdateWebClaimV2.log', $logstring, FILE_APPEND);
throw $e;
}
// Курс (cf_2654) — сохраняем напрямую в БД для точности 4 знака (как в CreateWebClaimV2)
if (array_key_exists('course', $claimData) && $claimData['course'] !== '' && $claimData['course'] !== null) {
$courseFormatted = sprintf('%.4f', floatval($claimData['course']));
try {
$adb->pquery("UPDATE vtiger_ticketcf SET cf_2654 = ? WHERE ticketid = ?", array($courseFormatted, $ticketIdNumeric));
} catch (Exception $ex) {
file_put_contents('logs/UpdateWebClaimV2.log', date('Y-m-d H:i:s').' Предупреждение: курс '.$courseFormatted.' — '.$ex->getMessage().PHP_EOL, FILE_APPEND);
}
}
$ticketNumber = isset($entity['ticket_no']) ? $entity['ticket_no'] : 'N/A';
$logstring = date('Y-m-d H:i:s').' Заявка обновлена: id='.$ticketIdNumeric.' ticket_no='.$ticketNumber.PHP_EOL;
file_put_contents('logs/UpdateWebClaimV2.log', $logstring, FILE_APPEND);
return array(
'success' => true,
'ticket_id' => $ticketIdNumeric,
'ticket_number' => $ticketNumber,
'updated' => true
);
}
/*
Регистрация операции в БД (если ещё не добавлено):
INSERT INTO vtiger_ws_operation (name, handler_path, handler_method, type, prelogin)
VALUES ('updatewebclaimv2', 'include/Webservices/UpdateWebClaimV2.php', 'vtws_updatewebclaimv2', 'POST', 0);
INSERT INTO vtiger_ws_operation_parameters (operationid, name, type, sequence)
SELECT operationid, 'ticket_id', 'string', 1 FROM vtiger_ws_operation WHERE name = 'updatewebclaimv2';
INSERT INTO vtiger_ws_operation_parameters (operationid, name, type, sequence)
SELECT operationid, 'claim_json', 'string', 2 FROM vtiger_ws_operation WHERE name = 'updatewebclaimv2';
*/