Налаштування маркирування товарів на 1С-Bitrix
З 2020–2023 років більшість товарних груп підпадає під обов'язкове маркирування «Чесний знак»: одяг, взуття, ліки, молочна продукція, тютюн, шини, парфуми, фотоапарати. При продажу через інтернет-магазин коди маркирування мають передаватися в касовий чек, а при приймці та відправці — в систему моніторингу МДЛП або ГІС МТ.
Архітектура маркирування в Bitrix
Bitrix не має вбудованого модуля для роботи з «Чесним знаком». Інтеграція будується з кількох компонентів:
- Зберігання кодів маркирування — привязка кодів 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}");
}







