Как программно очистить документ «Корректировка записей регистров» при перезаписи?

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

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

Разберем подробно, как устроен этот документ, почему метод Удалить() и создание нового — плохая идея, и рассмотрим правильный алгоритм полной очистки документа перед записью новых данных.

Особенности документа «Корректировка записей регистров»

Прежде чем писать код, давайте проанализируем архитектуру этого объекта. Документ КорректировкаЗаписейРегистров (в типовых конфигурациях вроде «1С:Бухгалтерия» или «1С:Комплексная Автоматизация») работает как «оболочка» для прямого доступа к записям регистров.

У него есть табличные части, такие как ТаблицаРегистровНакопления, ТаблицаРегистровБухгалтерии и т.д. Однако эти таблицы хранят не сами проводки, а лишь настройки — список регистров, по которым документ будет делать движения.

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

Типичные ошибки при очистке

Рассмотрим несколько распространенных заблуждений, с которыми сталкиваются новички.

Ошибка 1: Удаление и создание нового документа

Иногда возникает соблазн просто удалить старый документ и создать новый программно, как было предложено в одном из вариантов решения:


Если ДокКЗР <> Документы.КорректировкаЗаписейРегистров.ПустаяСсылка() Тогда
    ДокКЗР.Удалить(); // Или получить объект и удалить
КонецЕсли;
СОЗДАТЬНОВЫЙДОК();

Почему так делать нельзя:

  1. Битые ссылки: Если на вашу корректировку ссылаются другие объекты (например, ручные операции или присоединенные файлы), ссылки станут «битыми» (Объект не найден), так как новый документ получит новый уникальный идентификатор (GUID).
  2. История изменений: Вы потеряете историю версий объекта и записи в Журнале регистрации, относящиеся к старому документу.

Ошибка 2: «Жесткое» кодирование имен регистров

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


// Плохой пример:
СтрокаТаблица = Объект.ТаблицаРегистровБухгалтерии.Добавить();
СтрокаТаблица.Имя = "Хозрасчетный"; // Hardcode

Этот подход делает код неуниверсальным. Если в будущем вам понадобится корректировать регистр накопления, придется переписывать программный код. Мы должны стремиться к универсальным алгоритмам.

Правильный алгоритм очистки документа

Чтобы документ стал «кристально чистым» перед новой записью, нам необходимо выполнить два действия:

  1. Очистить сами движения (записи в регистрах) и записать пустые наборы.
  2. Очистить табличные части самого документа (список используемых регистров).

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


Процедура ОчиститьКорректировку(СсылкаНаДокумент)
    
    // Получаем объект для редактирования
    ОбъектДокумент = СсылкаНаДокумент.ПолучитьОбъект();
    
    // 1. Очищаем движения по регистрам бухгалтерии
    // Аналогично можно сделать для регистров накопления и сведений
    
    Для Каждого СтрокаТЧ Из ОбъектДокумент.ТаблицаРегистровБухгалтерии Цикл
        
        ИмяРегистра = СтрокаТЧ.Имя;
        
        // Получаем набор записей через коллекцию Движения
        НаборЗаписей = ОбъектДокумент.Движения[ИмяРегистра];
        
        // Очищаем набор и записываем изменения в базу
        НаборЗаписей.Очистить();
        НаборЗаписей.Записать();
        
    КонецЦикла;
    
    // 2. Теперь, когда движения пусты, можно очистить саму таблицу настроек документа
    ОбъектДокумент.ТаблицаРегистровБухгалтерии.Очистить();
    
    // 3. Записываем сам пустой документ
    ОбъектДокумент.Записать();
    
КонецПроцедуры

Обратите внимание на важный момент: метод НаборЗаписей.Записать() внутри цикла обязателен. Если вы просто очистите коллекцию, но не запишете её, а затем очистите табличную часть документа и запишете документ, платформа может не понять, что старые движения нужно удалить, так как ссылка на регистр уже удалена из табличной части.

Альтернативный вариант: Использование свойства «Записывать»

В платформе 1С:Предприятие 8 есть свойство Движения.<Имя>.Записывать. Если установить его в значение Истина, то при записи самого документа набор записей будет записан автоматически. Однако для документа «Корректировка записей регистров» надежнее управлять записью явно, как в примере выше.

Если же вы хотите использовать более компактный код, можно попробовать следующий подход:


Для Каждого СтрокаТЧ Из ОбъектДокумент.ТаблицаРегистровБухгалтерии Цикл
    Движения = ОбъектДокумент.Движения[СтрокаТЧ.Имя]; 
    Движения.Очистить();
    Движения.Записать(); // Явная запись пустого набора
КонецЦикла;

ОбъектДокумент.ТаблицаРегистровБухгалтерии.Очистить();
ОбъектДокумент.Записать();

Использование стандартных библиотек (БСП)

Если ваша конфигурация построена на базе БСП (Библиотека Стандартных Подсистем), то в ней часто присутствуют готовые процедуры для работы с движениями. Давайте посмотрим на полезный метод, который упоминался в обсуждении.

В общих модулях, связанных с обменом данными или удалением объектов, часто встречается процедура вида УдалитьДвиженияУДокумента. Например:


// Пример вызова из БСП (название модуля может отличаться в разных версиях)
ОбменДаннымиСервер.УдалитьДвиженияУДокумента(ДокОбъект);

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

Очистка через пометку удаления

Если ваша задача — просто «выключить» документ, чтобы он перестал влиять на учет, но не удалять его физически и не перезаполнять прямо сейчас, используйте установку пометки удаления.

ДокОбъект.УстановитьПометкуУдаления(Истина);

При выполнении этого метода платформа автоматически вызывает обработчик ОбработкаУдаленияПроведения (или системный механизм), который очищает все движения документа (устанавливает свойство Активность = Ложь или удаляет записи в зависимости от режима проведения).

Заключение

Подведем итог. Чтобы правильно перезаписать документ «Корректировка записей регистров»:

  1. Никогда не удаляйте сам документ, если планируете заполнить его же заново — это нарушает целостность ссылок.
  2. Сначала очищайте движения (записи в регистрах) и явно записывайте пустые наборы.
  3. Только после очистки движений очищайте табличные части самого документа.
  4. Избегайте указания имен регистров в коде явно (в кавычках), используйте перебор коллекций или метаданных для универсальности.
← На главную