Как удалить документы в РИБ, сохранив их движения в регистрах

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

В процессе эксплуатации распределенных информационных баз (РИБ) системные администраторы и разработчики часто сталкиваются с проблемой лавинообразного роста объема данных в периферийных узлах. Часто возникает ситуация, когда детальная информация о первичном документе (его реквизиты, печатные формы, авторство) в подчиненной базе не требуется, однако сами итоги — движения по регистрам накопления, бухгалтерии или сведений — критически необходимы для формирования отчетов и ведения учета на местах. Разберем детально, как реализовать механизм удаления документов-регистраторов с сохранением их «следа» в базе данных.

Понимание архитектуры хранения данных в 1С

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

Способ 1: Непосредственное удаление объекта

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

Если в конфигураторе для документа установлено значение «Не удалять автоматически», то при выполнении программного кода записи в регистрах останутся нетронутыми. Проанализируем пример кода:


// Выбираем ссылку на документ, который нужно удалить
ОбъектДокумента = СсылкаНаДокумент.ПолучитьОбъект();

// Непосредственное удаление без проверок и очистки движений
ОбъектДокумента.Удалить();

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

Способ 2: Перепривязка движений на «Технический регистратор»

Этот метод считается наиболее правильным и «гуманным» по отношению к системе. Вместо того чтобы оставлять в поле Регистратор битую ссылку <Объект не найден>, мы перенаправляем все движения на один специально созданный документ (например, КорректировкаЗаписейРегистров или ОперацияБух).

Разберем по шагам, как это реализовать:

  1. Создаем в базе один экземпляр документа КорректировкаЗаписейРегистров (или аналогичного).
  2. Для каждого документа, подлежащего удалению, считываем его наборы записей по всем регистрам.
  3. Меняем в наборе записей значение поля Регистратор на наш новый технический документ.
  4. Записываем набор, после чего удаляем исходный документ.

Рассмотрим пример реализации на языке 1С:


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

Особенности работы в РИБ

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

Во-первых, перед удалением документов в периферии их нужно исключить из состава обмена для данного узла. Это делается через работу с планами обмена:

ПланыОбмена.УдалитьРегистрациюИзменений(УзелРИБ, СсылкаНаДокумент);

Во-вторых, в правилах синхронизации (или в коде модуля плана обмена) следует прописать условие, запрещающее выгрузку удаления этих типов документов из периферийной базы в центральную. В противном случае первая же синхронизация уничтожит данные во всей сети.

Технические риски и последствия

Выясним, с какими проблемами вы можете столкнуться при использовании данных методов:

  1. Битые ссылки (Object not found): Если вы выбрали путь простого удаления (Способ 1), то во всех отчетах, где выводится поле «Регистратор», пользователь увидит некрасивую надпись <Объект не найден...>. Это может мешать расшифровке отчетов.
  2. Тестирование и исправление (ТиИ): Стандартная процедура «Проверка ссылочной целостности» при включенном режиме удаления битых ссылок уничтожит ваши движения. Вам придется навсегда отказаться от этого пункта в ТиИ или очень осторожно настраивать исключения.
  3. Производительность SQL: На уровне базы данных отсутствие физических связей между таблицами итогов и таблицами документов может привести к неоптимальной работе планов запросов SQL-сервера. Индексы по полю Регистратор будут содержать ссылки на несуществующие записи, что в редких случаях замедляет построение виртуальных таблиц «Остатки и обороты».
  4. Реструктуризация: При обновлении конфигурации, если меняется структура регистра, платформа может выполнять пересчет итогов. В некоторых версиях платформы это может привести к потере записей с «битыми» регистраторами.

Альтернативный подход: Фильтрация при регистрации

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

В типовых конфигурациях на платформе 8.3 это реализуется через Правила регистрации объектов. Мы можем указать системе, что для подчиненного узла регистрация изменений документа не требуется, при этом регистрация движений этого документа по регистрам остается активной. В результате в периферийной базе появятся движения, у которых в поле регистратор будет ссылка, но самого объекта (файла документа) существовать не будет. Это дает тот же эффект экономии места, но более штатным способом.

Выводы и рекомендации

Подводя итог, можно сказать: технически задача «удалить документ, оставив движения» решаема.

Для разовой очистки старых данных лучше всего подходит Способ 2 (Перепривязка на один документ-корректировку). Он сохраняет целостность базы для процедур ТиИ и позволяет отчетам работать корректно, ссылаясь на один существующий «технический» документ.

Если же задача стоит на постоянной основе, рекомендуем пересмотреть архитектуру обмена и ограничить миграцию самих объектов документов через настройки планов обмена, оставляя только необходимые наборы записей. Всегда делайте резервную копию базы перед массовым удалением объектов, так как операции с непосредственным удалением (метод Удалить()) необратимы.

← На главную