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