<?php
/**
* Bitrix24 VAT Updater Tool
* Скрипт для массового обновления ставки НДС товаров и торговых предложений (SKU).
* Автоматически определяет ID инфоблоков каталога.
*/
// --- КОНФИГУРАЦИЯ ---
const WEBHOOK_URL = 'https://ваш-портал.bitrix24.ru/rest/1/ключ/'; // Укажите ваш вебхук
const TARGET_VAT = 5; // ID ставки НДС (см. настройки CRM -> Налоги)
const BATCH_SIZE = 50; // Количество товаров за один шаг (рекомендуется 50)
const SLEEP_TIME = 10000; // Пауза между запросами в мкс (анти-DDOS)
// --- СИСТЕМНЫЕ НАСТРОЙКИ ---
ini_set('display_errors', 0);
error_reporting(E_ALL);
ini_set('max_execution_time', 300);
// --- ОБРАБОТКА AJAX ЗАПРОСА ---
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
while (ob_get_level()) ob_end_clean();
header('Content-Type: application/json');
try {
$input = json_decode(file_get_contents('php://input'), true);
$lastId = intval($input['lastId'] ?? 0);
$offersIblockId = intval($input['offersIblockId'] ?? 0);
$mainIblockId = intval($input['mainIblockId'] ?? 0);
$logs = [];
// 1. Автоматический поиск ID инфоблоков, если они не переданы
if ($mainIblockId === 0) {
$ids = getCatalogIds();
$mainIblockId = $ids['main'];
$offersIblockId = $ids['offers'];
if ($mainIblockId > 0) {
$logs[] = ['type' => 'info', 'msg' => "ℹ️ Основной каталог: ID <b>{$mainIblockId}</b>"];
} else {
throw new Exception("Не удалось определить ID каталога товаров.");
}
if ($offersIblockId > 0) {
$logs[] = ['type' => 'info', 'msg' => "ℹ️ Каталог SKU: ID <b>{$offersIblockId}</b>"];
}
}
// 2. Получение списка товаров (пагинация по ID)
$filter = [
'>id' => $lastId,
'iblockId' => $mainIblockId
];
$params = [
'filter' => $filter,
'select' => ['id', 'iblockId', 'name', 'parentId'],
'order' => ['id' => 'ASC'],
'start' => 0,
'limit' => BATCH_SIZE
];
$response = callB24('catalog.product.list', $params);
if (isset($response['error'])) {
throw new Exception("API Error: " . ($response['error_description'] ?? $response['error']));
}
$products = $response['result']['products'] ?? $response['result'] ?? [];
// Если товары закончились
if (empty($products)) {
echo json_encode(['finished' => true, 'logs' => $logs]);
exit;
}
$currentLastId = $lastId;
foreach ($products as $product) {
$id = $product['id'] ?? $product['ID'];
if (!$id) continue;
$currentLastId = $id;
// Пропускаем SKU, если они случайно попали в выборку (обрабатываем только родителей)
if (!empty($product['parentId'] ?? $product['PARENT_ID'])) {
continue;
}
$name = $product['name'] ?? $product['NAME'] ?? "Без названия ($id)";
$logs[] = ['type' => 'head', 'msg' => "📦 <b>#{$id}</b> " . htmlspecialchars($name)];
// Обновляем Родителя
$resParent = updateProduct($id, TARGET_VAT);
$logs[] = ['type' => 'row', 'msg' => "Родитель: " . $resParent];
// Обновляем SKU (если есть)
$skuHtml = processSku($id, TARGET_VAT, $offersIblockId);
if ($skuHtml) {
$logs[] = ['type' => 'row', 'msg' => $skuHtml];
} else {
$logs[] = ['type' => 'info', 'msg' => "↳ Вариаций нет."];
}
}
echo json_encode([
'finished' => false,
'nextId' => $currentLastId,
'offersIblockId' => $offersIblockId,
'mainIblockId' => $mainIblockId,
'logs' => $logs
]);
} catch (Exception $e) {
echo json_encode(['finished' => true, 'logs' => [['type' => 'error', 'msg' => "Error: " . $e->getMessage()]]]);
}
exit;
}
// --- ФУНКЦИИ ---
function getCatalogIds() {
$res = callB24('catalog.catalog.list', []);
$catalogs = $res['result']['catalogs'] ?? $res['result'] ?? [];
$mainId = 0;
$offersId = 0;
// Ищем связку каталогов
foreach ($catalogs as $cat) {
if (isset($cat['productIblockId']) && $cat['productIblockId'] > 0) {
$offersId = $cat['iblockId'] ?? $cat['id'];
$mainId = $cat['productIblockId'];
break;
}
}
// Если SKU каталог не найден, берем первый попавшийся простой каталог
if ($mainId === 0 && !empty($catalogs)) {
foreach ($catalogs as $cat) {
if (!isset($cat['productIblockId']) || $cat['productIblockId'] == 0) {
$mainId = $cat['iblockId'] ?? $cat['id'];
break;
}
}
}
................................Получить полную версию скрипта по ссылке ниже