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

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

В процессе разработки на платформе 1С:Предприятие 8 часто возникает задача связать независимый регистр сведений с документом. В отличие от подчиненных регистров, которые очищаются автоматически при отмене проведения или удалении документа-регистратора, независимые регистры требуют ручного управления их жизненным циклом. Особенно остро встает вопрос, когда записи регистра должны исчезать не только при физическом удалении документа из базы, но и при простой установке пометки на удаление.

Рассмотрим детально, как реализовать этот механизм, разберем типичные ошибки и выберем наиболее оптимальный способ решения задачи.

Метод 1. Программная очистка в модуле объекта (событие ПередЗаписью)

Самый распространенный и надежный способ — прописать логику очистки непосредственно в модуле документа. Мы будем использовать событие ПередЗаписью, так как оно позволяет перехватить момент изменения состояния документа до того, как данные будут зафиксированы в базе данных.

Разберем по шагам, как это работает. Когда пользователь нажимает кнопку «Установить пометку на удаление», документ записывается с установленным флагом ПометкаУдаления = Истина. В этот момент нам нужно создать пустой набор записей регистра сведений, установить фильтр по нашему документу и записать этот пустой набор.

Посмотрим на пример кода, который можно разместить в модуле документа:


Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
    
    // Проверяем, что документ записывается в обычном режиме (не при обмене данными)
    Если ОбменДанными.Загрузка Тогда
        Возврат;
    КонецЕсли;

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

КонецПроцедуры

Проанализируем важный нюанс в условии: Если ПометкаУдаления И Не Ссылка.ПометкаУдаления Тогда. Здесь мы сравниваем текущее состояние объекта в памяти (ПометкаУдаления) с состоянием объекта, которое записано в базе (Ссылка.ПометкаУдаления). Это позволяет нам выполнять очистку только один раз — в момент непосредственного нажатия на кнопку пометки. Без этой проверки код будет срабатывать при каждом сохранении уже помеченного документа, создавая лишнюю нагрузку на сервер.

Метод 2. Использование свойства «Ведущее»

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

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

Вывод: свойство Ведущее полезно использовать как «страховку» для поддержания целостности базы, чтобы в регистре не оставалось битых ссылок на удаленные документы, но оно не заменяет программный код, если данные нужно скрыть сразу после пометки.

Метод 3. Подписки на события (современный подход)

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

  1. Создадим общий модуль (например, РаботаСРегистрамиСведенийСобытия).
  2. Создадим новый объект метаданных Подписка на событие.
  3. В качестве источника выберем нужные типы документов (или ДокументОбъект целиком).
  4. Событие выберем ПередЗаписью.
  5. В обработчик подписки перенесем логику из Метода 1.

Это позволит централизованно управлять логикой очистки регистра без редактирования каждого отдельного документа. Пример кода в общем модуле будет выглядеть аналогично, только вместо обращения к ПометкаУдаления напрямую, мы будем использовать параметр Источник:


Процедура ПередЗаписьюДокументаДляРегистра(Источник, Отказ, РежимЗаписи, РежимПроведения) Экспорт
    
    Если Источник.ОбменДанными.Загрузка Тогда
        Возврат;
    КонецЕсли;

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

Важные аспекты производительности и надежности

Рассмотрим дополнительные факторы, которые могут повлиять на работу системы:

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

Подводя итог, можно сказать, что наиболее корректным способом удаления записей независимого регистра является использование метода НаборЗаписей.Записать() в событии ПередЗаписью с обязательной проверкой факта изменения статуса пометки на удаление.

← На главную