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