Как настроить интеграцию с МДЛП в 1С и подготовить оборудование: разбор архитектуры, кодировок и сканеров

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

Интеграция с системой Мониторинга движения лекарственных препаратов (МДЛП, она же «Честный знак» для фармы) на начальных этапах казалась разработчикам и системным администраторам настоящим техническим кошмаром. Огромный объем транзакций, строгие требования к сетевой безопасности, запутанные бизнес-процессы агрегирования и расформирования упаковок — все это требовало нестандартных архитектурных ходов. В рамках данной статьи мы подробно разберем, как решать ключевые проблемы интеграции, спроектировать надежную базу данных, правильно настроить торговое оборудование и обойти ограничения платформы 1С.

Архитектура базы данных: почему хранить sGTIN в 1С — плохая идея для крупного бизнеса

Давайте проанализируем ситуацию, с которой сталкивается крупный дистрибьютор или крупная аптечная сеть. При обороте в 30 миллионов упаковок в месяц база данных за год должна будет вместить сотни миллионов уникальных кодов маркировки (sGTIN). Если записывать каждый код непосредственно в стандартные регистры сведений или справочники информационной базы 1С, это неминуемо приведет к лавинообразному росту размера базы (на терабайты данных) и катастрофическому падению производительности СУБД.

Для решения этой проблемы рассмотрим гибридную архитектуру. Вместо хранения кодов в 1С мы выносим весь помарочный учет во внешнюю специализированную базу данных (например, на MS SQL Server или PostgreSQL), а в самой 1С храним только ссылки на документы и агрегированные идентификаторы пакетов. Наша система 1С будет общаться с внешней базой через механизмы ADO (ActiveX Data Objects) или посредством HTTP-запросов к специально написанному микросервису.

Ниже приведем практический пример кода на языке 1С, реализующий получение кодов sGTIN из внешней базы данных MS SQL для конкретного документа поступления:


// Функция выполняет запрос к внешней базе данных для получения списка sGTIN
Функция ПолучитьМаркиИзВнешнейБД(ИдентификаторДокумента1С) Экспорт
    
    Соединение = Новый ADODB.Connection;
    СтрокаПодключения = "Driver={SQL Server};Server=MdlpServerAddress;Database=MdlpStore;Uid=1c_integration;Pwd=SecurePassword123;";
    
    Попытка
        Соединение.Open(СтрокаПодключения);
    Исключение
        ЗаписатьЛогСобытий("Ошибка подключения к внешней БД МДЛП: " + ОписаниеОшибки(), УровеньЖурналаРегистрации.Ошибка);
        Возврат Неопределено;
    КонецПопытки;
    
    ЗапросSQL = "
    |SELECT sGTIN, CodeStatus 
    |FROM dbo.SgtinStorage 
    |WHERE DocUUID = '" + Строка(ИдентификаторДокумента1С) + "'";
    
    НаборЗаписей = Новый ADODB.Recordset;
    Попытка
        НаборЗаписей = Соединение.Execute(ЗапросSQL);
    Исключение
        ЗаписатьЛогСобытий("Ошибка выполнения запроса к БД: " + ОписаниеОшибки(), УровеньЖурналаРегистрации.Ошибка);
        Соединение.Close();
        Возврат Неопределено;
    КонецПопытки;
    
    ТаблицаКодов = Новый ТаблицаЗначений;
    ТаблицаКодов.Колонки.Добавить("sGTIN", Новый ОписаниеТипов("Строка",,,, Новый КвалификаторыСтроки(27)));
    ТаблицаКодов.Колонки.Добавить("Статус", Новый ОписаниеТипов("Строка",,,, Новый КвалификаторыСтроки(50)));
    
    Пока НЕ НаборЗаписей.EOF() Цикл
        НоваяСтрока = ТаблицаКодов.Добавить();
        НоваяСтрока.sGTIN = Строка(НаборЗаписей.Fields("sGTIN").Value);
        НоваяСтрока.Статус = Строка(НаборЗаписей.Fields("CodeStatus").Value);
        НаборЗаписей.MoveNext();
    КонецЦикла;
    
    Соединение.Close();
    Возврат ТаблицаКодов;
    
КонецФункции

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

Сетевые требования и кодировки: обходим подводные камни API МДЛП

Рассмотрим сетевые нюансы работы с API Честного Знака. На этапе тестирования и ранней интеграции разработчики часто сталкиваются с ошибками сетевого тайм-аута. Выясним причину: в целях защиты от DDoS-атак и несанкционированного доступа СУЗ (Станция управления заказами) и сам шлюз МДЛП могут требовать предварительной регистрации статического публичного IP-адреса вашей организации. Без внесения вашего IP-адреса в белый список на стороне сервера Честного Знака, ваши запросы будут просто отбрасываться файрволом («падать по тайм-ауту»). Поэтому перед началом программирования обязательно согласуйте со своим провайдером выделение белого статического IP-адреса и отправьте заявку на его регистрацию в техподдержку ЦРПТ.

Второй частый подводный камень — кодировка передаваемых файлов и сообщений. В официальных мануалах повсеместно декларируется стандарт UTF-8. Однако при интеграции с тестовыми контурами и при выгрузке некоторых файлов отчетов (особенно в формате CSV) вы можете столкнуться с кодировкой Windows-1251. Если ваше кассовое или складское ПО сформирует XML/JSON в неверной кодировке, сервер МДЛП вернет ошибку валидации схемы. Принудительно устанавливайте кодировку при формировании HTTP-запросов и файлов обмена в коде 1С, как показано далее:


// Пример правильной установки кодировки при отправке JSON-запроса в API МДЛП
Функция ОтправитьЗапросВМДЛП(АдресРесурса, ТелоЗапросаСтрока, ТокенАвторизации)
    
    HTTPСоединение = Новый HTTPСоединение("api.mdlp.crpt.ru", 443,,,,, Новый ЗащищенноеСоединениеOpenSSL());
    
    HTTPЗапрос = Новый HTTPRequest(АдресРесурса);
    HTTPЗапрос.Заголовки.Вставить("Authorization", "Token " + ТокенАвторизации);
    // Принудительно указываем UTF-8 для Content-Type
    HTTPЗапрос.Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");
    
    // Передаем строку, предварительно убедившись, что платформа 1С преобразует ее в UTF-8
    HTTPЗапрос.УстановитьТелоИзСтроки(ТелоЗапросаСтрока, КодировкаТекста.UTF8, ИспользованиеМаркераПоследовательностиБайтов.НеИспользовать);
    
    Попытка
        Ответ = HTTPСоединение.ОтправитьДляОбъекта(HTTPЗапрос);
        Возврат Ответ.ПолучитьТелоКакСтроку(КодировкаТекста.UTF8);
    Исключение
        ЗаписатьЛогСобытий("Ошибка HTTP-запроса: " + ОписаниеОшибки(), УровеньЖурналаРегистрации.Ошибка);
        Возврат "";
    КонецПопытки;
    
КонецФункции

Выбор и настройка 2D-сканера для считывания DataMatrix (на примере Honeywell Voyager 1450g)

Для корректного распознавания кодов DataMatrix на лекарственных упаковках обычные линейные 1D-сканеры не подходят. Необходим качественный 2D-сканер-имиджер. Практическим стандартом в фармацевтической отрасли стал сканер Honeywell Voyager 1450g благодаря оптимальному соотношению цены и качества распознавания замятых или блеклых кодов.

Рассмотрим пошагово процесс подготовки и программирования этого сканера для работы с 1С и МДЛП:

  1. Режим презентации (на подставке): В аптеках важно освободить руки первостольника. Чтобы сканер работал в непрерывном режиме или активировался по датчику приближения, необходимо считать управляющий штрихкод «Presentation Mode» из оригинальной инструкции Honeywell. Это переведет сканер в режим автоматического распознавания при поднесении упаковки.
  2. Эмуляция COM-порта (USB-COM): По умолчанию сканер работает в режиме клавиатуры (USB-HID). В этом режиме велика вероятность потери символов при быстрой работе или некорректной раскладке клавиатуры ПК (русская/английская). Рекомендуется установить на ПК официальный драйвер Honeywell HSM USB Serial Driver и отсканировать штрихкод «USB Serial Emulation». В системе появится виртуальный COM-порт (например, COM3), к которому без труда подключится драйвер торгового оборудования в 1С.
  3. Настройка передачи разделителя GS (ASCII 29): Коды DataMatrix для МДЛП содержат спецсимвол-разделитель GS, который отделяет серийный номер от криптохвоста. Если сканер не настроен на передачу этого символа, 1С не сможет корректно распарсить штрихкод, и документ не пройдет проверку в Честном Знаке. Настройте в сканере суффиксы и префиксы, чтобы символ ASCII 29 передавался корректно (например, через замену на печатный символ или прямую передачу управляющего кода в драйвер).

Проанализируем алгоритм обработки считанного штрихкода в коде 1С, учитывающий наличие скрытого разделителя GS:


// Функция разбирает считанный 2D-сканером код маркировки лекарственного средства
Функция РазобратьШтрихкодDataMatrix(Знач СчитанныйШтрихкод) Экспорт
    
    Результат = Новый Структура;
    Результат.Вставить("GTIN", "");
    Результат.Вставить("СерийныйНомер", "");
    Результат.Вставить("ОшибкаРазбора", Истина);
    
    РазделительGS = Символ(29); // ASCII код 29
    
    // В стандартном коде МДЛП первыми идут идентификаторы применения (AI): 01 (GTIN) и 21 (Серийный номер)
    Если Лев(СчитанныйШтрихкод, 2) = "01" Тогда
        Результат.GTIN = Сред(СчитанныйШтрихкод, 3, 14);
        
        Если Сред(СчитанныйШтрихкод, 17, 2) = "21" Тогда
            ОстатокСтроки = Сред(СчитанныйШтрихкод, 19);
            ПозицияGS = Найти(ОстатокСтроки, РазделительGS);
            
            Если ПозицияGS > 0 Тогда
                Результат.СерийныйНомер = Лев(ОстатокСтроки, ПозицияGS - 1);
            Иначе
                // Если разделитель GS не найден, серийный номер может идти до конца строки
                // Это бывает, если криптохвост отсутствует или сканер настроен некорректно
                Результат.СерийныйНомер = ОстатокСтроки;
            КонецЕсли;
            
            Результат.ОшибкаРазбора = Ложь;
        КонецЕсли;
    КонецЕсли;
    
    Возврат Результат;
    
КонецФункции

Помарочный учет на складе: Агрегирование и работа с кодами SSCC

Для дистрибьюторов и крупных аптечных складов критически важна операция агрегирования (объединения индивидуальных sGTIN в групповые транспортные коробки и паллеты со своими уникальными кодами SSCC). Рассмотрим, как устроен этот процесс.

Приемка и отгрузка паллетами существенно ускоряет работу склада: вместо сканирования сотен отдельных пачек оператор сканирует один штрихкод SSCC, и система автоматически понимает, какие именно лекарства находятся внутри. Однако в реальной жизни происходят процессы расформирования (разагрегирования) коробок из-за брака, пересорта или частичной продажи. Система МДЛП позволяет расформировать коробку и собрать её заново с другим составом sGTIN под тем же самым или новым кодом SSCC.

Чтобы избежать путаницы в WMS-системе склада, настоятельно рекомендуем не пытаться хранить в 1С бесконечную историю изменения состава одной и той же коробки SSCC. При любой операции разагрегирования уничтожайте связь состава с этим SSCC в вашей базе данных, а при повторной упаковке генерируйте новый уникальный код SSCC. Это спасет вашу базу от коллизий данных и расхождения с реестром Честного Знака.

Оформление розничных возвратов в 1С

С технической и юридической точки зрения возврат лекарств имеет строгую специфику. По закону РФ качественные лекарственные препараты возврату не подлежат. Но что делать, если произошел ошибочный отпуск, или препарат оказался некачественным/бракованным?

Современные конфигурации 1С (такие как «1С:Розница. Аптека») полностью поддерживают необходимые бизнес-процессы возврата выведенных из оборота препаратов. При оформлении чека возврата на кассе, программа автоматически формирует уведомление по схеме 391 (возврат лекарственных препаратов в оборот). Этот документ подписывается УКЭП организации и отправляется в МДЛП. После подтверждения со стороны системы код маркировки снова становится активным и может быть повторно продан или списан по процедуре утилизации.

Эволюция МДЛП: Разрешительный режим с 2025 года

Интеграция с МДЛП — динамический процесс. С 2025 года для лекарственных средств вводится обязательный разрешительный режим на кассах. Если раньше кассовая программа просто отправляла отчет о выбытии постфактум, то теперь касса перед пробитием чека обязана в онлайн-режиме запросить МДЛП о статусе данного конкретного кода DataMatrix. Если сервер вернет информацию о том, что срок годности лекарства истек, код заблокирован государственными органами, или он уже был выведен из оборота ранее — кассовое ПО технически заблокирует продажу. Это требует от разработчиков 1С внедрения новых API-запросов онлайн-проверки и тонкой настройки таймаутов соединения, чтобы покупатели на кассах не стояли в очередях из-за зависших интернет-запросов.

← На главную