Files
crm.clientright.ru/include/Webservices/UpsertContact.php
Fedor da82100b60 feat: UI/UX improvements + CRM integration methods + documents_meta deduplication
Frontend:
- Changed main title to 'Подать обращение о защите прав потребителя'
- Changed browser title to 'Clientright — защита прав потребителей'
- Enhanced draft cards: show problem_description (250 chars), category tag, document progress bar
- Fixed 'Назад' button to always return to draft selection
- Added SSE connection for OCR status updates
- Renamed steps: Вход, Обращение, Документы, Заявление
- Skip 'Проверка полиса' and 'Тип события' steps for new claim flow

Backend:
- Fixed client IP extraction (X-Forwarded-For, X-Real-IP)
- Added problem_title, category, documents_required_list to draft list API
- Fixed documents_uploaded count to count unique field_labels

CRM Webservices:
- Added UpsertContact.php - create/update contacts with tgid support
- Added UpsertAccounts.php - batch upsert offenders by INN
- Added UpsertProject.php - create/update projects with offender mapping

Database:
- Fixed documents_meta duplicates in existing claims
- SQL query for deduplication by field_name provided
2025-12-01 22:18:21 +03:00

235 lines
10 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-интерфейс для создания/обновления Контакта (Upsert)
* Гибкий метод: обновляет если найден, создаёт если нет
*
* Приоритет поиска:
* 1. contact_id (если передан - сразу обновляем)
* 2. mobile (ищем по мобильному)
* 3. tgid (ищем по полю phone, где хранится telegram_id)
*
* Все поля опциональны, кроме хотя бы одного идентификатора
*
* Автор: Фёдор, 2025-12-01
********************************************************************************/
include_once 'include/Webservices/Query.php';
include_once 'modules/Users/Users.php';
require_once('include/Webservices/Utils.php');
require_once 'include/Webservices/Create.php';
require_once 'include/Webservices/Revise.php';
require_once 'includes/Loader.php';
vimport('includes.runtime.Globals');
vimport('includes.runtime.BaseModel');
vimport('includes.runtime.LanguageHandler');
/**
* Upsert контакта - создание или обновление
*
* @param string $contact_id - ID контакта в CRM (если известен)
* @param string $mobile - мобильный телефон
* @param string $tgid - telegram ID
* @param string $firstname - имя
* @param string $secondname - отчество
* @param string $lastname - фамилия
* @param string $email - email
* @param string $birthday - дата рождения
* @param string $birthplace - место рождения
* @param string $mailingstreet - адрес
* @param string $inn - ИНН
* @param string $requisites - реквизиты
* @param string $code - SMS код верификации
* @param mixed $user - пользователь CRM
* @return string JSON с результатом
*/
function vtws_upsertcontact(
$contact_id = '',
$mobile = '',
$tgid = '',
$firstname = '',
$secondname = '',
$lastname = '',
$email = '',
$birthday = '',
$birthplace = '',
$mailingstreet = '',
$inn = '',
$requisites = '',
$code = '',
$user = false
) {
$logFile = 'logs/UpsertContact.log';
$logstring = date("Y-m-d H:i:s") . ' REQUEST: ' . json_encode($_REQUEST);
file_put_contents($logFile, $logstring . PHP_EOL, FILE_APPEND);
global $adb, $current_user;
// Результат
$result = array(
'success' => false,
'contact_id' => null,
'action' => null, // 'created', 'updated', 'found'
'message' => ''
);
// ========================================
// 1. ФОРМАТИРОВАНИЕ ТЕЛЕФОНА
// ========================================
if (!empty($mobile)) {
$mobile = preg_replace('/[^0-9]/', '', $mobile);
if (strlen($mobile) == 11 && $mobile[0] == '8') {
$mobile = "7" . substr($mobile, 1);
} else if (strlen($mobile) == 10) {
$mobile = "7" . $mobile;
} else if (strlen($mobile) != 11) {
// Некорректный номер - логируем, но не падаем
$logstring = date("Y-m-d H:i:s") . ' ⚠️ Некорректный номер телефона: ' . $mobile . ' (игнорируем)';
file_put_contents($logFile, $logstring . PHP_EOL, FILE_APPEND);
$mobile = ''; // Обнуляем некорректный номер
}
}
// ========================================
// 2. ПОИСК СУЩЕСТВУЮЩЕГО КОНТАКТА
// ========================================
$existingContactId = null;
$searchMethod = '';
// 2.1 По contact_id (приоритет 1)
if (!empty($contact_id)) {
$contact_id = preg_replace('/[^0-9]/', '', $contact_id); // Очищаем от 12x префикса
$query = "SELECT c.contactid FROM vtiger_contactdetails c
LEFT JOIN vtiger_crmentity e ON e.crmid = c.contactid
WHERE e.deleted = 0 AND c.contactid = ? LIMIT 1";
$res = $adb->pquery($query, array($contact_id));
if ($adb->num_rows($res) > 0) {
$existingContactId = $adb->query_result($res, 0, 'contactid');
$searchMethod = 'by_contact_id';
}
}
// 2.2 По mobile (приоритет 2)
if (empty($existingContactId) && !empty($mobile)) {
$query = "SELECT c.contactid FROM vtiger_contactdetails c
LEFT JOIN vtiger_crmentity e ON e.crmid = c.contactid
WHERE e.deleted = 0 AND c.mobile = ? LIMIT 1";
$res = $adb->pquery($query, array($mobile));
if ($adb->num_rows($res) > 0) {
$existingContactId = $adb->query_result($res, 0, 'contactid');
$searchMethod = 'by_mobile';
}
}
// 2.3 По tgid (приоритет 3) - tgid хранится в поле phone
if (empty($existingContactId) && !empty($tgid)) {
$query = "SELECT c.contactid FROM vtiger_contactdetails c
LEFT JOIN vtiger_crmentity e ON e.crmid = c.contactid
WHERE e.deleted = 0 AND c.phone = ? LIMIT 1";
$res = $adb->pquery($query, array($tgid));
if ($adb->num_rows($res) > 0) {
$existingContactId = $adb->query_result($res, 0, 'contactid');
$searchMethod = 'by_tgid';
}
}
$logstring = date('Y-m-d H:i:s') . ' Поиск: contact_id=' . $contact_id . ', mobile=' . $mobile . ', tgid=' . $tgid;
$logstring .= ' → Найден: ' . ($existingContactId ? $existingContactId . ' (' . $searchMethod . ')' : 'НЕТ');
file_put_contents($logFile, $logstring . PHP_EOL, FILE_APPEND);
// ========================================
// 3. ФОРМИРУЕМ ПАРАМЕТРЫ
// ========================================
$params = array();
// Только непустые поля добавляем в params
if (!empty($firstname)) $params['firstname'] = $firstname;
if (!empty($secondname)) $params['cf_1157'] = $secondname; // Отчество
if (!empty($lastname)) $params['lastname'] = $lastname;
if (!empty($mobile)) $params['mobile'] = $mobile;
if (!empty($email)) $params['email'] = $email;
if (!empty($tgid)) $params['phone'] = $tgid; // TG ID в поле phone
if (!empty($birthday)) $params['birthday'] = $birthday;
if (!empty($birthplace)) $params['cf_1263'] = $birthplace; // Место рождения
if (!empty($mailingstreet)) $params['mailingstreet'] = $mailingstreet;
if (!empty($inn)) $params['cf_1257'] = $inn; // ИНН
if (!empty($requisites)) $params['cf_1849'] = $requisites; // Реквизиты
if (!empty($code)) $params['cf_1580'] = $code; // SMS код
// ========================================
// 4. СОЗДАНИЕ ИЛИ ОБНОВЛЕНИЕ
// ========================================
try {
if (!empty($existingContactId)) {
// === ОБНОВЛЕНИЕ ===
$params['id'] = '12x' . $existingContactId;
$logstring = date('Y-m-d H:i:s') . ' 📝 Обновляем контакт ' . $existingContactId . ': ' . json_encode($params);
file_put_contents($logFile, $logstring . PHP_EOL, FILE_APPEND);
$contact = vtws_revise($params, $current_user);
$result['success'] = true;
$result['contact_id'] = $existingContactId;
$result['action'] = 'updated';
$result['search_method'] = $searchMethod;
$result['message'] = 'Контакт обновлён';
$logstring = date('Y-m-d H:i:s') . ' ✅ Контакт ' . $existingContactId . ' обновлён';
file_put_contents($logFile, $logstring . PHP_EOL, FILE_APPEND);
} else {
// === СОЗДАНИЕ ===
// Проверяем минимальные данные для создания
if (empty($mobile) && empty($tgid)) {
throw new WebServiceException(
WebServiceErrorCode::$INVALIDID,
"Для создания контакта нужен хотя бы mobile или tgid"
);
}
// Дефолтные значения для обязательных полей CRM
if (empty($params['firstname'])) {
$params['firstname'] = 'Клиент';
}
if (empty($params['lastname'])) {
$suffix = !empty($mobile) ? substr($mobile, -4) : substr($tgid, -4);
$params['lastname'] = 'Web_' . $suffix;
}
if (empty($params['birthday'])) {
$params['birthday'] = '01-01-1990';
}
// Назначаем ответственного
$params['assigned_user_id'] = vtws_getWebserviceEntityId('Users', $current_user->id);
$logstring = date('Y-m-d H:i:s') . ' 🆕 Создаём контакт: ' . json_encode($params);
file_put_contents($logFile, $logstring . PHP_EOL, FILE_APPEND);
$contact = vtws_create('Contacts', $params, $current_user);
$newContactId = substr($contact['id'], 3); // Убираем 12x
$result['success'] = true;
$result['contact_id'] = $newContactId;
$result['action'] = 'created';
$result['message'] = 'Контакт создан';
$logstring = date('Y-m-d H:i:s') . ' ✅ Создан контакт ' . $newContactId;
file_put_contents($logFile, $logstring . PHP_EOL, FILE_APPEND);
}
} catch (WebServiceException $ex) {
$result['success'] = false;
$result['message'] = $ex->getMessage();
$logstring = date('Y-m-d H:i:s') . ' ❌ Ошибка: ' . $ex->getMessage();
file_put_contents($logFile, $logstring . PHP_EOL, FILE_APPEND);
throw $ex;
}
$logstring = date('Y-m-d H:i:s') . ' RESULT: ' . json_encode($result, JSON_UNESCAPED_UNICODE) . PHP_EOL;
file_put_contents($logFile, $logstring, FILE_APPEND);
return json_encode($result, JSON_UNESCAPED_UNICODE);
}