Разработка и Конфигурация · 11 мин
Как отловить пометку на удаление в 1С
Как в 1С отловить пометку на удаление: подписки на события, обработчики ПередЗаписью и ПриЗаписи, запросы по помеченным объектам, контроль ссылочной целостности.
Пометка на удаление в 1С — это не отдельное событие, а обычная запись объекта с изменённым значением свойства ПометкаУдаления. Поэтому «отловить» её можно несколькими способами: через подписки на события записи, через обработчики в модуле объекта, через запросы к данным и через регламентные механизмы контроля. Выбор зависит от задачи: нужно ли реагировать в момент действия пользователя, запретить пометку, журналировать её или просто найти помеченные объекты.
Важно понимать механику платформы. Когда пользователь нажимает «Пометить на удаление», система открывает объект, устанавливает флаг пометки и записывает его. При этом срабатывают те же события, что и при обычной записи: ПередЗаписью, ПриЗаписи, подписки на события. Значит, перехват сводится к сравнению нового значения пометки со значением, хранящимся в базе.
Ниже разобраны рабочие приёмы: код перехвата в модуле объекта и в подписке, запросы для поиска помеченных элементов, журналирование через регистр сведений, а также ограничения и типичные ошибки, из-за которых перехват «не срабатывает».
Как устроена пометка на удаление в механизме платформы
Флаг пометки хранится как системное свойство объекта и доступен во встроенном языке через Объект.ПометкаУдаления. Пометка не удаляет данные физически: запись остаётся в таблицах, на неё сохраняются ссылки из других объектов. Физическое удаление выполняет только обработка «Удаление помеченных объектов», и то лишь при отсутствии ссылок.
При установке или снятии пометки платформа вызывает цепочку событий записи: ОбработкаЗаполнения не вызывается, а вот ПередЗаписью, ПриЗаписи и подписки на события записи отрабатывают в полном объёме. Именно в этих точках и можно сравнить «старое» и «новое» состояние флага.
Перехват в модуле объекта через ПередЗаписью
Самый прямой способ — добавить код в обработчик ПередЗаписью модуля объекта справочника или документа. Проблема в том, что в момент записи объект уже содержит новое значение пометки, а старое нужно получить из базы запросом. Для этого сравнивают ПометкаУдаления текущего объекта с пометкой у ссылки.
Процедура ПередЗаписью(Отказ)
Если ОбменДанными.Загрузка Тогда
Возврат;
КонецЕсли;
Если Не Ссылка.Пустая() Тогда
ПометкаВБазе = Ссылка.ПометкаУдаления;
Если ПометкаВБазе <> ПометкаУдаления Тогда
Если ПометкаУдаления Тогда
// Объект помечают на удаление
ЗаписьЖурналаРегистрации("ПометкаНаУдаление",
УровеньЖурналаРегистрации.Информация, , Ссылка,
"Установлена пометка на удаление");
Иначе
// С пометки снимают
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Обращение Ссылка.ПометкаУдаления выполняет неявный запрос к базе и возвращает значение, которое хранится там до записи. Это стандартный приём определения факта изменения флага. Для нового объекта (ссылка пустая) сравнение не имеет смысла — пометка у него по определению новая.
Подписка на событие для всех объектов сразу
Если отслеживать пометку нужно по многим видам объектов, редактировать каждый модуль объекта неудобно и опасно для обновления конфигурации. Правильное решение — подписка на событие: в конфигураторе создаётся объект «Подписка на событие» с событием ПередЗаписью или ПриЗаписи, а в источнике перечисляются нужные типы (справочники, документы, планы счетов и т.д.).
Обработчик подписки размещают в общем модуле с признаками «Сервер» и «Вызов сервера». Сигнатура аналогична обработчику объекта — источник передаётся параметром. Внутри используют тот же приём сравнения с Источник.Ссылка.ПометкаУдаления. Такой подход централизует логику: один обработчик обслуживает всю конфигурацию.
Процедура КонтрольПометкиУдаленияПередЗаписью(Источник, Отказ) Экспорт
Если Источник.ОбменДанными.Загрузка Тогда
Возврат;
КонецЕсли;
Если Источник.ЭтоНовый() Тогда
Возврат;
КонецЕсли;
ПометкаВБазе = Источник.Ссылка.ПометкаУдаления;
Если ПометкаВБазе = Источник.ПометкаУдаления Тогда
Возврат; // флаг не менялся
КонецЕсли;
// реакция на изменение пометки
КонецПроцедуры
- 1Создайте общий модуль с флагами Сервер и Вызов сервера
- 2Добавьте экспортную процедуру обработчика с параметрами (Источник, Отказ)
- 3Создайте подписку на событие, укажите событие ПередЗаписью и общий модуль
- 4В свойстве Источник отметьте нужные типы объектов
- 5Проверьте: пометьте объект в пользовательском режиме и убедитесь, что обработчик сработал (например, по записи в журнале регистрации)
Запрет и контроль: как не дать пометить объект
Частая задача — не просто отловить пометку, а запретить её по условию: например, нельзя помечать проведённые документы или элементы, на которые есть ссылки. Для этого в обработчике при обнаружении установки пометки проверяют условие и при его нарушении устанавливают Отказ = Истина и выводят сообщение пользователю.
Дополнительно доступ контролируют правами: роль может запрещать интерактивную пометку на удаление для отдельных видов объектов. Это надёжнее кода, потому что право действует независимо от обхода обработчиков через программную запись. Оптимальная схема — сочетание прав (грубый контур) и проверок в подписке (тонкие бизнес-условия).
Как выбрать способ контроля
Как найти помеченные объекты запросом
Для разового анализа помеченных данных запрос — самый быстрый инструмент. Условие по системному полю работает в любой объектной таблице:
ВЫБРАТЬ
Номенклатура.Ссылка,
Номенклатура.Код,
Номенклатура.Наименование
ИЗ
Справочник.Номенклатура КАК Номенклатура
ГДЕ
Номенклатура.ПометкаУдаления
В типовых конфигурациях есть штатная обработка «Поиск и удаление помеченных объектов» (в разделе администрирования). Она показывает помеченные объекты и места их использования. Для регулярного контроля удобно сделать собственный отчёт на СКД, который группирует помеченные объекты по видам и датам изменения.
Журналирование факта пометки для аудита
Журнал регистрации фиксирует изменение данных, но фильтровать в нём именно установку пометки неудобно. Для аудита лучше писать факт в собственный регистр сведений: дата, пользователь, ссылка, действие (установка/снятие). Записывать такой регистр следует в событии ПриЗаписи или в транзакции записи, чтобы не зафиксировать пометку, которая потом отменена отказом.
Учитывайте производительность: обращение к Ссылка.ПометкаУдаления в подписке — это лишний запрос на каждую запись объекта. На высоконагруженных документах с массовой записью это заметно. Оптимизация — получать старое значение одним запросом пакетно, если запись идёт наборами, либо ограничивать подписку только критичными типами объектов.
Проверка результата и границы самостоятельной работы
После внедрения перехвата проверьте три сценария: интерактивная пометка пользователем, программная установка пометки из обработки и пометка при обмене данными. В каждом случае убедитесь, что реакция соответствует ожиданиям: событие зафиксировано, запрет сработал, обмен не сломан. Тестировать следует на копии базы.
Самостоятельно безопасно делать: запросы по помеченным объектам, настройку прав, подписки с журналированием. К доработкам, отменяющим запись (Отказ в подписках на критичных документах), стоит привлекать разработчика, знающего прикладную логику конфигурации: ошибка в таком обработчике блокирует запись объектов для всех пользователей.
Как проверить результат
Обработчик сработал, событие зафиксировано или показан запрет
Ничего не происходит — проверьте источник подписки и флаги общего модуля
Обмен проходит без ошибок
Обмен падает — вероятно, нет проверки ОбменДанными.Загрузка
Пользователь видит сообщение, объект остаётся непомеченным
Объект помечается несмотря на запрет — Отказ установлен не в том событии
Частые вопросы
Почему подписка на событие не срабатывает при пометке?
Чаще всего не выбран тип объекта в свойстве «Источник» подписки, общий модуль не имеет флагов «Сервер» и «Вызов сервера», либо запись идёт в режиме загрузки обмена данными. Также проверьте, что обработчик подписки объявлен с ключевым словом Экспорт.
Можно ли отловить пометку без изменения конфигурации?
Полноценно — нет. Без доработки доступны только периодический анализ: запросы по полю ПометкаУдаления, штатная обработка поиска помеченных объектов и просмотр журнала регистрации по событиям изменения данных. Реагировать в момент пометки может только код в обработчиках событий.
Как узнать, кто и когда пометил объект на удаление?
Штатно — через журнал регистрации: отфильтруйте события изменения данных по конкретному объекту, там видны пользователь и время. Если нужен удобный постоянный аудит, добавьте запись в собственный регистр сведений из подписки на событие записи.
Срабатывают ли обработчики при снятии пометки?
Да, снятие пометки — та же запись объекта с изменённым флагом, поэтому ПередЗаписью и ПриЗаписи вызываются. В коде различайте направление изменения: если новое значение ПометкаУдаления ложно, а в базе истина — это снятие пометки.
Можно ли запретить пометку только для проведённых документов?
Да. В подписке ПередЗаписью при обнаружении установки пометки проверьте Источник.Проведен, и если документ проведён, установите Отказ = Истина с сообщением пользователю. Учтите, что пометка проведённого документа штатно требует отмены проведения, поэтому дополнительно контролируйте и событие отмены проведения.
Что важно запомнить
Пометка на удаление — это запись объекта, поэтому перехватывается в ПередЗаписью/ПриЗаписи или подпиской на событие через сравнение со значением в базе. Для запрета используйте Отказ в ПередЗаписью и права, для аудита — свой регистр сведений, для поиска — запросы по полю ПометкаУдаления. Всегда проверяйте ОбменДанными.Загрузка и тестируйте на копии базы.