Как программно списать коды маркировки в системе "Честный ЗНАК" из 1С?

Программист 1С v7.7 Управленческий учет Торговля и дистрибуция
← На главную

Приветствуем вас! Сегодня мы с вами разберем одну из важных задач при работе с маркированными товарами — программное списание кодов маркировки (КМ) в системе "Честный ЗНАК" (ЧЗ) непосредственно из вашей конфигурации 1С. Эта процедура необходима, когда товар выбывает из оборота не через розничную продажу, и требует точного учета и соблюдения законодательных требований. API "Честного ЗНАКа", используя примеры кода 1С.

Почему важно программное списание кодов маркировки?

Мы выясним, что списание кодов маркировки требуется во многих случаях, когда товар перестает быть частью вашего товарного оборота, но не продается через кассу. Давайте рассмотрим наиболее распространенные причины: * **Безвозмездная передача:** например, для рекламных целей или в качестве подарка. * **Дистанционная продажа:** когда товар отправляется покупателю без использования стандартной кассы. * **Использование для производственных или собственных нужд:** когда маркированный товар используется как сырье или для внутренних потребностей компании. * **Порча, утеря, истечение срока годности:** если товар стал непригоден или был утрачен. * **Конфискация, утилизация, уничтожение:** принудительное или добровольное выведение товара из оборота. * **Экспорт за пределы ЕАЭС:** при вывозе товара из стран Евразийского экономического союза. * **Продажа по госконтракту, по образцам, по сделке с гостайной, через вендинговый аппарат.** Подобные интеграции встречаются и в других сферах, например, когда требуется отражение движений в ГИИС ДМДК для драгоценных металлов. * **Другие причины:** если ни одна из перечисленных причин не подходит, всегда можно указать "Другое" и подробно описать ситуацию. Для осуществления списания через API вам понадобится усиленная квалифицированная электронная подпись (УКЭП), и, конечно же, вы должны быть зарегистрированы в системе "Честный ЗНАК". Сведения о списании можно подавать как через личный кабинет ЧЗ вручную, так и программно, используя True API. Именно второй вариант мы с вами и разберем.

Общие принципы работы с API "Честного ЗНАКа" для списания

Давайте проанализируем, как происходит взаимодействие с ЧЗ через API. Для создания документов списания используется единый метод `POST /lk/documents/create` для большинства товарных групп. Этот метод является актуальным и пришел на смену устаревающим. Существует несколько вариантов отправки API-запросов, некоторые из которых корректно работают даже на устаревших версиях Windows, что критично для пользователей 1С 7.7. При формировании запроса в формате JSON для списания, мы должны указать следующие ключевые данные: * **ИНН участника оборота** (`inn`). * **Причина вывода из оборота** (`action`): например, "PACKING" (фасовка/упаковка) или "EXPIRATION" (истечение срока годности). * **Дата операции** (`action_date`). * **Тип документа** (`document_type`): часто используется "OTHER". * **Номер и дата первичного документа** (`document_number`, `document_date`). * **Пользовательское наименование первичного документа** (`primary_document_custom_name`): например, "Акт списания товара". * В секции `products` мы указываем информацию о списываемых товарах. Здесь есть нюансы, зависящие от способа учета: * Для **поэкземплярного учета** (например, одежда, обувь, табак) указываются индивидуальные коды маркировки (`cis`). * Для **объемно-сортового учета (ОСУ)** (например, молочная продукция, упакованная вода для HoReCa) достаточно передать глобальный идентификатор товара (GTIN) и его количество (`gtin_quantity`). Теперь, когда мы понимаем общие принципы, перейдем к конкретному примеру реализации в 1С.

Подробный разбор процедуры программного списания в 1С

Мы рассмотрим процедуру ОтправитьЧерезАПИ(), которая реализует логику программного списания кодов маркировки.

Шаг 1: Авторизация и получение токена

Первым делом нам необходимо убедиться, что у нас есть действующий токен авторизации. Без него любое взаимодействие с API ЧЗ невозможно. Механизмы авторизации и запроса данных по маркам в 1С 7.7 имеют свои особенности реализации, которые мы сейчас увидим.


Если ПроверитьПолучитьТокен() = 0 Тогда	
    Если Вопрос("Отсутствует токен авторизации. Если это рабочее место имеет доступ к ЭЦП, нажмите ""Да"", иначе нажмите ""Нет"" и выполните проверку связи с ЦРПТ с рабочего места, имеющего доступ к ЭЦП.", 4, 15) = 6 Тогда
        СтрОшибка 	= "";
        ТекТокен 	= ПолучитьТокенЦРПТ(глПользователь.ЭЦП, ПрефиксВерсии, СтрОшибка);
    Иначе
        Записать();
        СтатусВозврата(0);
        Возврат;
    КонецЕсли;	   		
КонецЕсли;

Здесь мы видим, что сначала выполняется функция `ПроверитьПолучитьТокен()`. Если токен отсутствует, система предлагает получить его с помощью ЭЦП, используя функцию `ПолучитьТокенЦРПТ()`. Мы должны убедиться, что рабочее место имеет доступ к электронной подписи.

Шаг 2: Подготовка данных для JSON-запроса

Далее мы приступаем к формированию данных, которые будут отправлены в "Честный ЗНАК". Для этого мы будем использовать объекты 1С `СписокЗначений` и `ТаблицаЗначений`.


ВремКат	= КаталогВременныхФайлов(); 
СзЗаг 	= СоздатьОбъект("СписокЗначений");
СзТов	= СоздатьОбъект("СписокЗначений"); // Это похоже на заготовку, но далее используется ТзТов
ТзТов	= СоздатьОбъект("ТаблицаЗначений");

Мы создаем `СписокЗначений` под названием `СзЗаг` для хранения общих данных документа (заголовочная часть) и `ТаблицаЗначений` `ТзТов` для хранения информации о товарах.

Заполнение заголовочной части документа (`СзЗаг`)

Мы пошагово заполняем `СзЗаг` необходимыми полями:


СзЗаг.ДобавитьЗначение(СокрЛП(ВыделитьИНН(ЮрЛицо.ИНН)),	"inn");
Если ПричВыб = Перечисление.ПричВыбМарки.Развес Тогда
    СзЗаг.ДобавитьЗначение("PACKING", 		"action");
Иначе
    СзЗаг.ДобавитьЗначение("EXPIRATION",	"action");
КонецЕсли; 
СзЗаг.ДобавитьЗначение(ПреобразоватьДатуВСтрХМЛ(ТекущаяДата()),	"action_date");

СзЗаг.ДобавитьЗначение("OTHER", 			"document_type");

СзЗаг.ДобавитьЗначение(СокрЛП(Число(НомерДок)),			"document_number");
СзЗаг.ДобавитьЗначение(ПреобразоватьДатуВСтрХМЛ(ДатаДок),"document_date");
Если ПричВыб = Перечисление.ПричВыбМарки.Развес Тогда
    СзЗаг.ДобавитьЗначение("Акт фасовки товара", 		"primary_document_custom_name");
Иначе
    СзЗаг.ДобавитьЗначение("Акт списания товара", 		"primary_document_custom_name");	
КонецЕсли;

* `inn`: ИНН юридического лица. * `action`: Причина выбытия. Здесь мы видим примеры "PACKING" (фасовка) или "EXPIRATION" (истечение срока годности). * `action_date`: Дата операции. * `document_type`: Тип документа, в данном случае "OTHER".

Заполнение табличной части товаров (`ТзТов`)

Теперь мы перейдем к заполнению информации о самих товарах. Здесь особенно важно учитывать способ учета – поэкземплярный или объемно-сортовой.


ВыбратьСтроки(); // Предполагается, что это метод документа, который позволяет перебрать его строки
Если ПричВыб = Перечисление.ПричВыбМарки.Развес Тогда
    ТзТов.НоваяКолонка("cis");
    ТзТов.НоваяКолонка("product_cost");; 
Иначе 
    Если СпосУч = Перечисление.СпособУчета.ОСУ Тогда
        ТзТов.НоваяКолонка("gtin");
        ТзТов.НоваяКолонка("gtin_quantity");
    Иначе
        ТзТов.НоваяКолонка("cis");
    КонецЕсли;
КонецЕсли;
Пока ПолучитьСтроку() = 1 Цикл
    ТзТов.НоваяСтрока(); 
    Марк						= СокрЛП(Марка); 
    Если ПричВыб = Перечисление.ПричВыбМарки.Развес Тогда
        ТзТов.cis				= Марк;
    Иначе 
        Если СпосУч = Перечисление.СпособУчета.ОСУ Тогда
            // Извлечение GTIN из полного кода маркировки
            Если СтрДлина(Марк) > 14  Тогда
                ПозРазд 			= Найти(Марк, "21");
                НачМарки			= Лев(Марк, ПозРазд - 1);
                GTIN				= Прав(НачМарки, 14);				
            Иначе	
                GTIN				= Марк;
            КонецЕсли;
            ТзТов.gtin				= GTIN;
        Иначе
            ТзТов.cis				= ПолучитьКИЗ(СтрЗаменить(Марка, "<GS1>", Симв(29)));
        КонецЕсли;
    КонецЕсли;	
    Если ПричВыб = Перечисление.ПричВыбМарки.Развес Тогда
        ТзТов.product_cost		= ЦенаЕд * 100;	
    Иначе
        Если СпГрупп.ТекущаяСтрока() = 1 Тогда // Возможно, имеется в виду группировка по GTIN
            Если СпосУч = Перечисление.СпособУчета.ОСУ Тогда
                ТзТов.gtin_quantity	= Количество;
            КонецЕсли;
        КонецЕсли;
    КонецЕсли;
КонецЦикла;
СзЗаг.ДобавитьЗначение(ТзТов,	"products");

Шаг 3: Формирование JSON-строки и ее кодирование

После того как все данные собраны в `СзЗаг`, мы преобразуем их в строку JSON.


СтрДжейсон		  = Сервис.DecodeToUTF8(ЗначениеВJSON(СзЗаг));
Кодировка 			= "base64";
Стр 				= Кодировать(СтрДжейсон, Кодировка);
// Удаляем переносы строк, которые могут быть добавлены при кодировании
Стр 				= СтрЗаменить(Стр, Симв(10), "");
СтрДок64			= СтрЗаменить(Стр, Симв(13), "");

Шаг 4: Создание файла для подписи и формирование электронной подписи

Для отправки документа в ЧЗ требуется его электронная подпись.


Тхт					= СоздатьОбъект("Текст");
Тхт.ДобавитьСтроку(СтрДжейсон);
ИсхФайл				= ВремКат + "DocJSON.json";	
Тхт.Записать(ИсхФайл);
ПодпФайл			= ВремКат + "DocJSON.json.sig";	
Серт 				= ПолучитьСертификатПоОтпечатку(СокрЛП(глПользователь.ЭЦП.Отпечаток));
ПодписатьФайл(ИсхФайл, Серт, ПодпФайл, 1);
СтрЭЦП				= УбратьПереносыСтрок(ПодпФайл);

Шаг 5: Формирование финального JSON-запроса для API

Теперь мы собираем все части запроса в единую JSON-структуру.


сзJSONЗапрос		= СоздатьОбъект("СписокЗначений");
сзJSONЗапрос.ДобавитьЗначение("MANUAL", 		"document_format");
сзJSONЗапрос.ДобавитьЗначение(СтрДок64, 		"product_document");
сзJSONЗапрос.ДобавитьЗначение(СокрЛП(СтрЭЦП),	"signature");
Если Причвыб = Перечисление.ПричВыбМарки.Развес Тогда
    сзJSONЗапрос.ДобавитьЗначение("LK_RECEIPT", 		"type");
Иначе
    Если СпосУч = Перечисление.СпособУчета.Поэкземплярный Тогда
        сзJSONЗапрос.ДобавитьЗначение("LK_RECEIPT", 	"type");	
    Иначе	
        сзJSONЗапрос.ДобавитьЗначение("LK_GTIN_RECEIPT","type");
    КонецЕсли;
КонецЕсли;

Шаг 6: Отправка HTTP-запроса и обработка ответа

Финальный шаг — отправка запроса на сервер "Честного ЗНАКа".


сзЗаголовки 						= СоздатьОбъект("СписокЗначений");
сзЗаголовки.ДобавитьЗначение("application/json;charset=utf-8", "Content-Type");
сзЗаголовки.ДобавитьЗначение("no-cache", 			"cache-control");
сзЗаголовки.ДобавитьЗначение("application/json", 	"Accept");
СтрОшибка			= "";
Url					= АдресСервераМОТП + "/" + ПрефиксВерсии + "/lk/documents/create?pg=" + ВернутьГруппуТовара();

Ответ 				= глКарлик_ВыполнитьЗапрос("POST", Url, ТекТокен, сзЗаголовки, СтрОшибка, сзJSONЗапрос);

Поэкземплярный и объемно-сортовой учет: важные различия

Мы уже касались этих понятий, но давайте рассмотрим их подробнее: * **Поэкземплярный учет:** В запросе необходимо указывать индивидуальные коды (`cis`). Этот метод применяется для одежды, обуви, табака. * **Объемно-сортовой учет (ОСУ):** В запросе достаточно передать GTIN товара и его количество (`gtin_quantity`). Этот метод активно внедряется для молочной продукции и воды.

Важные моменты и рекомендации

* **Актуальность документации:** "Честный ЗНАК" постоянно обновляет свои API. * **Тестирование:** Всегда начинайте с тестирования на тестовом контуре. * **Компоненты для ЭЦП:** Для работы с УКЭП могут потребоваться дополнительные криптопровайдеры, такие как КриптоПро CSP.

Мы надеемся, что этот подробный разбор поможет вам успешно реализовать программное списание кодов маркировки в вашей системе 1С. Совместная работа с API "Честного ЗНАКа" открывает широкие возможности для автоматизации и оптимизации бизнес-процессов!

← На главную