пятница, 5 июля 2019 г.

1С УФ ПоказатьВопрос ПередЗаписью

Встала задача - перед записью документа произвести некоторые проверки и задать вопрос пользователю, в зависимости от ответа - провести документ или нет.

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

Есть несколько вариантов решения, один - это замена стандартных команд своими, второй использование дополнительных переменных и повторный вызов процедуры.
В моем случае инициирует все процедура ПередЗаписью() (я делал в расширении, перед):

//Объявляем ряд глобальных переменных в контексте клиента
//Пока переменные не переопределены их значение равно - Неопределено
&НаКлиенте
Перем ОтказатьВПроведении;
&НаКлиенте
Перем глПараметрыЗаписи;



&НаКлиенте
Процедура Расш1_ПередЗаписьюПеред(Отказ, ПараметрыЗаписи)
    Если ПараметрыЗаписи.РежимЗаписи = РежимЗаписиДокумента.Проведение Тогда
        глПараметрыЗаписи=ПараметрыЗаписи;
        Если ОтказатьВПроведении=Неопределено Тогда 
            ДиалогСВопросом();
            Отказ=Истина; // завершаем работу процедуры в самом ее зачатке
        Иначе 
            Отказ=ОтказатьВПроведении;
            ОтказатьВПроведении=Неопределено;
        КонецЕсли;
    КонецЕсли;
КонецПроцедуры

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



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

UP 21/05/2022
Был много удивлен, увидев свой пост на этот вопрос заданный мной в гугле, но даже при этом я не удовлетворился описанным методом и упростил его использовав ПараметрыЗаписи:

ПередЗаписью (BeforeWrite)

Синтаксис:

ПередЗаписью(<Отказ>, <ПараметрыЗаписи>)

Параметры:

<Отказ>

Тип: Булево. 
Признак отказа от записи. Если в теле процедуры-обработчика установить данному параметру значение Истина, запись выполнена не будет и будет вызвано исключение.
Значение по умолчанию: Ложь.

<ПараметрыЗаписи>

Тип: Структура. 
Структура, содержащая параметры записи. Для формы документа существует два предопределенных параметра - РежимЗаписи и РежимПроведения. Они добавляются автоматически при вызове команд "Провести", "Провести и закрыть", "Отмена проведения".
Параметр РежимПроведения может отсутствовать, если режим проведения в документе не определен.

 


//НЕ Объявляем ряд глобальных переменных в контексте клиента

&НаКлиенте
Процедура Расш1_ПередЗаписьюПеред(Отказ, ПараметрыЗаписи)
    Если ПараметрыЗаписи.РежимЗаписи = РежимЗаписиДокумента.Проведение Тогда
        Если ПараметрыЗаписи.Свойство("ОтказатьВПроведении") Тогда
            ДиалогСВопросом();
            Отказ=Истина; // завершаем работу процедуры в самом ее зачатке
        Иначе 
            Отказ=ПараметрыЗаписи.ОтказатьВПроведении;
        КонецЕсли;
    КонецЕсли;
КонецПроцедуры

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



Здесь логика почти такая же, но переменная ОтказатьВПроведнии превращается в свойство стандартной структуры ПараметрыЗаписи, что уменьшает код и улучшает его читаемость.

2 комментария:

  1. Сейчас столкнулся с такой задачей, решение в голову пришло такое же. Но есть одна проблема: мы не можем отследить нажал пользователь кнопку "Провести и закрыть" или просто "Провести". Можно, конечно, не закрывать, но у пользователей сразу возникнет большое количество вопросов: "Почему я нажал "Закрыть", но ничего не закрылось".

    ОтветитьУдалить
  2. Хм, интересная мысль. Нет возможности сейчас проверить

    ОтветитьУдалить