Как правильно реализовать опрос о бонусной карте перед оплатой в РМК 1С:Розница, чтобы окна открывались в нужном порядке?

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

При разработке интерфейсов в режиме управляемого приложения 1С, особенно в таких нагруженных участках, как Рабочее место кассира (РМК), программисты часто сталкиваются с проблемой нарушения последовательности открытия окон. Типичная ситуация: при нажатии кнопки "Наличные" сначала должно появиться окно с вопросом о бонусной карте, а только после ответа на него — форма оплаты. Однако на практике часто происходит наоборот или окна накладываются друг на друга некорректно. Рассмотрим подробно, почему это происходит и как правильно реализовать эту логику, используя современные механизмы платформы 1С.

Разбор причины: почему нарушается последовательность выполнения кода

Проанализируем ситуацию, с которой сталкиваются многие разработчики. В старых версиях платформы (или в режиме обычных форм) мы привыкли к модальным окнам. Код останавливался на строке вызова функции Вопрос, ждал ответа пользователя и только потом шел дальше. В управляемом приложении и при включенном режиме "Запретить модальные окна" используется асинхронный метод ПоказатьВопрос.

Основная особенность ПоказатьВопрос заключается в том, что эта процедура не останавливает выполнение кода. Когда система встречает этот вызов, она лишь "запланирует" показ окна и моментально перейдет к следующей строке кода. В результате процедура открытия формы оплаты (например, ВыполнитьЧО05Наличные()) запускается сразу же, не дожидаясь, пока кассир нажмет "Да" или "Нет" в окне вопроса. Именно поэтому окно оплаты "выскакивает" первым или перекрывает вопрос.

Решение №1: Использование ОписанияОповещения (классический асинхронный подход)

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

Во-первых, в основной процедуре нажатия кнопки мы должны вызвать окно вопроса и прекратить дальнейшее выполнение кода. Весь последующий код, включая оплату, мы перенесем в отдельную процедуру-обработчик.


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

&НаКлиенте
Процедура ПослеВопросаОКарте(Результат, ДополнительныеПараметры) Экспорт
    
    // Результат — это то, что выбрал пользователь (КодВозвратаДиалога)
    Если Результат = КодВозвратаДиалога.Да Тогда
        // Здесь вызываем логику поиска или сканирования карты
        ПроверитьДисконтнуюКарту(); 
    КонецЕсли;
    
    // Только ТЕПЕРЬ, когда мы получили ответ, вызываем форму оплаты
    ВыполнитьЧО05Наличные();
    
КонецПроцедуры

Этот метод гарантирует, что ВыполнитьЧО05Наличные() сработает только после закрытия диалога ПоказатьВопрос. Обратите внимание на ключевое слово Экспорт в процедуре-обработчике — оно обязательно для процедур, вызываемых через ОписаниеОповещения.

Решение №2: Современный подход через Асинх / Ждать (платформа 8.3.18+)

Если ваша конфигурация работает на современной версии платформы 1С (8.3.18 и выше), мы можем использовать более элегантный способ — асинхронные функции. Они позволяют писать асинхронный код так, будто он линейный. Проанализируем, как изменится наш пример:


&НаКлиенте
Асинх Процедура КартинкаЧО05НаличныеНажатие(Элемент)
    
    // Используем Ждать для приостановки выполнения до получения ответа
    Результат = Ждать ВопросАсинх("Использовать бонусную карту?", РежимДиалогаВопрос.ДаНет);
    
    Если Результат = КодВозвратаДиалога.Да Тогда
        // Выполняем действия с картой
        Ждать ПроверитьДисконтнуюКартуАсинх(); 
    КонецЕсли;
    
    // Код продолжится только после того, как "Ждать" получит результат
    ВыполнитьЧО05Наличные();
    
КонецПроцедуры

Использование Асинх и Ждать (await) значительно упрощает чтение кода и исключает создание множества процедур-оповещений. Это наиболее рекомендуемый способ для современной разработки.

Важные нюансы работы в РМК 1С:Розница

Рассмотрим специфические моменты, которые могут помешать работе даже правильного кода. При внедрении проверок в РМК нужно учитывать следующее:

  1. Горячие клавиши: В 1С:Розница оплата наличными часто вызывается нажатием клавиши (например, F6). Если вы написали код только в обработчике нажатия на картинку/кнопку, то при нажатии F6 ваш вопрос не появится. Необходимо найти общую точку входа в модуле формы РМК (например, процедуру ВыполнитьОплату) и вносить изменения туда через расширение.
  2. СтандартнаяОбработка: Если вы используете предопределенные события формы, всегда устанавливайте СтандартнаяОбработка = Ложь, иначе система выполнит типовой алгоритм параллельно с вашим вопросом.
  3. Повторный вызов оплаты: Проанализируем ситуацию из сообщения №13 форума. Если после переноса кода в оповещение окно всё равно двоится, проверьте, не остался ли вызов ВыполнитьЧО05Наличные() в исходной процедуре. Также убедитесь, что процедура оплаты не вызывается обработчиком ожидания или другими событиями формы, которые могли сработать в момент паузы.

Почему не стоит возвращаться к модальным окнам?

Некоторые разработчики, отчаявшись настроить асинхронные вызовы, включают в свойствах конфигурации "Использовать модальность" и используют старый Вопрос(). Это плохая практика по нескольким причинам:

Таким образом, правильное использование ОписаниеОповещения или механизмов Асинх/Ждать является единственным верным способом реализации диалогов в современном РМК. Это обеспечивает стабильную работу программы и корректное взаимодействие с пользователем.

← На главную