При работе с маркированными товарами в 1С:Бухгалтерии 3.0 и интеграции с системой "Честный ЗНАК" нередко возникают специфические ошибки, одной из которых является сообщение "отсутствует полный код маркировки" при попытке печати чека. Давайте подробно разберем, почему это происходит и как устранить данную проблему, основываясь на практическом опыте и примерах кода.
Прежде всего, давайте выясним, что представляет собой полный код маркировки (КМ) и почему его корректная передача критически важна для успешной реализации маркированной продукции. Полный код маркировки — это уникальная последовательность символов, наносимая на каждую единицу товара, подлежащего обязательной маркировке. Он состоит из нескольких ключевых частей:
Ошибка "отсутствует полный код маркировки" чаще всего возникает, когда в учетную систему 1С передается или сохраняется код маркировки без этой самой криптографической части, то есть без "криптохвоста". В некоторых случаях, особенно при получении кодов из внешних источников (например, из PDF-файлов, от типографий или когда требуется загрузка списка товаров из Excel), может быть передан только код идентификации (КИ), состоящий из GTIN и серийного номера (около 31 символа). Однако для операций на кассе и проверки в "Честном ЗНАКе" требуется именно полный код маркировки, содержащий все компоненты.
Также важно отметить, что в коде маркировки присутствует специальный непечатаемый ASCII-символ-разделитель "GS" (29 символ таблицы ASCII), который может вызывать проблемы, если он не сохраняется или некорректно обрабатывается системой. Если этот символ отсутствует или введен с клавиатуры в текстовом формате, система не распознает код правильно.
Давайте проанализируем начальные попытки загрузки кодов маркировки, описанные в исходном сообщении, чтобы понять, какие аспекты могли привести к ошибке.
Изначально был предложен следующий код для заполнения данных о штрихкодах:
спрШУТ = Справочники.ШтрихкодыУпаковокТоваров;
...
//заполнение кодов ЧЗ
Шк64 = РезультатЗаполнения[Количество-1].Штрихкод;
Шк32 = ШтрихкодированиеИСКлиентСервер.ШтрихкодВФорматеGS1(ШтрихкодированиеОбщегоНазначенияИСКлиентСервер.Base64ВШтрихкод(Шк64));
//Шк28 = Лев(Шк32,28);
НовСтр.Штрихкод = Шк32;
НовСтр.КодАкцизнойМарки = Шк32;//Шк64;
ссСпрШУТ = СпрШУТ.ПолучитьПоЗначениюШтрихкода(Шк32);//(Шк28);
Если ссСпрШУТ = Неопределено Тогда
ДанныеШтрихкода = СпрШУТ.СтруктураСозданияШтрихкодаУпаковки();
ДанныеШтрихкода.ТипУпаковки = Перечисления.ТипыУпаковок.МаркированныйТовар;
ДанныеШтрихкода.Номенклатура = НовСтр.Номенклатура;
ДанныеШтрихкода.Количество = 1;
ДанныеШтрихкода.ТипШтрихкода = Перечисления.ТипыШтрихкодов.GS1_DataMatrix;
ДанныеШтрихкода.Штрихкод = Шк32;
//ДанныеШтрихкода.ХешСуммаНормализации = ИнтеграцияИС.ХешированиеДанныхSHA256(ШтрихкодыУпаковокКлиентСервер.ШтрихкодGS1(Шк32));
НовСтр.АкцизнаяМарка = СпрШУТ.СоздатьШтрихкодУпаковки(ДанныеШтрихкода);
сообщить("создан штрихкод"+Шк32+".");
Иначе
НовСтр.АкцизнаяМарка = ссСпрШУТ;
КонецЕсли;
В этом фрагменте мы видим попытку преобразования Base64-кода (Шк64) в формат GS1 DataMatrix (Шк32). Однако, ключевая проблема часто заключается в том, что Шк64, приходящий из внешней программы, может изначально не содержать криптохвоста или быть некорректно сформированным. Если Base64ВШтрихкод получает неполный код, то и ШтрихкодВФорматеGS1 не сможет создать корректный полный GS1-код.
Поле НовСтр.КодАкцизнойМарки, которое является полем табличной части документа "Розничная продажа", должно содержать полный Base64-код маркировки. Присвоение ему Шк32 (GS1-формата) вместо Шк64 (Base64) также могло быть причиной проблемы, так как система ожидает определенный формат в каждом поле.
В другой попытке автор использовал функцию ИнтерфейсИСМП.РазобратьИНормализоватьКодМаркировки:
//Шк32 = ШтрихкодированиеИСКлиентСервер.ШтрихкодВФорматеGS1(ШтрихкодированиеОбщегоНазначенияИСКлиентСервер.Base64ВШтрихкод(Шк64));
Шк32 = ИнтерфейсИСМП.РазобратьИНормализоватьКодМаркировки(ШтрихкодированиеОбщегоНазначенияИСКлиентСервер.Base64ВШтрихкод(Шк64));
Эта функция предназначена для правильного разбора и нормализации кода маркировки, но если исходный Base64-код (Шк64) был неполным, она также не сможет его восстановить. Кроме того, возникшая ошибка с "непечатаемым символом" при открытии списка СпрШУТ указывает на возможные проблемы с кодировкой или наличием некорректных символов в сохраненных штрихкодах.
Далее была предпринята попытка с изменением типов упаковки и штрихкода:
//заполнение кодов ЧЗ
Шк64 = РезультатЗаполнения[Количество-1].Штрихкод;
Шк32 = ШтрихкодированиеИСКлиентСервер.ШтрихкодВФорматеGS1(ШтрихкодированиеОбщегоНазначенияИСКлиентСервер.Base64ВШтрихкод(Шк64));
НовСтр.Штрихкод = Шк32;
НовСтр.КодАкцизнойМарки = Шк32;
ссСпрШУТ = СпрШУТ.ПолучитьПоЗначениюШтрихкода(Шк32);
Если ссСпрШУТ = Неопределено Тогда
ДанныеШтрихкода = СпрШУТ.СтруктураСозданияШтрихкодаУпаковки();
ДанныеШтрихкода.ТипУпаковки = Перечисления.ТипыУпаковок.МонотоварнаяУпаковка;
ДанныеШтрихкода.Номенклатура = НовСтр.Номенклатура;
ДанныеШтрихкода.Количество = 1;
ДанныеШтрихкода.ДатаУпаковки = Док.Дата;
ДанныеШтрихкода.ТипШтрихкода = Перечисления.ТипыШтрихкодов.GS1_128;
ДанныеШтрихкода.Штрихкод = Шк32;
НовСтр.АкцизнаяМарка = СпрШУТ.СоздатьШтрихкодУпаковки(ДанныеШтрихкода);
сообщить("создан штрихкод"+Шк32+".");
Иначе
НовСтр.АкцизнаяМарка = ссСпрШУТ;
КонецЕсли;
Здесь автор изменил ТипУпаковки на Перечисления.ТипыУпаковок.МонотоварнаяУпаковка и ТипШтрихкода на Перечисления.ТипыШтрихкодов.GS1_128. Хотя для некоторых типов маркировки это может быть корректно, для большинства маркированных товаров, использующих Data Matrix, правильным типом является Перечисления.ТипыШтрихкодов.GS1_DataMatrix, а тип упаковки чаще всего МаркированныйТовар. Несоответствие этих параметров типу фактически используемого кода также может приводить к ошибкам или игнорированию команды печати, как это произошло в данном случае.
Для правильной работы с маркировкой критически важно корректно создавать и хранить штрихкоды упаковок (в ряде случаев может потребоваться запрос остатков из системы «Честный знак» для выравнивания данных). Мы используем справочник Справочники.ШтрихкодыУпаковокТоваров.
Разберем основные принципы:
Шк32, который вы получаете после преобразования из Base64 (Шк64), действительно является полным кодом маркировки в формате GS1 DataMatrix, включая непечатаемый разделитель GS (ASCII 29) и криптохвост. Если Шк64 приходит из внешней системы, убедитесь, что она передает полный код маркировки.СпрШУТ.СтруктураСозданияШтрихкодаУпаковки().ДанныеШтрихкода.ТипУпаковки: Для большинства маркированных товаров это Перечисления.ТипыУпаковок.МаркированныйТовар.ДанныеШтрихкода.Номенклатура: Ссылка на элемент номенклатуры, к которой относится марка.ДанныеШтрихкода.Количество: Обычно 1 для единичного маркированного товара.ДанныеШтрихкода.ТипШтрихкода: Для Data Matrix это Перечисления.ТипыШтрихкодов.GS1_DataMatrix.ДанныеШтрихкода.Штрихкод: Сюда записываем Шк32 – полный код маркировки в формате GS1 DataMatrix (с AI, скобками и разделителями).НовСтр.АкцизнаяМарка в табличной части документа РозничнаяПродажа должно ссылаться на созданный или найденный элемент справочника Справочники.ШтрихкодыУпаковокТоваров. Поле НовСтр.КодАкцизнойМарки в табличной части документа РозничнаяПродажа должно содержать Base64-код (Шк64), так как именно он используется для отправки в Честный ЗНАК.Для корректной работы разрешительного режима, который требует онлайн-проверки кода маркировки в системе "Честный ЗНАК" перед продажей, необходимо не только создать запись в справочнике ШтрихкодыУпаковокТоваров, но и заполнить регистр сведений РегистрыСведений.ПулКодовМаркировкиСУЗ. Этот регистр хранит подробные данные о статусе кодов маркировки и используется для взаимодействия с ГИС МТ.
Давайте рассмотрим расширенный фрагмент кода, который включает заполнение этого регистра:
//заполнение кодов ЧЗ
Шк64 = РезультатЗаполнения[Количество-1].Штрихкод;
Шк32 = ШтрихкодированиеИСКлиентСервер.ШтрихкодВФорматеGS1(ШтрихкодированиеОбщегоНазначенияИСКлиентСервер.Base64ВШтрихкод(Шк64));
//Шк32 = ИнтерфейсИСМП.РазобратьИНормализоватьКодМаркировки(ШтрихкодированиеОбщегоНазначенияИСКлиентСервер.Base64ВШтрихкод(Шк64));// может так...
НовСтр.Штрихкод = Шк32;
НовСтр.КодАкцизнойМарки = Шк64; // Важно: здесь должен быть Шк64 (Base64)
ссСпрШУТ = СпрШУТ.ПолучитьПоЗначениюШтрихкода(Шк32);
Если ссСпрШУТ = Неопределено Тогда
ДанныеШтрихкода = СпрШУТ.СтруктураСозданияШтрихкодаУпаковки();
ДанныеШтрихкода.ТипУпаковки = Перечисления.ТипыУпаковок.МаркированныйТовар;
ДанныеШтрихкода.Номенклатура = НовСтр.Номенклатура;
ДанныеШтрихкода.Количество = 1;
ДанныеШтрихкода.ДатаУпаковки = Док.Дата;
ДанныеШтрихкода.ТипШтрихкода = Перечисления.ТипыШтрихкодов.GS1_DataMatrix;
ДанныеШтрихкода.Штрихкод = Шк32;
НовСтр.АкцизнаяМарка = СпрШУТ.СоздатьШтрихкодУпаковки(ДанныеШтрихкода);
сообщить("создан штрихкод"+Шк32+".");
//пул СУЗ
ПараметрыСканирования = ШтрихкодированиеОбщегоНазначенияИСКлиентСервер.БазовыеПараметрыСканирования();
ШтрихкодированиеОбщегоНазначенияИСКлиентСервер.ЗаполнитьБазовыеПараметрыСканирования(ПараметрыСканирования, Док);
ШтрихкодированиеОбщегоНазначенияИСМПКлиентСервер.ЗаполнитьПараметрыСканирования(Док,Перечисления.ВидыПродукцииИС.ПустаяСсылка(),ПараметрыСканирования,Неопределено);
ДанныеШтрихкодаПолные = ШтрихкодированиеОбщегоНазначенияИС.ИнициализироватьДанныеШтрихкода(ПараметрыСканирования);
ДанныеШтрихкодаПолные.Штрихкод = Шк32;
ДанныеШтрихкодаПолные.ШтрихкодBase64 = Шк64;
ДанныеШтрихкодаПолные.МаркируемаяПродукция = Истина;
ДанныеШтрихкодаПолные.ТипУпаковки = Перечисления.ТипыУпаковок.МаркированныйТовар;
ДанныеШтрихкодаПолные.ТипШтрихкода = Перечисления.ТипыШтрихкодов.GS1_DataMatrix;
ДанныеШтрихкодаПолные.Номенклатура = НовСтр.Номенклатура;
ДанныеШтрихкодаПолные.Вставить("ЕстьВПулеКодовМаркировки", Ложь); //иначе ошибка...
ДанныеШтрихкодаПолные.Вставить("ПолныйКодМаркировки", ""); //иначе ошибка...
РегистрыСведений.ПулКодовМаркировкиСУЗ.ЗаписатьДанныеКодаМаркировки(ДанныеШтрихкодаПолные,ПараметрыСканирования);
Иначе
НовСтр.АкцизнаяМарка = ссСпрШУТ;
КонецЕсли;
В этом коде мы видим, как после создания записи в справочнике ШтрихкодыУпаковокТоваров, система приступает к заполнению данных для регистра ПулКодовМаркировкиСУЗ. Разберем ключевые моменты:
ШтрихкодированиеОбщегоНазначенияИСКлиентСервер.БазовыеПараметрыСканирования() и ЗаполнитьБазовыеПараметрыСканирования() для подготовки контекста, в котором будет обрабатываться код маркировки. Эти параметры содержат информацию о документе, организации, виде продукции и т.д.ДанныеШтрихкодаПолные с помощью ШтрихкодированиеОбщегоНазначенияИС.ИнициализироватьДанныеШтрихкода().ДанныеШтрихкодаПолные:
ДанныеШтрихкодаПолные.Штрихкод: Должен содержать GS1-код (Шк32).ДанныеШтрихкодаПолные.ШтрихкодBase64: Должен содержать Base64-код (Шк64). Критически важно, чтобы здесь был именно полный Base64-код, включая криптохвост. Если ваш внешний источник предоставляет только укороченный Base64, это и будет корневой причиной проблемы.ДанныеШтрихкодаПолные.МаркируемаяПродукция: Устанавливается в Истина.ДанныеШтрихкодаПолные.ТипУпаковки и ДанныеШтрихкодаПолные.ТипШтрихкода: Соответствуют ранее использованным для справочника.ДанныеШтрихкодаПолные.Номенклатура: Ссылка на номенклатуру.ДанныеШтрихкодаПолные.Вставить("ЕстьВПулеКодовМаркировки", Ложь) и ДанныеШтрихкодаПолные.Вставить("ПолныйКодМаркировки", ""): Эти строки были добавлены автором для обхода ошибок, что указывает на то, что типовые механизмы ожидали эти поля, но они могли отсутствовать или быть некорректно заполнены. Важно убедиться, что эти поля корректно обрабатываются в типовой конфигурации.РегистрыСведений.ПулКодовМаркировкиСУЗ.ЗаписатьДанныеКодаМаркировки().После решения проблемы с "отсутствует полный код маркировки" может возникнуть новая ошибка: "Поле объекта не обнаружено (ИдентификаторЗапросаГИСМТ)". Эта ошибка напрямую связана с работой разрешительного режима и взаимодействием с Государственной информационной системой маркировки товаров (ГИС МТ).
Разрешительный режим — это механизм, который в режиме реального времени проверяет легальность каждой торговой операции с маркированными товарами. При сканировании кода Data Matrix на кассе, она отправляет запрос в ГИС МТ. Система проверяет статус товара, его принадлежность продавцу, сроки годности и другие параметры. Только после получения электронного "одобрения" от ГИС МТ продажа разрешается. Если запрос не может быть сформирован или отправлен корректно, система выдает ошибку. Для отладки таких процессов часто используется клиент API ГИС МТ, позволяющий проверять данные на стороне сервера.
Ошибка "Поле объекта не обнаружено (ИдентификаторЗапросаГИСМТ)" означает, что в какой-то момент формирования запроса к ГИС МТ или обработки его результата, система не смогла найти поле ИдентификаторЗапросаГИСМТ. Это может произойти по нескольким причинам:
ПулКодовМаркировкиСУЗ не попадает полный и корректный код маркировки, система не сможет сформировать валидный запрос к ГИС МТ.Как часто бывает в мире 1С и интеграции, комплексные проблемы решаются путем обновления всех компонентов системы. В данном случае, ключевым моментом, который позволил преодолеть ошибку "отсутствует полный код маркировки" и успешно передавать данные о выбытии в "Честный ЗНАК", стало следующее:
После выполнения этих шагов, данные о выбытии начали успешно передаваться в "Честный ЗНАК", а статус разрешительного режима стал "Пройден", что указывает на корректную работу всей цепочки взаимодействия.
Однако, как часто бывает, решение одной проблемы может выявить другую. После успешной передачи данных, появилась новая "головная боль": касса начала печатать только чеки не больше двух позиций с маркировкой, а при попытке печати более длинных чеков происходил сброс связи.
Эта проблема, скорее всего, связана с:
Для диагностики этой проблемы рекомендуется:
Для стабильной и безошибочной работы с маркированными товарами в 1С и "Честном ЗНАКе" мы рекомендуем следовать следующим правилам:
Следуя этим рекомендациям, мы сможем минимизировать количество ошибок и обеспечить бесперебойную работу с маркированными товарами в вашей системе 1С.