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