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