Как перехватить пометку удаления документа в управляемой форме списка для подтверждения пользователем?

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

При разработке прикладных решений на платформе 1С:Предприятие 8.3 в управляемом интерфейсе часто возникает задача запросить у пользователя подтверждение или причину пометки документа на удаление. В обычном приложении для этого существовало событие ПередУстановкойПометкиУдаления, однако в управляемых формах поведение динамических списков существенно изменилось. Разберем, с какими ограничениями платформы приходится сталкиваться и как правильно реализовать интерактивный диалог перед установкой пометки удаления.

Почему стандартные события формы не позволяют задать вопрос

Проанализируем поведение управляемой формы списка при попытке перехватить действие штатными средствами:

  1. Отсутствие интерактивного события пометки: В управляемой таблице, отображающей динамический список, платформа не предоставляет события, предшествующего изменению признака пометки удаления.
  2. Ограничение события таблицы ПередУдалением: Данный обработчик вызывается платформой исключительно при физическом удалении строк (например, записей независимого регистра сведений или строк табличной части). При интерактивном нажатии клавиши Del на строке динамического списка документов событие ПередУдалением не срабатывает.
  3. Постфактумное событие ПриИзменении: Единственное клиентское событие таблицы, возникающее при изменении данных, — это ПриИзменении. Но оно отрабатывает уже после того, как документ физически записан в базе данных с новым состоянием флага. Задать вопрос до изменения в нем невозможно.
  4. Запрет модальности на сервере: На стороне сервера (в модуле объекта или подписке на событие ПередЗаписью) мы легко можем зафиксировать изменение признака через сравнение ЭтотОбъект.ПометкаУдаления и ЭтотОбъект.Ссылка.ПометкаУдаления. Однако на сервере невозможно вызвать диалог ПоказатьВопрос и прервать выполнение серверного вызова в ожидании ответа пользователя.

Единственным надежным способом перехватить действие на клиенте остается замена стандартной команды платформы на собственную команду формы.

Пошаговая реализация переопределенной команды формы

Разберем по шагам, как настроить форму списка, чтобы перехватывать нажатие пользователем кнопки пометки удаления или клавиши Del.

  1. Отключение стандартной команды: Открываем форму списка документа. В свойствах командной панели таблицы (или контекстного меню) снимаем видимость со стандартной команды УстановитьПометкуУдаления.
  2. Создание пользовательской команды: Создаем новую команду формы, например УстановитьПометкуУдаленияПользовательская. В свойствах команды назначаем сочетание клавиш Del и выбираем стандартную пиктограмму пометки удаления.
  3. Размещение в интерфейсе: Перетаскиваем созданную команду в командную панель формы и в контекстное меню таблицы списка.
  4. Отработка множественного выделения: В обработчике команды обязательно учитываем, что пользователь может выделить как одну, так и несколько строк одновременно, поэтому необходимо обращаться к свойству ВыделенныеСтроки, а не только к ТекущиеДанные.

Посмотрим на пример клиентского кода команды формы:


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

&НаКлиенте
Процедура ПослеОтветаНаВопросПометки(Результат, МассивОбъектов) Экспорт
    
    Если Результат = КодВозвратаДиалога.Да Тогда
        УстановитьПометкуУдаленияНаСервере(МассивОбъектов);
        Элементы.Список.Обновить();
    КонецЕсли;
    
КонецПроцедуры

В серверной процедуре выполняем непосредственное изменение признака пометки. Чтобы связать клиентское действие с серверными проверками, передаем специальный признак через свойство ДополнительныеСвойства:


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

Защита от установки пометки из сторонних форм

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

Для гарантированного контроля используем проверку флага в модуле документа или общей подписке на событие ПередЗаписью:


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

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

← На главную