Разработка модуля загрузки заказа из файла 1С-Битрикс
На B2B-проектах менеджеры закупщика работают с прайс-листами. У них есть Excel-файл с артикулами и количеством, и они хотят загрузить его в корзину, а не кликать по каталогу. Стандартный Битрикс этого не умеет — нужен отдельный модуль.
Поддерживаемые форматы файлов
Практика показывает три основных формата, которые приходят от клиентов:
-
XLSX / XLS — самый распространённый. Парсинг через
PhpSpreadsheet(устанавливается вlocal/vendor/через composer). - CSV — простой вариант, часто используется в автоматизированных выгрузках из 1С.
- XML — реже, но встречается на проектах с EDI-интеграцией.
Загрузка PDF не поддерживается — из него нельзя надёжно извлечь табличные данные.
Структура модуля
Модуль регистрируется в local/modules/vendor.orderimport/. Основные компоненты:
-
lib/FileParser/XlsxParser.php— парсер XLSX -
lib/FileParser/CsvParser.php— парсер CSV -
lib/ProductMatcher.php— поиск товаров по артикулу -
lib/CartFiller.php— заполнение корзины -
components/vendor/orderimport.form/— компонент формы загрузки
Парсинг файла
Загруженный файл сохраняется во временную директорию, определяется его тип по расширению и MIME-типу, затем запускается соответствующий парсер. Парсер возвращает массив строк:
// Результат парсинга: массив позиций
[
['sku' => 'ART-1234', 'qty' => 5, 'row' => 2],
['sku' => 'ART-5678', 'qty' => 10, 'row' => 3],
// ...
]
Парсер пропускает строки заголовка (первая строка или строка, где в колонке артикула текст вместо числа). Гибкая настройка: номера колонок для артикула и количества задаются в настройках модуля или определяются автоматически по заголовкам.
Поиск товаров по артикулу
Артикул в Битрикс хранится в нескольких местах: поле XML_ID элемента инфоблока, свойство ARTICLE (если используется), поле ARTICLE в таблице b_catalog_product. Поиск ведётся последовательно:
// 1. Поиск по b_catalog_product.ARTICLE
$product = \Bitrix\Catalog\ProductTable::getList([
'filter' => ['=ARTICLE' => $sku],
'select' => ['ID', 'ARTICLE'],
])->fetch();
// 2. Если не найден — поиск по XML_ID элемента инфоблока
if (!$product) {
$element = \CIBlockElement::GetList(
[],
['=XML_ID' => $sku, 'IBLOCK_ID' => $catalogIblockId],
false, false,
['ID', 'XML_ID']
)->Fetch();
}
Результат поиска по каждой строке — статус: found (найден), not_found (не найден), multiple (найдено несколько с одним артикулом — неоднозначность).
Предпросмотр перед добавлением в корзину
Пользователь загружает файл → видит таблицу с результатом парсинга: для каждой строки показывается найденный товар (название, фото, цена, доступный остаток), количество из файла и статус. Строки со статусом not_found подсвечиваются — пользователь может вручную указать товар из каталога.
Только после подтверждения пользователем данные отправляются в корзину. Это защищает от случайных ошибок в файле.
Заполнение корзины
use Bitrix\Sale\Basket;
use Bitrix\Sale\BasketItem;
$basket = Sale\Basket::loadItemsForFUser(Sale\Fuser::getId(), SITE_ID);
foreach ($confirmedItems as $item) {
$basketItem = $basket->getExistsItem('catalog', $item['product_id']);
if ($basketItem) {
$basketItem->setField('QUANTITY', $basketItem->getQuantity() + $item['qty']);
} else {
$newItem = $basket->createItem('catalog', $item['product_id']);
$newItem->setFields([
'QUANTITY' => $item['qty'],
'PRODUCT_PROVIDER_CLASS' => \CCatalogProductProvider::class,
'LID' => SITE_ID,
'CURRENCY' => \Bitrix\Currency\CurrencyManager::getBaseCurrency(),
]);
}
}
$basket->save();
Шаблон файла для скачивания
На странице загрузки выводится ссылка для скачивания шаблона — готового XLSX-файла с заголовками колонок («Артикул», «Количество», «Примечание») и примером данных. Шаблон генерируется через PhpSpreadsheet при каждом запросе или отдаётся как статичный файл.
Логирование загрузок
Все попытки загрузки записываются в таблицу b_orderimport_log:
| Поле | Тип | Назначение |
|---|---|---|
| ID | int auto_increment | — |
| USER_ID | int | Кто загружал |
| FILE_NAME | varchar(255) | Оригинальное имя файла |
| ROWS_TOTAL | int | Строк в файле |
| ROWS_FOUND | int | Найдено товаров |
| ROWS_ADDED | int | Добавлено в корзину |
| STATUS | enum | SUCCESS, PARTIAL, FAILED |
| CREATED_AT | datetime | — |
Сроки разработки
| Масштаб | Состав | Срок |
|---|---|---|
| Базовый | Парсинг XLSX/CSV, поиск по артикулу, добавление в корзину | 5–7 дней |
| Стандартный | + Предпросмотр, ручное сопоставление ненайденных, шаблон файла | 9–12 дней |
| Расширенный | + XML-формат, логирование, поддержка нескольких колонок цен, проверка остатков | 14–18 дней |







