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