Настройка разрешительного режима и исправление ошибок проверки марок в УТ 10.3

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

С 1 апреля 2024 года поэтапно вводится обязательный разрешительный режим на кассах для маркированных товаров. Для пользователей конфигурации 1С:Управление торговлей 10.3 эта задача усложняется тем, что конфигурация находится на ограниченной поддержке (или снята с нее), и типовой функционал последних релизов (например, 10.3.88.3) содержит ошибки или недоработки. В частности, данные о проверке кода маркировки (UUID запроса и дата) не попадают в фискальный чек (тег 1260), а продажа запрещенного товара не блокируется программой.

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

Предварительные настройки и требования

Прежде чем приступать к правкам кода, убедимся, что базовые условия выполнены. Без них программные доработки не дадут результата.

  1. Драйвер ККТ: Версия драйвера должна быть актуальной (например, для АТОЛ ветка 10.10.x). Прошивка кассы должна поддерживать ФФД 1.2.
  2. Токен авторизации: В настройках интеграции с ИС МП должен быть введен токен для разрешительного режима, полученный в личном кабинете Честного ЗНАКа.
  3. Настройки сканирования: В настройках параметров учета или настройках сканера штрихкодов должны быть установлены даты начала действия разрешительного режима для соответствующих товарных групп (вода, молоко, пиво и т.д.).
  4. CDN площадки: Список CDN площадок должен быть обновлен и доступен (проверьте, не блокирует ли файрвол доступ к адресам Честного ЗНАКа).

Проблема 1: Отсутствие данных проверки в теге 1260

Основная проблема заключается в том, что даже при успешной проверке марки через API Честного ЗНАКа, идентификаторы этой проверки не сохраняются в документ ЧекККМ. Следовательно, они не передаются в драйвер ККТ при пробитии чека, и в ОФД чек уходит со статусом "Не проверен" (красный статус в ЛК ЧЗ).

Данные о проверке (РазрешительныйРежимИдентификаторЗапросаГИСМТ и РазрешительныйРежимДатаЗапросаГИСМТ) теряются при переносе подобранных товаров из формы подбора/проверки в табличную часть документа.

Для исправления необходимо доработать процедуру в форме документа ЧекККМ. Откроем форму документа (обычно это ФормаРегистрацииПродаж или основная форма документа, в зависимости от того, как организовано РМК) и найдем процедуру, отвечающую за закрытие формы подбора маркировки — ПриЗакрытииФормыПроверкиПодбораИСМП.

В типовом коде происходит перебор строк из ДанныеПроверкиИПодбора.ТаблицаШтрихкодовВерхнегоУровня и добавление их в АкцизныеМарки документа. Нам необходимо явно перенести реквизиты разрешительного режима.

Рассмотрим корректный код с проверкой на наличие колонок (чтобы избежать ошибок, если структура данных отличается в разных сценариях, например, при возврате):


Для Каждого СтрокаАкцизныхМарок Из ДанныеПроверкиИПодбора.ТаблицаШтрихкодовВерхнегоУровня Цикл
    НоваяСтрокаАкцизныхМарок = АкцизныеМарки.Добавить();
    НоваяСтрокаАкцизныхМарок.АкцизнаяМарка = СтрокаАкцизныхМарок.ШтрихкодУпаковки;
    
    // Начало доработки: перенос данных разрешительного режима
    
    // Проверяем наличие колонки с Идентификатором запроса
    Если НЕ ДанныеПроверкиИПодбора.ТаблицаШтрихкодовВерхнегоУровня.Колонки.Найти("РазрешительныйРежимИдентификаторЗапросаГИСМТ") = Неопределено Тогда
        // Переносим значение
        НоваяСтрокаАкцизныхМарок.РазрешительныйРежимИдентификаторЗапросаГИСМТ = СтрокаАкцизныхМарок.РазрешительныйРежимИдентификаторЗапросаГИСМТ;
    КонецЕсли;

    // Проверяем наличие колонки с Датой запроса
    Если НЕ ДанныеПроверкиИПодбора.ТаблицаШтрихкодовВерхнегоУровня.Колонки.Найти("РазрешительныйРежимДатаЗапросаГИСМТ") = Неопределено Тогда
        // Переносим значение
        НоваяСтрокаАкцизныхМарок.РазрешительныйРежимДатаЗапросаГИСМТ = СтрокаАкцизныхМарок.РазрешительныйРежимДатаЗапросаГИСМТ;
    КонецЕсли;
    
    // Конец доработки

КонецЦикла;

Обратите внимание: мы используем конструкцию НЕ ... = Неопределено вместо ЗначениеЗаполнено() для проверки наличия колонки, так как в некоторых старых платформах проверка мутабельных значений коллекции колонок может вызывать ошибку.

Проблема 2: "Костыль" при формировании строки штрихкода

В некоторых случаях данные теряются еще раньше — на этапе формирования структуры штрихкода в общем модуле. Если предыдущее решение не помогло полностью, стоит проверить общий модуль ШтрихкодированиеИСМП.

В процедуре ЗаполнениеСохраняемойСтрокиШтрихкодовУпаковкиПоДаннымРазрешительнойСистемыГИСМТ иногда приходит пустой идентификатор в корне структуры ДанныеШтрихкода, но при этом он есть внутри массива ДополнительныеПараметры.ЭлементыПроверки.

Внесем изменения для принудительного извлечения данных:


// В модуле ШтрихкодированиеИСМП
Если ЗначениеЗаполнено(ПараметрыСканирования.ИмяКолонкиРазрешительныйРежимИдентификаторЗапросаГИСМТ) Тогда
    // Пробуем штатное заполнение
    СтрокаШтрихкод[ПараметрыСканирования.ИмяКолонкиРазрешительныйРежимИдентификаторЗапросаГИСМТ] = ДанныеШтрихкода.РазрешительныйРежимИдентификаторЗапросаГИСМТ;
    
    // Дополнительная подстраховка: берем из элементов проверки, если штатно пусто или для надежности
    // Проверьте, что массив ЭлементыПроверки существует и не пуст перед обращением к [0]
    Если ДанныеШтрихкода.ДополнительныеПараметры.Свойство("ЭлементыПроверки") 
       И ДанныеШтрихкода.ДополнительныеПараметры.ЭлементыПроверки.Количество() > 0 Тогда
          СтрокаШтрихкод[ПараметрыСканирования.ИмяКолонкиРазрешительныйРежимИдентификаторЗапросаГИСМТ] = ДанныеШтрихкода.ДополнительныеПараметры.ЭлементыПроверки[0].РазрешительныйРежимИдентификаторЗапросаГИСМТ;
    КонецЕсли;
КонецЕсли;

Если ЗначениеЗаполнено(ПараметрыСканирования.ИмяКолонкиРазрешительныйРежимДатаЗапросаГИСМТ) Тогда
    СтрокаШтрихкод[ПараметрыСканирования.ИмяКолонкиРазрешительныйРежимДатаЗапросаГИСМТ] = ДанныеШтрихкода.РазрешительныйРежимДатаЗапросаГИСМТ;
    
    // Аналогично для даты
    Если ДанныеШтрихкода.ДополнительныеПараметры.Свойство("ЭлементыПроверки") 
       И ДанныеШтрихкода.ДополнительныеПараметры.ЭлементыПроверки.Количество() > 0 Тогда
        СтрокаШтрихкод[ПараметрыСканирования.ИмяКолонкиРазрешительныйРежимДатаЗапросаГИСМТ] = ДанныеШтрихкода.ДополнительныеПараметры.ЭлементыПроверки[0].РазрешительныйРежимДатаЗапросаГИСМТ;
    КонецЕсли;
КонецЕсли;

Проблема 3: Отсутствие блокировки продажи

Самый критичный момент: даже если проверка проходит и возвращает ошибку (например, "Товар просрочен" или "Выведен из оборота"), УТ 10.3 в типовом релизе может просто проигнорировать это и позволить добавить товар в чек. Визуально вы увидите сообщение о статусе, но блокировки действия не произойдет.

Для реализации жесткой блокировки необходимо доработать общий модуль ИнтерфейсИСМП. Найдем процедуру, выполняющую запрос к площадке (обычно ОтправитьЗапросПоКодуМаркировкиНаПлощадку или аналогичную, вызываемую при сканировании).

Нам нужно проанализировать ответ от ГИС МТ и, если есть флаг блокировки, принудительно установить текст ошибки, который прервет дальнейшую обработку.


// В процедуре обработки ответа от ИС МП

// 1. Проверка флага блокировки от самого Честного Знака
Если ПараметрыКодаМаркировки.ПродажаЗаблокирована И ПараметрыКодаМаркировки.СписокОрганизацийБлокировкиКМ.Количество() > 0 Тогда
    ШаблонОшибки = НСтр("ru = 'Оборот товара был заблокирован. | |Организации, принявшие решение о блокировке товара: |%1.'");
    
    МассивПредставленийОрганизацийПоИдентификаторам = ИнтерфейсИСМПСлужебный.ОрганыВластиУстанавливающиеБлокировкуНаКМПоДаннымГИСМТ(ПараметрыКодаМаркировки.СписокОрганизацийБлокировкиКМ);
    
    // Установка текста ошибки прерывает продажу в стандартной логике 1С
    ДанныеШтрихкода.ТекстОшибки = СтрШаблон(ШаблонОшибки, СтрСоединить(МассивПредставленийОрганизацийПоИдентификаторам, ", "));
КонецЕсли;

// 2. Дополнительная проверка статуса (например, попытка повторной продажи)
// Проверяем, что статус отличается от "Введен в оборот"
Если ПараметрыКодаМаркировки.Статус <> Перечисления.СтатусыКодовМаркировкиИСМП.ВведенВОборот 
   И ПараметрыКодаМаркировки.Статус <> Перечисления.СтатусыКодовМаркировкиИСМП.ВведенВОборотПриВозврате Тогда
    
    ДанныеШтрихкода.ТекстОшибки = НСтр("ru = 'Статус кода маркировки: "+ПараметрыКодаМаркировки.Статус+". Продажа запрещена!'");

КонецЕсли;

Добавление этого кода гарантирует, что при получении негативного статуса от ГИС МТ кассир увидит окно с ошибкой, и товар не будет добавлен в табличную часть.

Проблема 4: Ошибки таймаута

Иногда идентификатор запроса (UUID) не возвращается или возвращается пустым эпизодически. Это может быть связано с коротким временем ожидания ответа от сервера Честного Знака. По умолчанию может стоять значение около 1.5 секунд.

Решение: Увеличьте таймаут ожидания ответа в настройках интеграции с ИС МП до 5 секунд. Это снижает количество "ложных" ошибок при нестабильном интернете.

Нюансы работы в разных режимах

Важно отметить, что описанные механизмы корректно отрабатывают преимущественно в режиме РМК (Рабочее Место Кассира). Если вы пытаетесь оформить розничную продажу через документ Реализация товаров и услуг с последующим пробитием чека, логика может не сработать, так как цепочка вызовов процедур проверки там иная.

В документе Реализация товаров и услуг зачастую проверка марок запускается только в контексте оптовых продаж (для ЭДО), а механизмы онлайн-проверки на кассе (разрешительный режим) могут быть не подключены к процедуре печати чека из этого документа. Рекомендуется использовать для розничных продаж специализированный интерфейс РМК или документ ЧекККМ.

Резюме

Для настройки разрешительного режима в УТ 10.3 необходимо:

  1. Обновить драйвер ККТ и прошивку.
  2. Дописать в форме документа ЧекККМ перенос полей РазрешительныйРежимИдентификаторЗапросаГИСМТ и даты запроса.
  3. Внедрить проверку флага ПродажаЗаблокирована в модуле интеграции ИС МП для реальной блокировки действий кассира.
  4. Увеличить таймаут запроса до 5 секунд.
← На главную