Розробка кастомних імпорт/експорт модулів 1С-Бітрікс
Стандартний обмін через CommerceML покриває типові завдання з 1С: каталог, замовлення, залишки. Але коли дані надходять у нестандартному форматі — XML від постачальника, JSON з CRM, XLSX‑звіти — продуктивність падає, а маппінг перетворюється на квест. Кастомний модуль імпорту/експорту вирішує цю проблему: він працює безпосередньо з будь-яким джерелом, використовує потокову обробку для великих обсягів та підтримує двосторонню синхронізацію з контролем колізій. Ми розробляємо такі модулі під ключ: від аналізу схем до деплою та навчання адміністраторів. Наша команда займається кастомною розробкою понад 8 років і успішно впровадила 50+ інтеграцій для рітейлу, логістики та виробництва. Оцінимо проект за один день — зв'яжіться з нами для консультації.
Типовий сценарій: у вас є зовнішній склад або ERP‑система, яка віддає дані у форматі CommerceML. Але CommerceML — це важкий XML, який при обсягах понад 10 000 товарів за одне завантаження обробляється годинами. Кастомний модуль парсить дані власним парсером, використовуючи XMLReader для потокового читання, і може обробляти до 1 000 елементів на секунду. Різниця — у 3–5 разів швидше за стандартний обмін. Крім того, ми реалізуємо пакетну обробку з агентами Бітрікс, що виключає тайм-аути веб-запитів.
Коли CommerceML не справляється?
CommerceML — універсальний протокол, але він не завжди гнучкий. Якщо ваше джерело даних — JSON API стороннього сервісу, бінарний XLSX з тисячами рядків або потрібне складне перетворення полів (об'єднання, видалення дублів, зв'язок з довідниками), стандартний обмін неефективний. Кастомний модуль дозволяє обробляти довільні формати: XML (будь-яка схема), CSV, XLSX, JSON, а також забирати файли по FTP/SFTP. При обсягах від 100 000 записів обов'язкове чанкове завантаження — ми вбудовуємо його в ядро модуля.
Як працює двостороння синхронізація?
Найскладніше — уникнути колізій при одночасних змінах в обох системах. Ми використовуємо timestamp-based sync з полем sync_hash. При експорті записуємо хеш стану запису. При наступному імпорті: якщо хеш змінився в джерелі — оновлюємо в Бітрікс; якщо змінився в Бітрікс (користувач відредагував) — надсилаємо зміни назад у джерело. Якщо обидва змінилися — конфлікт, логуємо для ручного розбору.
SQL для додавання поля sync_hash
ALTER TABLE b_iblock_element ADD COLUMN sync_hash VARCHAR(32); ALTER TABLE b_iblock_element ADD COLUMN synced_at DATETIME; Архітектура кастомного модуля
Модуль Бітрікс — це директорія в /local/modules/{vendor}.{modulename}/, зареєстрована через RegisterModule. Стандартна структура:
local/modules/company.import/ ├── install/ │ ├── index.php # InstallDB(), UnInstallDB(), DoInstall() │ └── db/mysql/install.sql ├── lib/ │ ├── Importer.php # основна логіка │ ├── Parser/ │ │ ├── XmlParser.php │ │ └── CsvParser.php │ └── Queue/ │ └── ImportQueue.php ├── admin/ │ └── import_settings.php # адміністративний інтерфейс ├── include.php └── .settings.php Імпорт з довільного XML-джерела
Приклад реалізації парсера для кастомної схеми:
namespace Company\Import; use Bitrix\Main\Loader; use Bitrix\Catalog\ProductTable; class Importer { private \SimpleXMLElement $xml; public function __construct(string $filePath) { Loader::includeModule('iblock'); Loader::includeModule('catalog'); $this->xml = simplexml_load_file($filePath); } public function run(): array { $stats = ['created' => 0, 'updated' => 0, 'errors' => 0]; foreach ($this->xml->products->product as $product) { try { $this->processProduct($product, $stats); } catch (\Throwable $e) { \Bitrix\Main\Diag\Debug::writeToFile($e->getMessage(), 'IMPORT ERROR', '/bitrix/modules/company.import/error.log'); $stats['errors']++; } } return $stats; } private function processProduct(\SimpleXMLElement $p, array &$stats): void { $externalId = (string)$p->id; $existing = $this->findByExternalId($externalId); $fields = [ 'IBLOCK_ID' => IMPORT_IBLOCK_ID, 'NAME' => (string)$p->name, 'CODE' => \CUtil::translit((string)$p->name, 'ru'), 'ACTIVE' => (string)$p->is_active === '1' ? 'Y' : 'N', 'PROPERTY_VALUES' => [ 'EXTERNAL_ID' => $externalId, 'VENDOR_CODE' => (string)$p->sku, 'DESCRIPTION' => (string)$p->description, ], ]; if ($existing) { \CIBlockElement::Update($existing, $fields); $stats['updated']++; } else { $el = new \CIBlockElement(); $newId = $el->Add($fields); if (!$newId) throw new \RuntimeException($el->LAST_ERROR); $stats['created']++; } // Оновлюємо ціну та залишок \CPrice::SetBasePrice($newId ?? $existing, (float)$p->price, 'RUB'); \CCatalogProduct::Update($newId ?? $existing, ['QUANTITY' => (int)$p->stock]); } } Пакетна обробка та агенти
При 100 000+ записах прямий веб-запит неможливий — timeout. Використовуємо агент Бітрікс із збереженням прогресу в БД. Агент викликається кожну хвилину і обробляє наступний чанк:
class ImportQueue { public static function processChunk(int $jobId, int $offset, int $limit = 500): array { $job = ImportJobTable::getById($jobId)->fetch(); // ... читаем $limit строк начиная с $offset // ... обрабатываем // ... обновляем прогресс в БД return ['processed' => $count, 'total' => $job['total_rows']]; } } function ImportAgent(): string { $activeJob = getActiveImportJob(); if (!$activeJob) return ''; $result = ImportQueue::processChunk($activeJob['id'], $activeJob['offset']); if ($activeJob['offset'] + $result['processed'] >= $result['total']) { markJobComplete($activeJob['id']); return ''; } return 'ImportAgent();'; } Експорт даних
Експорт у довільний формат для зовнішньої системи:
class Exporter { public function exportOrders(\DateTime $from, \DateTime $to): string { $orders = \Bitrix\Sale\OrderTable::getList([ 'filter' => [ '>=DATE_INSERT' => $from->format('d.m.Y H:i:s'), '<=DATE_INSERT' => $to->format('d.m.Y H:i:s'), 'CANCELED' => 'N', ], 'select' => ['ID', 'ACCOUNT_NUMBER', 'PRICE', 'CURRENCY', 'DATE_INSERT', 'USER_ID'], ])->fetchAll(); $xml = new \XMLWriter(); $xml->openMemory(); $xml->startDocument('1.0', 'UTF-8'); $xml->startElement('orders'); foreach ($orders as $order) { $xml->startElement('order'); $xml->writeElement('id', $order['ID']); $xml->writeElement('number', $order['ACCOUNT_NUMBER']); $xml->writeElement('amount', $order['PRICE']); $xml->writeElement('date', $order['DATE_INSERT']->format(\DateTime::ATOM)); // ... позиции заказа $xml->endElement(); } $xml->endElement(); return $xml->outputMemory(); } } Формати та джерела
| Формат/Джерело | Інструменти | Особливості |
|---|---|---|
| XML (кастомний) | SimpleXML, XMLReader | XMLReader для файлів > 100 МБ |
| CSV/XLSX | PhpSpreadsheet, fgetcsv | XLSX — бінарний, потребує бібліотеку |
| JSON REST API | curl, Guzzle | Пагінація, rate limiting |
| FTP/SFTP | phpseclib | Автоматичне завантаження файлів |
| 1С CommerceML | Вбудований обмін Бітрікс | Кастомізація через події |
| Google Sheets | Google Sheets API v4 | Для невеликих обсягів |
Як прискорити імпорт великих каталогів?
При обсязі понад 50 000 товарів стандартний обмін впирається в обмеження PHP за часом виконання та пам'яттю. Кастомний модуль використовує асинхронні агенти, чанкове завантаження та профілювання запитів. Ми додаємо індекси на зовнішні ID та дату синхронізації, що прискорює пошук дублів у 10 разів. У результатах клієнти отримують імпорт 100 000 елементів за 2–3 хвилини замість години.
Строки та вартість
Вартість розробки розраховується індивідуально і залежить від складності маппінгу, кількості форматів та необхідності двосторонньої синхронізації. Точну оцінку ми надамо після аналізу ваших даних.
| Етап | Термін |
|---|---|
| Аналіз форматів та маппінг полів | 1–2 дні |
| Розробка парсера/експортера | 3–5 днів |
| Пакетна обробка, агент Бітрікс | 2–3 дні |
| Адміністративний інтерфейс | 2–3 дні |
| Двостороння синхронізація (якщо потрібна) | 3–5 днів |
| Тестування на реальних даних | 2–3 дні |
Разом: 2–3 тижні для одностороннього імпорту; 3–4 тижні для двосторонньої синхронізації.
Що входить у роботу
- Вихідний код модуля з коментарями.
- Документація API модуля та інструкція з налаштування.
- Доступ до репозиторію (Git) з історією змін.
- Навчання адміністраторів (до 2 годин онлайн).
- Гарантія 3 місяці на безперебійну роботу.
Отримайте консультацію інженера — замовте попередній аудит вашого обміну. CommerceML — протокол обміну







