Как правильно реализовать вопрос пользователю при удалении документа в 1С?

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

Разработчики 1С часто сталкиваются с задачей: необходимо запретить удаление документа или выдать предупреждение, если некий реквизит имеет определенное значение. Начинающие специалисты пытаются прописать вызов функции Вопрос() в модуле объекта, однако платформа выдает ошибку. Давайте разберемся, почему так происходит и как сделать это правильно с точки зрения архитектуры 1С.

Почему нельзя использовать Вопрос() в модуле объекта?

Модуль объекта (и серверные методы в целом) исполняется на стороне сервера. В этот момент выполнение кода происходит внутри транзакции записи. Серверная часть 1С работает изолированно и не имеет прямого доступа к пользовательскому интерфейсу (клиенту). Попытка вызвать функцию Вопрос() на сервере приведет к немедленной ошибке, так как сервер «не знает», какому именно пользователю нужно показать диалоговое окно.

Более того, если бы это было технически возможно, это создало бы критические проблемы для системы:

  1. Блокировки: Транзакция записи удерживалась бы открытой в ожидании ответа пользователя, что привело бы к блокировкам таблиц базы данных и замедлению работы всей системы.
  2. Групповые обработки: При программном удалении 1000 документов через обработки или регламентные задания, выполнение кода постоянно прерывалось бы диалогами, требующими участия человека.
  3. Фоновые задания: Регламентные задания работают без участия пользователя. В таких условиях вызов Вопрос() привел бы к краху процесса.

Решение 1: Вынос логики в обработчики команд формы

Самый правильный и архитектурно верный способ — перенести проверку из модуля объекта в клиентский контекст формы. Поскольку удаление чаще всего инициируется пользователем через форму документа или форму списка, именно там мы и должны «ловить» этот момент.

Рассмотрим по шагам, как это реализовать:

  1. Отключите стандартную команду удаления в форме (или переопределите её обработчик).
  2. Создайте свою команду формы, например, УдалитьСПроверкой.
  3. В клиентском обработчике команды вызовите серверную функцию для проверки вашего реквизита.

Пример реализации проверки на клиенте:


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

Решение 2: Использование статусов или промежуточных состояний

Если бизнес-процесс требует сложной логики проверки, не стоит завязываться на интерактив в момент записи. Вместо удаления можно использовать промежуточный статус объекта, например: Статус: На удаление.

В этом случае:

Решение 3: Валидация в ПередЗаписью модуля объекта

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


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

Итоговые рекомендации

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

← На главную