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