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