Удаляем движения одного документа из регистра накопления: от отмены проведения до кода и SQL

· 9 мин

Содержание

Чтобы очистить регистр накопления по регистратору, в 1С 8.3 достаточно записать пустой набор записей с отбором по этому документу: НаборЗаписей.Отбор.Регистратор.Установить(Документ) и затем НаборЗаписей.Записать(). Без программирования тот же результат даёт отмена проведения документа или ручная корректировка его движений.

Типичная ситуация: отчёт по складу показывает остаток, которого нет, а в расшифровке висит документ с движениями «из ниоткуда». Или после неудачного обмена в регистре остались записи с регистратором <Объект не найден>. Убрать их нужно точечно, не трогая остальные документы. Ниже — способы от безопасного к радикальному, порядок важен.

Когда регистр накопления чистят по регистратору

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

Когда она действительно нужна:

  • 🧾 документ проведён с ошибкой, его движения ломают остатки, а перепровести его пока нельзя (закрыт период, нет данных);
  • 🔗 регистратор удалён, а записи остались: в отчётах видно <Объект не найден> и строку вида <Объект не найден> (123:a1b2c3...);
  • 🔄 после загрузки из другой базы движения задвоились: документ провели дважды или загрузили вместе с движениями и провели ещё раз;
  • 🧪 нужно убрать движения одного документа из одного регистра, оставив остальные (например, при отладке нового регистра).

Если документ нормальный и просто проведён не так — чистить регистр не нужно. Исправьте документ и проведите заново: платформа сама заменит старые движения новыми.

Какой способ выбрать: сравнение методов

СпособКогда подходитЧто затрагиваетРиски
Отмена проведенияДокумент существует, его движения не нужны совсемВсе регистры документаМинимальные: документ можно провести снова
Ручная корректировка движенийНужно удалить или поправить часть строк в одном регистреВыбранные строкиДвижения перестают пересчитываться при перепроведении, пока флаг включён
Запись пустого набора кодомНужен один регистр, много документов или битый регистраторТолько указанный регистрФлаг «Проведён» остаётся, данные расходятся с документом
Тестирование и исправлениеМассово висят записи удалённых документовВсе битые ссылки базыДействует сразу на всю базу
DELETE в SQLПлатформа не открывает базу или набор не записываетсяТаблица регистраИтоги и кэш платформы не обновляются, поддержки нет

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

Очистка регистра без программирования

Отмена проведения документа

Самый чистый вариант. Откройте документ и нажмите в командной панели Ещё → Отмена проведения. В списке документов можно выделить сразу несколько строк и выполнить ту же команду из меню Ещё.

Платформа удалит движения документа во всех регистрах, где он регистратор, и пересчитает итоги. Сам документ останется, его можно поправить и провести снова.

Если период закрыт датой запрета изменения, программа не даст отменить проведение. Дату запрета временно снимает пользователь с правами администратора. Верните её сразу после правки.

Ручная корректировка движений в БП 3.0

В «Бухгалтерии предприятия» есть штатный способ убрать строки только из одного регистра:

  1. Откройте документ и нажмите кнопку Дт/Кт (показать проводки и другие движения документа).
  2. Установите флажок «Ручная корректировка (разрешает редактирование движений документа)».
  3. Перейдите на закладку нужного регистра накопления.
  4. Выделите строки и удалите их. Если удаляете все строки закладки, регистр по этому документу будет очищен.
  5. Нажмите Записать и закрыть.

Пока флажок ручной корректировки стоит, перепроведение не перезапишет ваши правки. Снимете флажок — при следующем проведении документ сформирует движения заново по своему алгоритму.

Удалённый документ: Тестирование и исправление

Если регистратора больше нет, отменять проведение нечего. Тогда помогает режим конфигуратора Администрирование → Тестирование и исправление с галкой «Проверка ссылочной целостности информационной базы». Для битых ссылок выберите действие «Удалять ссылки на объекты»: записи регистров с удалённым регистратором будут удалены.

Режим работает в монопольном режиме и обрабатывает всю базу сразу, а не один документ. Перед запуском сделайте выгрузку в .dt или резервную копию SQL. На большой базе проверка идёт часами — планируйте её на нерабочее время.

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

Код понадобится, когда нужно очистить один регистр, обработать список документов или аккуратно убрать записи битого регистратора без полного тестирования базы. Код запускают во внешней обработке через Файл → Открыть под пользователем с полными правами.

Один регистр — один документ

Основа всех вариантов — пустой набор записей с отбором по регистратору:

&НаСервере
Процедура ОчиститьРегистрНаСервере(Регистратор, ИмяРегистра)

	НаборЗаписей = РегистрыНакопления[ИмяРегистра].СоздатьНаборЗаписей();
	НаборЗаписей.Отбор.Регистратор.Установить(Регистратор);
	// пустой набор с замещением удаляет все записи этого регистратора
	НаборЗаписей.ОбменДанными.Загрузка = Истина;
	НаборЗаписей.Записать(Истина);

КонецПроцедуры

Что здесь происходит:

  • Записать(Истина) — запись с замещением: всё, что было по отбору, удаляется и заменяется содержимым набора. Набор пустой, значит, записей не остаётся.
  • ОбменДанными.Загрузка = Истина отключает обработчики модуля набора записей и подписки на события. Итоги регистра платформа при этом всё равно пересчитает.
  • Регистр передаётся строкой, например "ТоварыНаСкладах". Имя смотрите в конфигураторе, в ветке «Регистры накопления».

Все регистры накопления одного документа

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

&НаСервере
Процедура ОчиститьВсеРегистрыНакопления(Регистратор)

	МетаДокумента = Регистратор.Метаданные();

	НачатьТранзакцию();
	Попытка
		Для Каждого МетаРегистр Из Метаданные.РегистрыНакопления Цикл
			Если Не МетаДокумента.Движения.Содержит(МетаРегистр) Тогда
				Продолжить;
			КонецЕсли;
			НаборЗаписей = РегистрыНакопления[МетаРегистр.Имя].СоздатьНаборЗаписей();
			НаборЗаписей.Отбор.Регистратор.Установить(Регистратор);
			НаборЗаписей.ОбменДанными.Загрузка = Истина;
			НаборЗаписей.Записать(Истина);
		КонецЦикла;
		ЗафиксироватьТранзакцию();
	Исключение
		ОтменитьТранзакцию();
		ВызватьИсключение;
	КонецПопытки;

КонецПроцедуры

Транзакция нужна, чтобы при ошибке на третьем регистре первые два не остались очищенными.

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

Регистратор удалён: находим «висящие» записи

У записей удалённого документа ссылка в поле Регистратор формально жива, а сам объект в базе отсутствует. Найти такие ссылки помогает разыменование: у несуществующего документа реквизит Дата вернёт NULL.

&НаСервере
Процедура ОчиститьБитыеРегистраторы(ИмяРегистра)

	Запрос = Новый Запрос;
	Запрос.Текст = СтрЗаменить(
		"ВЫБРАТЬ РАЗЛИЧНЫЕ
		|	Т.Регистратор КАК Регистратор
		|ИЗ
		|	РегистрНакопления.%Имя% КАК Т
		|ГДЕ
		|	Т.Регистратор.Дата ЕСТЬ NULL", "%Имя%", ИмяРегистра);

	Выборка = Запрос.Выполнить().Выбрать();
	Пока Выборка.Следующий() Цикл
		НаборЗаписей = РегистрыНакопления[ИмяРегистра].СоздатьНаборЗаписей();
		НаборЗаписей.Отбор.Регистратор.Установить(Выборка.Регистратор);
		НаборЗаписей.ОбменДанными.Загрузка = Истина;
		НаборЗаписей.Записать(Истина);
	КонецЦикла;

КонецПроцедуры

Сначала выполните только запрос и посмотрите, сколько строк он возвращает. Если число неожиданно большое, остановитесь и выясните, откуда взялись битые ссылки: возможно, документы удалили по ошибке и их лучше восстановить из копии.

Перед очисткой сохраните записи в файл. Хватит выгрузить результат запроса ВЫБРАТЬ * ИЗ РегистрНакопления.Имя ГДЕ Регистратор = &Ссылка в табличный документ и записать его в .xlsx. Если что-то пойдёт не так, будет из чего восстановить картину.

Удаление записей регистра через SQL

Прямой DELETE в базе MS SQL или PostgreSQL оправдан в редких случаях: база не открывается из-за повреждённых записей, или запись набора падает с ошибкой платформы, которую не устраняет тестирование и исправление. Фирма 1С такой способ не поддерживает, ответственность целиком на вас.

Как найти таблицу и поля

Имена таблиц в СУБД обезличены: регистр накопления хранится в таблице вида _AccumRg1234, а итоги — в отдельной таблице итогов. Соответствие показывает функция ПолучитьСтруктуруХраненияБазыДанных(): выполните её во внешней обработке и найдите в результате метаданные своего регистра.

Ссылка на регистратор лежит в поле _RecorderRRef (двоичный идентификатор). Если в регистр пишут документы нескольких видов, рядом есть поле _RecorderTRef с кодом типа документа.

Двоичный идентификатор документа проще всего взять из таблицы самого документа (_Document123) по номеру, чем пересчитывать из GUID: порядок байтов там другой.

Безопасный порядок действий

-- 1. Сколько строк удалим
SELECT COUNT(*)
FROM _AccumRg1234
WHERE _RecorderRRef = 0x9F3A00155D01020311EE5B2C8A7D4E10;

-- 2. Удаление в транзакции
BEGIN TRAN;
DELETE FROM _AccumRg1234
WHERE _RecorderRRef = 0x9F3A00155D01020311EE5B2C8A7D4E10;
-- сверьте число удалённых строк с результатом шага 1
COMMIT;   -- или ROLLBACK, если число не совпало

Идентификатор в примере условный, подставьте свой. В PostgreSQL имена таблиц и полей пишутся в нижнем регистре (_accumrg1234, _recorderrref), а транзакцию открывает BEGIN.

Работайте при отключённых пользователях: завершение сеансов оборвёт их работу, поэтому делайте это вечером или в выходной. Таблицу итогов SQL-запрос не обновит, после него обязателен пересчёт итогов из следующего раздела.

Что сделать после очистки

Очистка регистра — половина работы. Вторая половина — убедиться, что остатки и обороты сходятся.

Пересчёт итогов. Нужен обязательно после SQL и желателен после массовой очистки кодом. Варианты:

  • конфигуратор: Администрирование → Тестирование и исправление, флажок «Пересчёт итогов»;
  • код: РегистрыНакопления.ТоварыНаСкладах.ПересчитатьИтоги();
  • в типовых конфигурациях на БСП — обработка «Управление итогами и агрегатами» в разделе Администрирование → Обслуживание.

Проверка документа. Если вы очистили движения кодом или через SQL, у документа по-прежнему стоит признак «Проведён». Пользователь увидит зелёную галку, а движений не будет. Решите сразу, что с ним делать: перепровести, отменить проведение или пометить на удаление.

Сверка отчётом. Сформируйте отчёт по остаткам регистра за период документа и сравните с ожиданием. В БП это, например, оборотно-сальдовая ведомость по счёту, если регистр связан с учётом на счетах.

Последовательности. В конфигурациях с партионным учётом и последовательностями (УТ, КА, ERP) после правки движений задним числом граница последовательности сдвигается. Восстановите её штатной обработкой проведения по последовательности.

Чек-лист перед очисткой регистра

Перед удалением движений
Выполнено: 0 / 6

Ошибки, из-за которых очистка создаёт новые проблемы

  • ❌ Очистили регистр, а документ потом перепровели. Движения вернулись. Если нужно, чтобы документ больше не двигал регистр, исправьте сам документ или отмените его проведение.
  • ❌ Передали не тот регистратор. В отбор попала ссылка на другой документ, например из соседней строки списка, и очищены чужие движения. Перед записью выведите в сообщение представление регистратора и количество его записей, а запускайте обработку сначала на копии базы.
  • ❌ Чистили регистр остатков, а связанные регистры оставили. Документ «Реализация» в УТ двигает и товары, и взаиморасчёты, и продажи. Очистили один — отчёты по другим перестали сходиться.
  • ❌ Очистили движения в закрытом периоде. Себестоимость, закрытие месяца и сданная отчётность уже посчитаны по старым данным. После правки нужно повторить закрытие месяца или сознательно оставить расхождение.
  • ❌ Удалили строки SQL-запросом и не пересчитали итоги. Отчёт по остаткам на текущую дату берёт данные из таблицы итогов и показывает старую цифру, а отчёт за прошлый период — новую.

Частые вопросы

Можно ли очистить регистр накопления по отбору, например по складу или номенклатуре?
Нет. Набор записей регистра накопления принимает отбор только по регистратору. Чтобы убрать записи по складу, придётся найти все документы с этим складом и чистить их движения по одному.
Почему после очистки кодом в отчётах всё равно старые остатки?
Чаще всего выключено использование итогов или они устарели после работы в SQL. Выполните пересчёт итогов регистра и переформируйте отчёт.
Как очистить регистр по регистратору в файловой базе?
Так же, как в клиент-серверной: отмена проведения, ручная корректировка или код с набором записей. Вариант с SQL для файловой базы недоступен, её таблицы не открываются внешними средствами.
Нужен ли монопольный режим для очистки кодом?
Нет. Запись набора блокирует только записи этого регистра по указанному регистратору. Монопольный режим требуется для тестирования и исправления.
Можно ли вернуть удалённые движения?
Только перепроведением документа или из резервной копии. Журнал регистрации значения удалённых строк не хранит, поэтому выгружайте их в файл заранее.