Files
crm.clientright.ru/include/Webservices/UpsertAccounts.php

225 lines
10 KiB
PHP
Raw Normal View History

<?php
/*********************************************************************************
* API-интерфейс для создания/поиска нескольких Контрагентов (Upsert Batch)
*
* Принимает JSON массив offenders, для каждого:
* - Ищет по ИНН
* - Если найден возвращает ID (БЕЗ обновления)
* - Если не найден создаёт новый
*
* Возвращает массив результатов с account_id для каждого offender
*
* Автор: Фёдор, 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 'includes/Loader.php';
vimport('includes.runtime.Globals');
vimport('includes.runtime.BaseModel');
vimport('includes.runtime.LanguageHandler');
/**
* Upsert нескольких контрагентов
*
* @param string $offenders_json - JSON массив offenders:
* [
* {
* "accountname": "ООО Рога и Копыта",
* "address": "Москва, ул. Ленина 1",
* "email": "info@example.com",
* "website": "example.com",
* "phone": "+7 999 123-45-67",
* "inn": "7712345678",
* "ogrn": "1234567890123",
* "role": "Турагент" // опционально, для информации
* },
* ...
* ]
* @param mixed $user - пользователь CRM
* @return string JSON с результатами
*/
function vtws_upsertaccounts($offenders_json, $user = false) {
$logFile = 'logs/UpsertAccounts.log';
$logstring = date("Y-m-d H:i:s") . ' REQUEST: ' . substr($offenders_json, 0, 2000);
file_put_contents($logFile, $logstring . PHP_EOL, FILE_APPEND);
global $adb, $current_user;
// Очистка JSON от мусора (лишние кавычки, BOM, пробелы)
$offenders_json = trim($offenders_json);
$offenders_json = preg_replace('/^\xEF\xBB\xBF/', '', $offenders_json); // Убираем BOM
// Если строка обёрнута в кавычки — убираем
if (preg_match('/^".*"$/s', $offenders_json)) {
$offenders_json = substr($offenders_json, 1, -1);
$offenders_json = stripcslashes($offenders_json); // Убираем экранирование
}
// Убираем лишнюю кавычку в конце (баг n8n)
$offenders_json = preg_replace('/"\s*$/', '', rtrim($offenders_json, '"'));
if (substr($offenders_json, -1) !== ']' && substr($offenders_json, -1) !== '}') {
// Пробуем найти конец массива/объекта
if (($pos = strrpos($offenders_json, ']')) !== false) {
$offenders_json = substr($offenders_json, 0, $pos + 1);
}
}
$logstring = date("Y-m-d H:i:s") . ' CLEANED JSON: ' . substr($offenders_json, 0, 500);
file_put_contents($logFile, $logstring . PHP_EOL, FILE_APPEND);
// Парсим JSON
$offenders = json_decode($offenders_json, true);
if (json_last_error() !== JSON_ERROR_NONE) {
$error = 'Ошибка парсинга JSON: ' . json_last_error_msg();
file_put_contents($logFile, date("Y-m-d H:i:s") . ' ❌ ' . $error . PHP_EOL, FILE_APPEND);
file_put_contents($logFile, date("Y-m-d H:i:s") . ' RAW: ' . $offenders_json . PHP_EOL, FILE_APPEND);
throw new WebServiceException(WebServiceErrorCode::$INVALIDID, $error);
}
if (!is_array($offenders)) {
$offenders = [$offenders]; // Если передан один объект — оборачиваем в массив
}
$logstring = date('Y-m-d H:i:s') . ' Получено offenders: ' . count($offenders);
file_put_contents($logFile, $logstring . PHP_EOL, FILE_APPEND);
// Результаты
$results = array(
'success' => true,
'total' => count($offenders),
'created' => 0,
'found' => 0,
'errors' => 0,
'accounts' => array()
);
// Обрабатываем каждого offender
foreach ($offenders as $index => $offender) {
$accountResult = array(
'index' => $index,
'success' => false,
'account_id' => null,
'action' => null,
'accountname' => $offender['accountname'] ?? '',
'inn' => $offender['inn'] ?? '',
'role' => $offender['role'] ?? null,
'message' => ''
);
try {
// Извлекаем данные
$accountname = trim($offender['accountname'] ?? '');
$address = trim($offender['address'] ?? '');
$email = trim($offender['email'] ?? '');
$website = trim($offender['website'] ?? '');
$phone = trim($offender['phone'] ?? '');
$inn = preg_replace('/[^0-9]/', '', $offender['inn'] ?? ''); // Только цифры
$ogrn = preg_replace('/[^0-9]/', '', $offender['ogrn'] ?? ''); // Только цифры
$role = trim($offender['role'] ?? '');
// Проверка обязательных полей
if (empty($accountname)) {
throw new Exception('Не указано наименование контрагента (accountname)');
}
if (empty($inn)) {
throw new Exception('Не указан ИНН');
}
// Валидация ИНН (10 или 12 цифр)
if (strlen($inn) != 10 && strlen($inn) != 12) {
$logstring = date('Y-m-d H:i:s') . " ⚠️ Нестандартный ИНН: $inn (длина " . strlen($inn) . ')';
file_put_contents($logFile, $logstring . PHP_EOL, FILE_APPEND);
// Не падаем, просто логируем
}
// ========================================
// ПОИСК ПО ИНН
// ========================================
$query = "SELECT a.accountid, a.accountname
FROM vtiger_account a
LEFT JOIN vtiger_crmentity e ON e.crmid = a.accountid
WHERE e.deleted = 0 AND a.inn = ?
LIMIT 1";
$res = $adb->pquery($query, array($inn));
if ($adb->num_rows($res) > 0) {
// === НАЙДЕН — просто возвращаем ID ===
$existingId = $adb->query_result($res, 0, 'accountid');
$existingName = $adb->query_result($res, 0, 'accountname');
$accountResult['success'] = true;
$accountResult['account_id'] = $existingId;
$accountResult['action'] = 'found';
$accountResult['message'] = 'Контрагент найден по ИНН';
$accountResult['existing_name'] = $existingName;
$results['found']++;
$logstring = date('Y-m-d H:i:s') . " ✓ [$index] Найден: $existingId ($existingName) по ИНН $inn";
file_put_contents($logFile, $logstring . PHP_EOL, FILE_APPEND);
} else {
// === НЕ НАЙДЕН — создаём ===
$params = array(
'accountname' => $accountname,
'bill_street' => $address,
'email1' => $email,
'website' => $website,
'phone' => $phone,
'inn' => $inn,
'cf_1951' => $ogrn, // ОГРН в кастомном поле
'assigned_user_id' => vtws_getWebserviceEntityId('Users', $current_user->id)
);
$logstring = date('Y-m-d H:i:s') . " 🆕 [$index] Создаём: " . json_encode($params, JSON_UNESCAPED_UNICODE);
file_put_contents($logFile, $logstring . PHP_EOL, FILE_APPEND);
$account = vtws_create('Accounts', $params, $current_user);
$newAccountId = substr($account['id'], 3); // Убираем 11x
$accountResult['success'] = true;
$accountResult['account_id'] = $newAccountId;
$accountResult['action'] = 'created';
$accountResult['message'] = 'Контрагент создан';
$results['created']++;
$logstring = date('Y-m-d H:i:s') . " ✅ [$index] Создан: $newAccountId";
file_put_contents($logFile, $logstring . PHP_EOL, FILE_APPEND);
}
} catch (WebServiceException $ex) {
$accountResult['success'] = false;
$accountResult['message'] = $ex->getMessage();
$results['errors']++;
$logstring = date('Y-m-d H:i:s') . " ❌ [$index] WebService ошибка: " . $ex->getMessage();
file_put_contents($logFile, $logstring . PHP_EOL, FILE_APPEND);
} catch (Exception $ex) {
$accountResult['success'] = false;
$accountResult['message'] = $ex->getMessage();
$results['errors']++;
$logstring = date('Y-m-d H:i:s') . " ❌ [$index] Ошибка: " . $ex->getMessage();
file_put_contents($logFile, $logstring . PHP_EOL, FILE_APPEND);
}
$results['accounts'][] = $accountResult;
}
// Итоговый статус
$results['success'] = ($results['errors'] == 0);
$logstring = date('Y-m-d H:i:s') . ' RESULT: total=' . $results['total']
. ', created=' . $results['created']
. ', found=' . $results['found']
. ', errors=' . $results['errors'] . PHP_EOL;
file_put_contents($logFile, $logstring, FILE_APPEND);
return json_encode($results, JSON_UNESCAPED_UNICODE);
}