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

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

В процессе разработки и поддержки конфигураций 1С часто возникает задача синхронизации данных. Одной из самых сложных ситуаций является необходимость внесения изменений в документы или другие объекты при удалении записи из регистра сведений, особенно если удаление происходит интерактивно пользователем. На первый взгляд задача кажется простой, но она скрывает в себе риски транзакционных блокировок и потерю данных — поможет журнал изменений и восстановление удаленных объектов. В этой статье мы подробно разберем, как правильно реализовать этот механизм, избегая типичных ошибок.

Анализ проблемы и рисков

Прежде чем приступать к кодингу, проанализируем ситуацию. Когда пользователь или программа удаляет запись из регистра, 1С работает не с одной строкой, а с набором записей. Если мы попытаемся изменить документ непосредственно в момент удаления записи регистра, мы можем столкнуться с Deadlock (взаимной блокировкой) — решит задачу инструмент анализа производительности и блокировок. Это происходит потому, что запись в регистр часто сама является частью транзакции проведения документа. Попытка "развернуться" и записать документ из модуля регистра приведет к тому, что два процесса будут бесконечно ждать друг друга.

Способ 1. Использование метода пустого набора записей

Рассмотрим самый простой способ определить, что происходит полная очистка данных по определенному фильтру. В модуле набора записей регистра (или в подписке на события) мы можем проанализировать состояние объекта ЭтотОбъект. Выясним причину, по которой вызывается событие ПередЗаписью — для этого подойдёт настройка произвольных проверок и условий контроля.

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


Процедура ПередЗаписью(Отказ, Замещение)
    // Если Замещение = Истина и количество записей в наборе 0 - 
    // значит, данные по этому отбору будут полностью удалены.
    Если Замещение И ЭтотОбъект.Количество() = 0 Тогда
        // Здесь мы понимаем, что записи удаляются.
        // Однако старые данные в ЭтотОбъект уже недоступны.
    КонецЕсли;
КонецПроцедуры

Способ 2. Сравнение состояний через ДополнительныеСвойства

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

Шаг 1: В событии ПередЗаписью считываем текущие данные из базы, которые еще не успели удалиться.


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

    // Считываем то, что сейчас лежит в БД по данному отбору
    Запрос = Новый Запрос;
    Запрос.Текст = "ВЫБРАТЬ * ИЗ РегистрСведений.ИмяВашегоРегистра ГДЕ <ФильтрПоОтборуНабора>";
    // ... установка параметров из ЭтотОбъект.Отбор
    
    ТаблицаСтарыхДанных = Запрос.Выполнить().Выгрузить();
    ЭтотОбъект.ДополнительныеСвойства.Вставить("СтарыеДанные", ТаблицаСтарыхДанных);
КонецПроцедуры

Шаг 2: В событии ПриЗаписи сравниваем старые данные с новыми. Если в старых данных запись была, а в новом наборе (ЭтотОбъект) её нет — значит, произошло удаление конкретной строки.


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

Способ 3. Безопасная обработка через очередь задач

Как мы уже выяснили, изменять документы прямо внутри ПриЗаписи опасно. Вместо этого рассмотрим архитектурно верный подход: регистрацию задания. Создадим вспомогательный регистр сведений (назовем его ОчередьОбновленияДокументов).

  1. В момент удаления записи регистра (событие ПриЗаписи), вместо поиска и записи документа, мы записываем только ссылку на этот документ в наш новый регистр-очередь.
  2. Настроим РегламентноеЗадание, которое будет запускаться раз в минуту, считывать записи из ОчередьОбновленияДокументов, обрабатывать документы и очищать очередь.

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

Способ 4. Использование механизма истории данных

В современных версиях платформы (8.3.11+) для регистров сведений можно включить стандартный механизм История данных — для этого подойдёт ведение детальной истории изменений объектов. Проанализируем ситуацию: если в свойствах регистра включено логирование истории, платформа сама записывает все изменения. Мы можем программно обратиться к методам ИсторияДанных.ВыбратьВерсии(), чтобы найти факт удаления. Это избавляет от необходимости писать свои "зеркальные" регистры, но требует настройки состава хранимых данных.

Способ 5. Административный запрет интерактивного удаления

Иногда лучшим техническим решением является запрет самого действия. Если бизнес-логика подразумевает, что записи регистра должны всегда соответствовать документам, логично запретить пользователям удалять их вручную. Рассмотрим настройку прав доступа (ролей):

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

Использование подписок на события

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

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

← На главную