Маркировка лекарств - как передать код маркировки при продаже через ККТ Штрих-М

Публикация № 1192569

Разработка - Практика программирования

ККТ Маркировка пример кода для

Пример программного кода для вывода чеков на ККМ Штрих-М с передачей информации о маркированных товарах (лекарства).

Многие знают, что при продаже маркированных товаров необходимо передавать информацию о коде маркировки с помощью тега 1162. Про это достаточно много информации.

Для Штрих-М запрограммировать это не составляет большого труда. После операции FNOperation() необходимо добавить несколько строк.

ЗагрузитьВнешнююКомпоненту ("DrvFR.dll");
голеОбъектККМ = СоздатьОбъект("AddIn.DrvFR");
...

голеОбъектККМ.FNOperation();

голеОбъектККМ.MarkingType  = MarkingType; //3 - лекарства
голеОбъектККМ.GTIN         = GTIN;        //14 символов
голеОбъектККМ.SerialNumber = SerialNumber;//13 символов
голеОбъектККМ.FNSendItemCodeData();

Код маркировки включает в себя избыточные данные. Из него необходимо выделить SGTIN длиной 27 символов, который в свою очередь делится на 2 части: первые 14 символов GTIN, остальные 13 символов это серийный номер упаковки (длина серийного номера упаковки указана для группы Лекарства).

Мой вариант функции разбора штрих-кода маркировки:

//******************************************************************************
// глЭтоКодМаркировки(Данные)
//
// Параметры: 
//  Данные
//  SGTIN - выходной параметр для передачи вырезанного из штрихкода SGTIN
//  КодТН_ВЭД - выходной параметр
//  НомерСерии - выходной параметр
//  ДатаИстеченияСрокаГодности - выходной параметр
//
// Возвращаемое значение:
//  1 да, 0 нет
//
// Описание:
//
// Примечание:
//  В настройках сканера желательно включить передачу разделителя с кодом 29
//
Функция глЭтоКодМаркировки(Данные,SGTIN,КодТН_ВЭД="",НомерСерии="",ДатаИстеченияСрокаГодности="") Экспорт
	Перем лДанные,СчЦ,ЧастьДанных,GTIN,ИндивидуальныйСерийныйНомер;
	лДанные = СокрЛП(Данные);
	Если СтрДлина(лДанные) >= 27 Тогда
		лДанные = СтрЗаменить(лДанные,Симв(29),РазделительСтрок);
		Если СтрДлина(лДанные) = 27 Тогда
			SGTIN = Данные;
			Возврат 1;
		КонецЕсли;
		Если Лев(лДанные,2) = "01" Тогда
			GTIN = Сред(лДанные,3,14);
			лДанные = Сред(лДанные,17);
			ИндивидуальныйСерийныйНомер = "";//префикс 21  длина 13
			КодТН_ВЭД                   = "";//префикс 240 длина 4
			НомерСерии                  = "";//префикс 10 длина переменная, принимает что от 4 до 10
			ДатаИстеченияСрокаГодности  = "";//префикс 17 длина 6 
			Для СчЦ = 1 По СтрКоличествоСтрок(лДанные) Цикл
				ЧастьДанных = СтрПолучитьСтроку(лДанные,СчЦ);
				
				флПродолжитьПоиск = 1;
				Пока флПродолжитьПоиск = 1 Цикл
					Если СтрДлина(ЧастьДанных) <= 2 Тогда
						Прервать;
					КонецЕсли;
					Если Лев(Прав(ЧастьДанных,15),2) = "21" Тогда
						ИндивидуальныйСерийныйНомер = Прав(ЧастьДанных,13);
						ЧастьДанных = Лев(ЧастьДанных,СтрДлина(ЧастьДанных)-15);
					ИначеЕсли Лев(ЧастьДанных,2) = "21" Тогда
						ИндивидуальныйСерийныйНомер = Сред(ЧастьДанных,3,13);
						ЧастьДанных = Сред(ЧастьДанных,16);
					ИначеЕсли Лев(ЧастьДанных,2) = "17" Тогда
						ДатаИстеченияСрокаГодности = Сред(ЧастьДанных,3,6);
						ЧастьДанных = Сред(ЧастьДанных,9);
					ИначеЕсли Лев(ЧастьДанных,3) = "240" Тогда
						КодТН_ВЭД = Сред(ЧастьДанных,4,4);
						ЧастьДанных = Сред(ЧастьДанных,8);
					ИначеЕсли Лев(Прав(ЧастьДанных,7),3) = "240" Тогда
						КодТН_ВЭД = Прав(ЧастьДанных,4);
						ЧастьДанных = Лев(ЧастьДанных,СтрДлина(ЧастьДанных)-7);
					ИначеЕсли Лев(ЧастьДанных,2) = "10" Тогда
						Если (СтрДлина(ЧастьДанных) >= 6) И (СтрДлина(ЧастьДанных) <= 12) Тогда //допустим, что длина серии от 4 до 10
						    НомерСерии = Сред(ЧастьДанных,2);
							ЧастьДанных = "";
						Иначе
							флПродолжитьПоиск = 0;
						КонецЕсли;
					ИначеЕсли Лев(ЧастьДанных,2) = "91" Тогда
						ПроверочныйКлюч = Сред(ЧастьДанных,3,4);
						ЧастьДанных = Сред(ЧастьДанных,7);
					ИначеЕсли Лев(ЧастьДанных,2) = "92" Тогда
						ПроверочныйКод = Сред(ЧастьДанных,3,44);
						ЧастьДанных = Сред(ЧастьДанных,47);
					Иначе
						флПродолжитьПоиск = 0;
					КонецЕсли;
				КонецЦикла;
			
			КонецЦикла;
			Если ПустоеЗначение(ИндивидуальныйСерийныйНомер) = 0 Тогда
				SGTIN = GTIN + ИндивидуальныйСерийныйНомер;
				Если ПустоеЗначение(SGTIN) = 0 Тогда
					Если СтрДлина(SGTIN) = 27 Тогда
						Возврат 1;
					КонецЕсли;
				КонецЕсли;
			КонецЕсли;
		КонецЕсли;
		Если ПустоеЗначение(SGTIN) = 0 Тогда
			Если СтрДлина(SGTIN) = 27 Тогда
				Возврат 1;
			КонецЕсли;
		КонецЕсли;
	КонецЕсли;
	Возврат 0;
	
КонецФункции // глЭтоКодМаркировки()

Но при продаже лекарственных препаратов всё сложнее.

Когда я для теста сделал первый чек с кодом маркировки, то долго ждал когда же статус упаковки сменится с "in_circulation" (в обороте) на "in_sale" (продан в розницу), но этого так и не произошло.

Вот что мне ответил представитель ОФД:

Так же прошу отметить,что 54-ФЗ возлагает обязанности на оператора фискальных данных только в частности доставки кодов маркировки в составе кассового чека, а не контролировать его прием на стороне ЦРПТ.

Т.е. ОФД нет никакого дела, что именно ты передаёшь, правильно или нет.

Вот какой ответ из Честного Знака привёл один из разработчиков:

Отчёт о выбытии препарата при проведении его через ККТ не поступил в ИС "Маркировку" по причине того, что в отправляемом документе:
- отсутствуют теги 1085 и 1086, которые содержат информацию о месте деятельности, с которого происходит вывод ЛП из оборота;
- отсутствует тег 1191, который указывает именно, что производится именно продажа лекарственного препарата.

Читаем документацию и дополняем обработку.

Тег кассового чека 1084 является структурой и содержит следующие теги:
Код Наименование Тега Формат Размер
1085 наименование дополнительного реквизита пользователя Строка CP-866 64
1086 значение дополнительного реквизита пользователя Строка CP-866 256

 

Ниже приведены рекомендации по записи в структуру тега 1084 (дополнительный реквизит пользователя) данных о выбытии лекарственных препаратов.

В теге 1085 необходимо передавать следующие реквизиты:

1. Префикс «mdlp» как признак того, что тег 1086 содержит специфичную для передачи в МДЛП информацию;

2. Опционально 7 символов из диапазона «0..9», указывающих на тип документа, данные которого передаются в теге 1086, в соответствии с ОКУД.
a. Отсутствие этих символов указывает на то, что в чеке передаются данные розничной реализации ЛП по рецепту с частичным дотированием, которые преобразуются в 511 схему данных МДЛП, либо в чеке передаются данные розничной реализации ЛП по рецепту без льготы или отпускаемых без рецепта.
b. Значение «3108805» указывает на то, что в теге 1086 передаются данные льготного рецепта со 100% дотированием (тег 1086 должен содержать реквизит с префиксом «ps»), которые преобразуются в 521 схему данных МДЛП.
c. Другие значения тега 1085 не допускаются.
Все передаваемые в теге 1086 реквизиты необходимо разделять символами-разделителями «&»; каждому реквизиту сопоставить уникальный префикс для упрощения машинной обработки данных:
dn = <номер документа, учитывающего отраслевую специфику>, doc_num, не более 200 символов
dd = <дата документа, учитывающего отраслевую специфику> в формате ГГММДД, doc_date
ps = <номер серии льготного рецепта>, prescription_series

sid = <идентификатор места деятельности субъекта обращения в ИС МДЛП>, subject_id

Для самого простого случая продажи без рецепта в начало добавляем

голеОбъектККМ.CheckType = 0;
голеОбъектККМ.OpenCheck();

голеОбъектККМ.TagNumber = 1084;
голеОбъектККМ.FNBeginSTLVTag();
my_TagID = голеОбъектККМ.TagID;

голеОбъектККМ.TagID = my_TagID;
голеОбъектККМ.TagNumber = 1085;
голеОбъектККМ.TagType = 7;
голеОбъектККМ.TagValueStr = "mdlp";
голеОбъектККМ.FNAddTag();

голеОбъектККМ.TagID = my_TagID;
голеОбъектККМ.TagNumber = 1086;
голеОбъектККМ.TagType = 7;
голеОбъектККМ.TagValueStr = "sid"+subject_id+"&";
голеОбъектККМ.FNAddTag();

голеОбъектККМ.FNSendSTLVTag();

Где subject_id это идентификатор места деятельности.

В теге 1191 передаются следующие реквизиты, порядок их записи описан ниже:

sp = <часть потребительской (маркированной) упаковки, подлежащая выводу из оборота>, sold_part
ss = <сумма субсидии>, subsidy_sum (сумма, компенсируемая из федерального или регионального бюджета, при расчете за данный предмет расчета по льготному рецепту). Используется для заполнения параметра МДЛП «discount».
Идентификатор субъекта обращения (sid) - 14 разрядныйM4; номер (строка длиной 14 байт в CP-866, допустимые символы [«0»-«9»]). Завершающий символ при записи строки данных должен быть «&».
При определении максимальной суммарной длины реквизитов dn и ps необходимо учитывать ограничения длины тега 1086, установленные ФФД (256 байт в версии 1.05). Для включения в реквизиты с префиксом dn или ps символа «&» в передаваемых данных должна содержаться подстрока «&&», которая при обработке и передаче в МДЛП не интерпретируется как разделитель или завершающий символ, а заменяется на символ «&».
Реквизит sp включается в тег 1191 сразу после префикса mdlp без указания в качестве префикса названия реквизита в следующем виде: указывается общее количество отпущенных первичных упаковок (целое число в виде строки, лидирующие нули запрещены) и, далее, количество первичных упаковок в маркированной упаковке (целое число в виде строки, лидирующие нули запрещены), разделенные символом «/» с завершающим символом «&», т.е. при отпуске 4 блистеров из 12 указывается строка «4/12&». Если после префикса «mdlp» указание дробной части отсутствует, упаковка считается выведенной из оборота полностью.

Примеры допустимых значений тега 1191: «mdlp», «mdlp2/12&».
Реквизит ss для льготных ЛП содержит сумму, возмещаемую из регионального или федерального бюджета. В реквизитах чека данные суммы должны указываться суммарно по всем позициям чека , как «сумма встречным предоставлением». Передается только для льготных рецептов с частичным дотированием, для рецептов со 100% льготой этот реквизит передавать в составе ФД не нужно. Реквизит ss всегда должен следовать после первого разделителя «&», название реквизита в качестве префикса не указывается. Если тег 1191 не содержит информации о доле отпуска (отпуск полной упаковки), после префикса «mdlp» перед реквизитом ss добавляется разделитель «&».
Реквизит ss всегда завершается символом «&». Значение реквизита ss – строка, в которой допустимы только символы [0..9], которая интерпретируется как десятичное число с фиксированной точностью 2 знака после десятичного разделителя целой и дробной части.

Примеры допустимых значений тега 1191 при субсидии 123,00 руб.: «mdlp&12300&», «mdlp2/12&12300&».

Добавляем к передаче кода маркировки передачу тега 1191:

Если (ПустоеЗначение(MarkingType) = 0) И (ПустоеЗначение(GTIN) = 0) И (ПустоеЗначение(SerialNumber) = 0) Тогда
	голеОбъектККМ.MarkingType  = MarkingType; //3 - лекарства
	голеОбъектККМ.GTIN         = GTIN;        //14 символов
	голеОбъектККМ.SerialNumber = SerialNumber;//13 символов
	голеОбъектККМ.FNSendItemCodeData();
	
	Если СписокТоваров.Количество <> СписокТоваров.ОтоброжениеКоличества Тогда
		голеОбъектККМ.TagNumber      = 1191;
		голеОбъектККМ.TagType        = 7;
		голеОбъектККМ.TagValueStr    = "mdlp"+Окр(СписокТоваров.ОтоброжениеКоличества,0)+"/"+Цел(СписокТоваров.ОтоброжениеКоличества/СписокТоваров.Количество)+"&";//при продаже 1 блистера из 3 должно быть mdlp1/3
		голеОбъектККМ.FNSendTagOperation();
	Иначе
		голеОбъектККМ.TagNumber      = 1191;
		голеОбъектККМ.TagType        = 7;
		голеОбъектККМ.TagValueStr    = "mdlp";
		голеОбъектККМ.FNSendTagOperation();
	КонецЕсли;
КонецЕсли;

Если всё прошло удачно, то в личном кабинете Честного Знака в исходящих документах появится документ с типом 10511 - Розничная продажа с использованием ККТ, тип загрузки в систему - ОФД.

По поводу прошивки и драйверов

Версия драйвера использовалась 4.14.0.772

Прошивка "Сборка ПО: 5190" от 29.04.2019.

Никаких лицензий для ККТ не покупалось, было сделано только обновление прошивки через тест драйвера. Почему я хотел бы заострить на этом внимание - нас по телефону на протяжении нескольких недель терроризировал один продажник, уверяя что если мы у него не купим лицензии на все наши кассы, то маркировка у нас работать не будет.

 

Ссылки на документацию:

Формат записи данных о выбытии ЛП в ФФД (pdf, 537.54 КБ)

Руководство программиста "ШТРИХ-М: Драйвер ККТ" (ZIP, 6.73 MB)

Специальные предложения

Комментарии
Избранное Подписка Сортировка: Древо развёрнутое
Свернуть все
1. KUAvanesov 11.02.20 07:36 Сейчас в теме
А как же отправка в компоненту xml? На вашей прошивке это можно уже делать.
2. victuan 3550 11.02.20 09:03 Сейчас в теме
(1) Отправка через XML не требуется!
В этом и прелесть родного (нативного) драйвера ФР, что он работает с меньшими проблемами и раньше обновляется, чем версия драйвера "по стандарту 1С".

(0)
голеОбъектККМ.MarkingType = MarkingType; //3 - лекарства

Интересно, сработает без ошибок если передать MarkingType = 17485.
Дело в том, что с 1 марта нужно уже использовать общий префикс для всех групп товара 44 4D(16) = 17485(10) согласно обновленного "Протокол информационного обмена (ОФД)".

Техподдержка Штрих-М меня уверила, что прошивка и драйвер поддержат оба значения. Но хочется лишний раз убедится на практике, что это работает.
3. Rustig 1419 11.02.20 09:13 Сейчас в теме
(0) предыстория какая у вас? обычно кассовое ПО (учетная программа 1С) или ККМ обновляется для целей маркировки, а вы решили сами программировать передачу сведений в ККМ.
Как будто у вас не обновляемая 1с-ка... Что по ситуации у вас? Какая конфа и какой ККМ?
4. victuan 3550 11.02.20 09:59 Сейчас в теме
(3) Верно, имеются не обновляемые конфигурации. Это 1С 7.7. В них не предусмотрен учет маркировки и не будет в типовых релизах.
Оставьте свое сообщение

См. также

Использование классов .Net в 1С для новичков Промо

Практика программирования Разработка внешних компонент Универсальные функции v7.7 v8 Бесплатно (free)

Руководство для новичков. Написав статью http://infostart.ru/public/238584/, я понял, что многие не понимают того, что написано. Поэтому в этой статье постараюсь более подробно остановиться на азах и без кода на вражеском языке (C#)

27.01.2016    71161    0    Serginio    108    

.Net в 1С. Асинхронные HTTP запросы, отправка Post нескольких файлов multipart/form-data, сжатие трафика с использованием gzip, deflate, удобный парсинг сайтов и т.д.

Разработка внешних компонент Практика программирования WEB v7.7 v8 Бесплатно (free)

Очень часто нужно при работе с HTTP сервисами или сайтами использовать Асинхронные HTTP запросы, отправку на сервер нескольких файлов, использование сжатия трафика. Эта статья про то, как этого легко добиться.

09.03.2016    30230    0    Serginio    22    

Экспорт нескольких MXL таблиц в один XLS файл, на отдельные листы. Простой алгоритм

Загрузка и выгрузка в Excel Практика программирования v7.7 v8 Бесплатно (free)

Статья посвящена распространённому вопросу - как сохранить несколько таблиц (отчетов) в формате MXL, с которым работает 1С, на отдельные листы одного Excel файла. Освещается простой алгоритм решения проблемы штатными средствами, без использования внешних модулей и библиотек (не относящихся к 1С и Excel).

23.11.2015    16752    0    etmarket    14    

Универсальный способ сравнения таблиц

Практика программирования v7.7 v8 Бесплатно (free)

На эту тему уже есть статьи, но этот способ нигде не описан. Хотя я его использую с тех пор, как занимаюсь программированием. Его преимущество в простоте и универсальности: можно применять на 1С, SQL, а также в любом другом языке программирования.

05.07.2015    18416    0    json    1    

.Net в 1С. На примере использования HTTPClient, AngleSharp. Удобный парсинг сайтов с помощью библиотеки AngleSharp, в том числе с авторизацией аля JQuery с использованием CSS селекторов. Динамическая компиляция Промо

Практика программирования WEB v7.7 v8 Бесплатно (free)

Часто приходится парсить сайты, в том числе с авторизацией, перескакивая со страницы на страницу по ссылкам. Тот, кто занимался вэб программированием, знает, как удобно использовать JQuery и CSS селекторы. На .Net написана очень удобная библиотека AngleSharp. Я покажу, как с её помощью можно значительно облегчить себе труд.

10.03.2016    53757    0    Serginio    33    

Хитрости сохранения табличного документа в Excel для дальнейшей работы с ним

Загрузка и выгрузка в Excel Практика программирования v7.7 v8 1cv8.cf 1cv7.md Бесплатно (free)

Все пользователи 1С всех версий (начиная с 7-й) сталкиваются с проблемой нормальной работы с данными, сохраненными в Excel файл. Есть некоторые хитрости, которые позволяют облегчить работу с сохраненными данными из 1С в формат Excel.

16.01.2015    84042    0    shmellevich    37    

Отправка сообщения посредством почтового клиента Lotus Notes

Практика программирования v7.7 v8 1cv8.cf 1cv7.md Бесплатно (free)

Отправка сообщения посредством почтового клиента Lotus Notes из 1С 7,7 и 1с 8

21.08.2014    14132    0    iolko    8    

Полезные функции. Склонение (должность и фамилия подписантов). Любой язык

Практика программирования v7.7 v8 Бесплатно (free)

Уехал директор в командировку, отпуск... , оставил доверенность на хозяйственные операции на другого сотрудника. Все договора и другие документы в обмороке - "подписант" теперь другой, по тексту тоже много правок... Пересмотрел много публикаций, вариантов много, не приглянулось. Сделал свой "Баян" . У меня всего-то крутится пять фигурантов ... Нет простого, наглядного и всепогодного варианта без языкового барьера. Всем процессом управляет пользователь.

03.03.2014    17379    0    kompas-dm    5    

Конвертация данных 2.1 (2.1.3.1) 1С 7.7 - 1С 8.Х передача параметра ПКО

Практика программирования Перенос данных из 1С7.7 в 1C8.X v7.7 v8 КД Бесплатно (free)

Передача параметров по умолчанию доступна только для баз 1С 8.х -1С 8.х. Показан пример, как передать параметры из 1С 7.7 - 1С 8.х

10.12.2012    24617    0    serg_gres    6    

[Генератор внешних событий] Внешняя компонента для 1С

Практика программирования Разработка внешних компонент v7.7 v8 1cv8.cf 1cv7.md Бесплатно (free)

Компонента генерирует внешние события с заданным интервалом и с заданными значениями.

06.03.2009    36647    0    Душелов    81    

[Мониторинг изменения файлов] - ActiveX-компонента для 1С 8.х + ВК для 7.7

Практика программирования Разработка внешних компонент v7.7 v8 1cv8.cf 1cv7.md Бесплатно (free)

Компонента следит за изменениями файлов в заданных каталогах, без таймеров и опросов файловой системы. Использует события Windows.

05.03.2009    23143    0    Душелов    53    

[Проверка правописания] - ActiveX-компонента для 1С

Практика программирования Разработка внешних компонент v7.7 v8 1cv8.cf 1cv7.md Бесплатно (free)

Компонента проверяет правописание текста. Основана на технологии OpenOffice MySpell. Не требует установленного офиса. В комплекте словари для 5 языков, включая русский (с "ё").

09.02.2009    27408    0    Душелов    66    

Создание документа Word 2007

Загрузка и выгрузка в Excel Практика программирования v7.7 v8 1cv8.cf 1cv7.md Бесплатно (free)

Создание документа Word 2007 без установленного Word'а, без внешних компонент, исключительно средствами 1С

09.08.2008    37866    0    Душелов    43    

Объединение справочников и перенос остатков номенклатуры из нескольких баз 1С 7.7 в 1 базу УПП 8.1

Перенос данных из 1С7.7 в 1C8.X Практика программирования v7.7 v8 1cv7.md УПП1 Россия Бесплатно (free)

Объединение справочников и перенос остатков номенклатуры из нескольких баз 1С 7.7 в 1 базу УПП 8.1

11.12.2007    12074    0    danser    3