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