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