Как правильно прочитать и разобрать код маркировки DataMatrix на упаковке лекарственных средств?

Программист 1С v8.3 (Управляемые формы) Управленческий учет Торговля и дистрибуция
← На главную

В процессе автоматизации аптечной деятельности или складского учета лекарственных средств (ЛС) специалисты часто сталкиваются с проблемой: при сканировании кода с упаковки в строке не оказывается явных данных о номере партии или сроке годности. Давайте разберем, как устроена маркировка лекарств, почему коды могут различаться по длине и как правильно реализовать парсинг этой строки в 1С.

DataMatrix или QR-код: в чем разница?

Прежде всего, проанализируем терминологию. То, что часто называют «QR-кодом» на упаковках таблеток, на самом деле является кодом DataMatrix. В отличие от обычного QR-кода, DataMatrix позволяет упаковать большой объем информации на очень маленькой площади, что критично для ампул и небольших пачек. В фармацевтике используется стандарт GS1 DataMatrix, который строго регламентирует структуру данных внутри кода.

Структура кода GS1 и идентификаторы применения (AI)

Данные в коде маркировки не идут случайным потоком. Они разделены на блоки, каждый из которых начинается с двухзначного (иногда трех- или четырехзначного) префикса — идентификатора применения (Application Identifier, AI). Рассмотрим основные префиксы, которые встречаются в маркировке ЛС:

  1. 01 — GTIN (Global Trade Item Number). Это 14-значный код товара. Он определяет саму номенклатурную позицию (например, «Анальгин 500 мг №10»).
  2. 21 — Серийный номер (Serial Number). Это уникальный номер конкретной коробочки. Именно он делает каждую упаковку уникальной.
  3. 17 — Срок годности. Состоит из 6 цифр в формате ГГММДД.
  4. 10 — Номер партии (Batch/Lot number). Строка переменной длины.
  5. 91 и 92 — Код проверки и криптохвост. Используются для проверки подлинности в системах типа «Честный знак» (в РФ) или аналогичных системах ЕАЭС.

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

Проанализируем ситуацию, описанную в теме: сканер выдает строку 010460367900592321DLO0000119895. Разберем ее по частям:

Как мы видим, в этом коде физически отсутствуют идентификаторы 10 (партия) и 17 (срок годности). Это так называемый «короткий код» или SGTIN. В этом случае производитель зашифровал в DataMatrix только идентификатор товара и индивидуальный номер пачки.

Выясним причину, почему на сайте информационной системы (ЭБД ЛС или МДЛП) данные о партии при этом отображаются. Все дело в облачной базе данных. Когда вы сканируете SGTIN, ваша учетная программа (1С) должна отправить запрос в государственную информационную систему. Система находит у себя запись: «Упаковка с серийным номером DLO0000119895 принадлежит партии 280425 со сроком годности до 2027-03-31». Таким образом, информация «подтягивается» из внешнего реестра, а не из самого кода.

Символ-разделитель GS и настройки сканера

Одной из самых частых технических проблем является игнорирование символа Group Separator (GS), который соответствует коду ASCII 29. Он используется в GS1 DataMatrix для отделения полей переменной длины (например, серийного номера) от следующих за ними данных.

Если серийный номер имеет переменную длину, а за ним идет номер партии, без разделителя GS программа не поймет, где заканчивается один блок и начинается другой. Чтобы 1С «видела» этот символ, необходимо:

  1. Перевести сканер в режим эмуляции COM-порта.
  2. Настроить в 1С драйвер устройства ввода на работу через COM-порт (или USB-CDC).
  3. Если используется режим клавиатуры, настроить в сканере замену символа с кодом 29 на какой-то печатный символ (например, «#»), но это менее надежный способ.

Реализация парсинга в 1С

Рассмотрим пример функции, которая может разбирать строку DataMatrix, учитывая идентификаторы применения. Помним, что идентификаторы 01 и 17 имеют фиксированную длину, а 21 и 10 — переменную (до встречи символа GS или конца строки).


Функция РазобратьКодМаркировки(Знач СтрКода) Экспорт
    Результат = Новый Структура("GTIN, Серия, Партия, СрокГодности", "", "", "", "");
    
    // Очистим строку от возможных спецсимволов в начале
    СтрКода = Сред(СтрКода, 1); 
    
    ТекущаяПозиция = 1;
    Пока ТекущаяПозиция <= СтрДлина(СтрКода) Цикл
        Идентификатор = Сред(СтрКода, ТекущаяПозиция, 2);
        
        Если Идентификатор = "01" Тогда // GTIN
            Результат.GTIN = Сред(СтрКода, ТекущаяПозиция + 2, 14);
            ТекущаяПозиция = ТекущаяПозиция + 16;
            
        ИначеЕсли Идентификатор = "21" Тогда // Серийный номер
            // Ищем разделитель GS (Символ с кодом 29)
            ПозРазделителя = Найти(Сред(СтрКода, ТекущаяПозиция + 2), Символ(29));
            Если ПозРазделителя = 0 Тогда // Разделителя нет, значит данные до конца строки
                Результат.Серия = Сред(СтрКода, ТекущаяПозиция + 2);
                ТекущаяПозиция = СтрДлина(СтрКода) + 1;
            Иначе
                Результат.Серия = Сред(СтрКода, ТекущаяПозиция + 2, ПозРазделителя - 1);
                ТекущаяПозиция = ТекущаяПозиция + 2 + ПозРазделителя;
            КонецЕсли;
            
        ИначеЕсли Идентификатор = "17" Тогда // Срок годности (ГГММДД)
            СрокСтрокой = Сред(СтрКода, ТекущаяПозиция + 2, 6);
            Результат.СрокГодности = "20" + Лев(СрокСтрокой, 2) + "-" + Сред(СрокСтрокой, 3, 2) + "-" + Прав(СрокСтрокой, 2);
            ТекущаяПозиция = ТекущаяПозиция + 8;
            
        ИначеЕсли Идентификатор = "10" Тогда // Партия
            ПозРазделителя = Найти(Сред(СтрКода, ТекущаяПозиция + 2), Символ(29));
            Если ПозРазделителя = 0 Тогда
                Результат.Партия = Сред(СтрКода, ТекущаяПозиция + 2);
                ТекущаяПозиция = СтрДлина(СтрКода) + 1;
            Иначе
                Результат.Партия = Сред(СтрКода, ТекущаяПозиция + 2, ПозРазделителя - 1);
                ТекущаяПозиция = ТекущаяПозиция + 2 + ПозРазделителя;
            КонецЕсли;
        Иначе
            // Прочие идентификаторы (криптохвост и т.д.) пропускаем или обрабатываем аналогично
            ТекущаяПозиция = ТекущаяПозиция + 1;
        КонецЕсли;
    КонецЦикла;
    
    Возврат Результат;
КонецФункции

Алгоритм работы при отсутствии данных в коде

Если после работы функции парсинга поля Партия и СрокГодности остались пустыми, проанализируем следующий алгоритм действий:

  1. Проверка внутреннего справочника: Сначала поищем в нашей базе данных 1С (в регистрах сведений или справочнике «Штрихкоды упаковок») — возможно, эта упаковка уже была ранее зарегистрирована при поступлении.
  2. Запрос к API ГИС: Если упаковка новая, необходимо выполнить HTTP-запрос к API национальной системы маркировки (МДЛП или ЭБД ЛС). Для этого используется метод получения информации по SGTIN (комбинация GTIN + Серия).
  3. Обогащение данных: После получения JSON-ответа от системы, программно заполним реквизиты серии и срока годности в документе реализации или поступления.

Таким образом, полноценная работа с маркировкой лекарств требует не только умения разбирать текстовую строку, но и настроенного взаимодействия с внешними информационными системами. Помните, что код на упаковке — это лишь «ключ», который открывает доступ к полной карточке товара в государственном реестре.

← На главную