Настройка маркировки товаров на 1С-Битрикс
С 2020–2023 годов большинство товарных групп подпадает под обязательную маркировку «Честный знак»: одежда, обувь, лекарства, молочная продукция, табак, шины, духи, фотоаппараты. При продаже через интернет-магазин коды маркировки должны передаваться в кассовый чек, а при приёмке и отгрузке — в систему мониторинга МДЛП или ГИС МТ.
Архитектура маркировки в Битрикс
Битрикс не имеет встроенного модуля для работы с «Честным знаком». Интеграция строится из нескольких компонентов:
- Хранение кодов маркировки — привязка кодов DataMatrix к конкретным единицам товара
- Передача кода в кассовый чек — через кассовый модуль (АТОЛ, ЮКасса и др.)
- Отчётность в ГИС МТ — при продаже выбывание кода из оборота
Код маркировки (КМ) — строка вида 010460437166456221hHdB3ePhGH1I\u001d91EE06\u001d92XqnSm5YoGVLWJjOz...
Хранение кодов маркировки
Коды привязываются к SKU (торговым предложениям) инфоблока каталога. Варианты хранения:
Вариант 1 — Свойство инфоблока. Добавить свойство MARKING_CODE типа «Строка» или «HTML/Текст» к инфоблоку торговых предложений:
// Создать свойство программно
CIBlockProperty::Add([
'NAME' => 'Код маркировки',
'CODE' => 'MARKING_CODE',
'IBLOCK_ID' => OFFERS_IBLOCK_ID,
'PROPERTY_TYPE' => 'S',
'MULTIPLE' => 'N',
'ACTIVE' => 'Y'
]);
Вариант 2 — Отдельная таблица для проектов с большим оборотом (10 000+ кодов):
CREATE TABLE b_marking_codes (
ID INT AUTO_INCREMENT PRIMARY KEY,
PRODUCT_ID INT NOT NULL,
CODE VARCHAR(255) NOT NULL UNIQUE,
STATUS ENUM('available', 'reserved', 'sold', 'returned') DEFAULT 'available',
ORDER_ID INT NULL,
DATE_SOLD DATETIME NULL,
INDEX idx_product_status (PRODUCT_ID, STATUS),
INDEX idx_code (CODE)
);
Привязка кода маркировки к позиции корзины
При добавлении товара в корзину нужно зарезервировать конкретный код:
// Обработчик OnSaleBasketItemEntitySaved или кастомная логика
AddEventHandler('sale', 'OnSaleBasketBeforeSaved', function(\Bitrix\Main\Event $event) {
$basketItem = $event->getParameter('ENTITY');
$productId = $basketItem->getProductId();
// Найти свободный код маркировки
$res = \Bitrix\Main\Application::getConnection()->query(
"SELECT ID, CODE FROM b_marking_codes
WHERE PRODUCT_ID = {$productId} AND STATUS = 'available'
LIMIT 1 FOR UPDATE"
);
$codeRow = $res->fetch();
if ($codeRow) {
// Зарезервировать код
\Bitrix\Main\Application::getConnection()->query(
"UPDATE b_marking_codes SET STATUS = 'reserved', ORDER_ID = NULL
WHERE ID = {$codeRow['ID']}"
);
// Сохранить код в свойстве позиции корзины
$basketItem->setField('PROPS', [
'MARKING_CODE' => $codeRow['CODE']
]);
}
});
Передача кода в кассовый чек
Кассовый чек по 54-ФЗ с маркированным товаром должен содержать код маркировки в теге 1163. АТОЛ Онлайн и другие операторы принимают его в поле marking_code.
Доработка обработчика кассового модуля (расширение класса):
// Перехватить формирование позиций чека
AddEventHandler('sale', 'OnCashboxBuildCheck', function($checkData) {
foreach ($checkData['ITEMS'] as &$item) {
$basketItemId = $item['BASKET_ID'] ?? null;
if ($basketItemId) {
// Получить код маркировки из свойств позиции
$res = \Bitrix\Sale\Internals\BasketPropertiesTable::getList([
'filter' => ['BASKET_ID' => $basketItemId, 'CODE' => 'MARKING_CODE'],
'select' => ['VALUE']
]);
if ($prop = $res->fetch()) {
$item['MARKING_CODE'] = $prop['VALUE'];
}
}
}
return $checkData;
});
Выбывание кода после продажи
После фискализации чека код маркировки должен перейти в статус «Продан» и выбыть из оборота в ГИС МТ. Это либо автоматически через кассу (если ОФД интегрирован с «Честным знаком»), либо вручную через API ГИС МТ.
Обновление статуса кода после оплаты:
AddEventHandler('sale', 'OnSalePaymentEntitySaved', function(\Bitrix\Main\Event $event) {
$payment = $event->getParameter('ENTITY');
if ($payment->getField('PAID') === 'Y') {
$order = $payment->getOrder();
$basket = $order->getBasket();
foreach ($basket as $basketItem) {
$props = $basketItem->getPropertyCollection();
// Найти код маркировки в свойствах позиции
foreach ($props as $prop) {
if ($prop->getField('CODE') === 'MARKING_CODE') {
$code = $prop->getField('VALUE');
\Bitrix\Main\Application::getConnection()->query(
"UPDATE b_marking_codes SET STATUS = 'sold',
ORDER_ID = {$order->getId()},
DATE_SOLD = NOW()
WHERE CODE = '" . \Bitrix\Main\Application::getConnection()->getSqlHelper()->forSql($code) . "'"
);
}
}
}
}
});
Импорт кодов маркировки
Коды поступают от поставщика в виде файла (CSV, Excel) или через EDI. Для массового импорта:
// CLI-скрипт импорта
$codes = file('/path/to/marking_codes.txt', FILE_IGNORE_NEW_LINES);
$db = \Bitrix\Main\Application::getConnection();
$productId = 1234; // ID торгового предложения
foreach (array_chunk($codes, 1000) as $batch) {
$values = implode(',', array_map(function($code) use ($productId, $db) {
return "({$productId}, '" . $db->getSqlHelper()->forSql(trim($code)) . "', 'available')";
}, $batch));
$db->query("INSERT IGNORE INTO b_marking_codes (PRODUCT_ID, CODE, STATUS) VALUES {$values}");
}







