При разработке кассовых решений и механизмов взаимодействия с фискальными регистраторами часто возникает задача пробить два чека подряд (например, при разделении товаров по разным системам налогообложения). На платформе 1С в режиме управляемого приложения вызов форм не останавливает исполнение кода. В результате программа пытается сразу же сформировать второй чек, не дожидаясь завершения обработки первого. Это приводит к наложению интерфейсных окон, ошибкам драйвера ККТ и запросам на аннулирование чека.
Рассмотри подробно, почему возникает эта проблема и как правильно построить асинхронную логику работы без применения модальных окон.
Проанализируем ситуация с точки зрения работы платформы 1С и оборудования:
ОткрытьФорму выполняется асинхронно. Код клиентской процедуры не ждет закрытия окна, а продолжается линейно, выполняя команды создания второго чека.Пока Форма.Открыта() Цикл ... КонецЦикла приводит к полному зависанию клиентского сеанса, так как интерфейс перестает откликаться на действия пользователя.Для передачи управления после закрытия первого окна или завершения операции используется объект ОписаниеОповещения. С его помощью платформа вызывает нужную процедуру только после того, как первое окно будет зафиксировано и закрыто.
Разберем пример кода передачи параметров и вызова обратного обработчика:
// Формируем дополнительные параметры для передачи в следующий шаг
ДопПараметры = Новый Структура;
ДопПараметры.Вставить("ДокументПродажи", СсылкаНаДокумент);
ДопПараметры.Вставить("СуммаВторойЧасти", СуммаВторогоЧека);
// Создаем описание оповещения, указывая имя процедуры-обработчика и контекст
ОповещениеОЗавершении = Новый ОписаниеОповещения("НапечататьВторойЧекЗавершение", ЭтаФорма, ДопПараметры);
// Открываем форму фронта кассира для первого чека
ОткрытьФорму("Обработка.РМК.Форма.ФормаОплаты",
ПараметрыОткрытия,
ЭтаФорма,
УникальныйИдентификатор,
,
,
ОповещениеОЗавершении,
РежимОткрытияОкнаФормы.БлокироватьВесьИнтерфейс);
Для корректной работы процедуры-обработчика необходимо соблюдать следующие требования:
&НаКлиенте.Экспорт.Посмотрим на пример процедуры-обработчика, которая вызывается после закрытия формы первого чека:
&НаКлиенте
Процедура НапечататьВторойЧекЗавершение(РезультатЗакрытия, ДополнительныеПараметры) Экспорт
Если РезультатЗакрытия <> Неопределено И РезультатЗакрытия Тогда
// Первый чек успешно пробит, переходим к формированию и печати второго чека
ДокументПродажи = ДополнительныеПараметры.ДокументПродажи;
СуммаВторойЧасти = ДополнительныеПараметры.СуммаВторойЧасти;
// Вызов процедуры печати второго чека
ПробитьЧекПоВторойСНО(ДокументПродажи, СуммаВторойЧасти);
Иначе
ПоказатьПредупреждение(, "Печать второго чека отменена, так как первый чек не был оформлен.");
КонецЕсли;
КонецПроцедуры
Если логика пробития чека находится глубоко внутри модуля обработки кассы, удобнее использовать механизм глобальных или локальных оповещений. При завершении фискализации первого чека кассовый модуль генерирует событие с помощью метода Оповестить.
Рассмотрим порядок действий при таком подходе:
Оповестить("ПервыйЧекПробитУспешно", Новый Структура("Статус", Истина), ЭтаФорма);
ОбработкаОповещения:
&НаКлиенте
Процедура ОбработкаОповещения(ИмяСобытия, Параметр, Источник)
Если ИмяСобытия = "ПервыйЧекПробитУспешно" И Параметр.Статус Тогда
// Запускаем алгоритм отправки данных для второго чека
СформироватьИОтправитьВторойЧек();
КонецЕсли;
КонецПроцедуры
В современных версиях платформы 1С:Предприятие (начиная с версии 8.3.18) доступен механизм асинхронных функций, позволяющий писать последовательный код без разбиения его на множественные процедурные вызовы.
Выясним, как выглядит этот подходом на практике:
&НаКлиенте
Асинх Процедура ОплатитьИПробитьДваЧекаАсинх()
// Открываем форму первого чека и ждем ее закрытия
РезультатПервогоЧека = Ждать ОткрытьФормуАсинх("Обработка.РМК.Форма.ФормаОплаты", ПараметрыПервогоЧека);
Если РезультатПервогоЧека <> Неопределено Тогда
// Код приостанавливает выполнение на строке Ждать и продолжит работу только после закрытия первого окна
РезультатВторогоЧека = Ждать ОткрытьФормуАсинх("Обработка.РМК.Форма.ФормаОплаты", ПараметрыВторогоЧека);
КонецЕсли;
КонецПроцедуры
Использование ОткрытьФормуАсинх и оператора Ждать сохраняет читаемость кода и полностью исключает наложение интерфесных окон кассы друг на друга.