Почему помеченный на удаление или непроведенный документ создает движения по регистрам в 1С и как это исправить?

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

В процессе администрирования и сопровождения крупных информационных баз на платформе 1С:Предприятие 8.3 (особенно в тяжелых конфигурациях класса ERP, таких как 1С:ERP Управление предприятием 2.2 / 2.5 или 1С:Комплексная автоматизация) специалисты иногда сталкиваются с парадоксальной ситуацией. Документ в системе наглядно помечен на удаление или распроведен (его статус в интерфейсе — «Не проведен»), однако в связанных отчетах продолжают фигурировать его движения по регистрам накопления, сведений или бухгалтерии.

Такая ситуация вводит в ступор пользователей и может приводить к серьезным искажениям в финансовой отчетности, расчетах себестоимости и взаиморасчетах с контрагентами. В этой статье мы подробно разберем, почему возникает эта проблема, как быстро локализовать все «проблемные» документы в базе данных и какими методами можно навсегда устранить фантомные записи в регистрах.

Почему возникают движения у непроведенных документов? Разбор причин

Проблема не является случайным сбоем файловой системы — она имеет вполне конкретные архитектурные причины, связанные с особенностями параллельной работы и программной логикой конфигураций 1С. Рассмотрим основные из них:

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

Шаг 1. Как быстро найти все проблемные документы в базе данных

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

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


ВыборкаРегистров = Метаданные.РегистрыНакопления;
Запрос = Новый Запрос;
ТекстЗапроса = "";
ПервыйРегистр = Истина;

Для Каждого МетаданныеРегистра Из ВыборкаРегистров Цикл
    
    // Формируем динамический запрос по каждому регистру накопления
    ШаблонЗапроса = "
    |ВЫБРАТЬ РАЗЛИЧНЫЕ
    |	""" + МетаданныеРегистра.Имя + """ КАК ИмяРегистра,
    |	ТаблицаРегистра.Регистратор КАК ДокументСсылка,
    |	ТаблицаРегистра.Регистратор.Проведен КАК СтатусПроведен,
    |	ТаблицаРегистра.Регистратор.ПометкаУдаления КАК СтатусПометка
    |ИЗ
    |	РегистрНакопления." + МетаданныеРегистра.Имя + " КАК ТаблицаРегистра
    |ГДЕ
    |	(ТаблицаРегистра.Регистратор.Проведен = ЛОЖЬ 
    |	ИЛИ ТаблицаРегистра.Регистратор.ПометкаУдаления = ИСТИНА)";
    
    Если Не ПервыйРегистр Тогда
        ТекстЗапроса = ТекстЗапроса + "
        |ОБЪЕДИНИТЬ ВСЕ
        |";
    КонецЕсли;
    
    ТекстЗапроса = ТекстЗапроса + ШаблонЗапроса;
    ПервыйРегистр = Ложь;
    
КонецЦикла;

Запрос.Текст = ТекстЗапроса;
РезультатТаблица = Запрос.Выполнить().Выгрузить();

// Выводим результат в окно сообщений для анализа
Для Каждого СтрокаРезультата Из РезультатТаблица Цикл
    Сообщить("В регистре '" + СтрокаРезультата.ИмяРегистра 
        + "' найдены лишние движения по документу: " + СтрокаРезультата.DoкументСсылка);
КонецЦикла;

Этот простой и эффективный скрипт обходит все метаданные регистров накопления, собирает один большой пакетный запрос и моментально выводит список документов-нарушителей, у которых признак Проведен равен Ложь либо признак ПометкаУдаления равен Истина, но при этом записи в таблице регистра существуют физически.

Шаг 2. Практические методы исправления зависших движений

В зависимости от ограничений вашей базы (закрытый период, объемы данных, наличие административных прав) выберите один из следующих трех вариантов устранения проблемы:

Вариант 1. Классический ручной метод (через интерфейс)

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

  1. Найдите нужный документ в списке и снимите с него пометку на удаление (если она установлена).
  2. Проведите документ штатными средствами. При этом система заново сформирует корректные движения.
  3. Отмените проведение документа (распроводка). В этот момент платформа инициирует стандартный механизм очистки всех наборов записей по всем связанным регистрам.
  4. При необходимости снова пометьте документ на удаление.

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

Вариант 2. Программное зануление движений (для закрытых периодов)

Если период закрыт, интерактивно перепроводить документы нельзя. В этом случае мы можем применить программную очистку движений напрямую, записывая пустые наборы записей по конкретному документу в режиме загрузки данных. Это гарантирует, что мы не нарушим последовательности и не откроем закрытый период для перерасчетов.

Рассмотрим программный код, который выполняет эту процедуру для выбранного документа по всем регистрам:


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

Использование свойства ОбменДанными.Загрузка = Истина является ключевым в данном случае. Оно позволяет записать пустой набор данных напрямую в СУБД, игнорируя любые подписки на события и защитные механизмы конфигурации, которые могли бы заблокировать запись в закрытом периоде.

Вариант 3. Использование универсальных обработок

Для системных администраторов и программистов отличным решением является использование типовой обработки «Групповое изменение реквизитов» или специализированных инструментов с порталов технической поддержки. Такие обработки позволяют выбрать все документы по результатам нашего запроса из Шага 1 и массово выполнить очистку движений по регистрам без непосредственного изменения метаданных документов.

Меры профилактики: Как предотвратить проблему в будущем?

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

  1. Обновление конфигурации. В современных редакциях (например, в актуальных релизах ERP 2.5 и КА 2.5) разработчики фирмы «1С» доработали алгоритмы фонового проведения. Теперь перед непосредственной транзакцией записи движений в базу данных фоновые задания осуществляют жесткую перепроверку статуса актуальности документа-регистратора. Если документ успели распровести — фоновая транзакция отменяется.
  2. Регламентный аудит базы данных. Настройте регламентное задание на сервере 1С, которое раз в неделю будет выполнять поисковый запрос (представленный нами в Шаге 1). В случае обнаружения расхождений администратору или ведущему программисту на почту может отправляться автоматический алерт с перечнем документов-нарушителей.
  3. Контроль программного кода доработок. При написании собственных обработок обмена данными или группового изменения статусов документов всегда контролируйте использование правильных методов платформы. Запрещайте прямую установку реквизита пометки удаления, используйте метод УстановитьПометкуУдаления() и всегда закладывайте логику принудительного очищения наборов записей при программной отмене проведения документов.
← На главную