Как исключить повторную регистрацию документов при их перепроведении в планах обмена 1С?

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

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

В этой статье мы подробно разберем, почему так происходит, и проанализируем практические способы обхода этой проблемы на уровне платформы и Библиотеки стандартных подсистем (БСП).

Выясним причину: почему платформа регистрирует неизмененные документы?

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

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

Способ 1. Отключение авторегистрации и использование подписок на события

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

  1. Откроем конфигуратор, найдем наш план обмена и в составе объектов для нужного документа установим свойство Авторегистрация в значение Запретить.
  2. Создадим новую общую подписку на событие (например, ПередЗаписью для нужного типа документа) или добавим логику в существующую подписку, отвечающую за регистрацию изменений.
  3. В обработчике подписки программно определим, нужно ли регистрировать объект.

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


Процедура ПередЗаписьюДокументаРегистрация(Источник, Отказ, РежимЗаписи, РежимПроведения) Экспорт

    // Отключаем стандартный механизм автозаполнения получателей
    Источник.ОбменДанными.Получатели.АвтоЗаполнение = Ложь;
    
    // Если это не копирование и документ уже записан в базе, 
    // мы можем выполнить проверку изменений перед ручной регистрацией
    Если Не Источник.ЭтоНовый() Тогда
        // Здесь будет выполняться алгоритм проверки модифицированности
        НужноРегистрировать = ПроверитьИзменениеЗначимыхРеквизитов(Источник);
    Иначе
        НужноРегистрировать = Истина; // Новый документ регистрируем всегда
    КонецЕсли;

    Если НужноРегистрировать Тогда
        // Программно добавляем узлы-получатели, если условия выполняются
        Для Каждого Узел Из НайтиУзлыДляРегистрации(Источник) Цикл
            Источник.ОбменДанными.Получатели.Добавить(Узел);
        КонецЦикла;
    КонецЕсли;

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

Способ 2. Программное сравнение старой и новой версии объекта

Чтобы понять, изменились ли данные документа при перепроведении, нам необходимо сопоставить текущее состояние объекта в оперативной памяти (переданное в параметр Источник подписки ПередЗаписью) со старым состоянием, сохраненным в базе данных.

Важно: Прямое обращение к реквизитам через точку от ссылки (например, Источник.Ссылка.Контрагент) крайне нежелательно. Это приведет к неявному считыванию всего старого объекта из базы данных, что нивелирует всю оптимизацию. Правильнее и быстрее использовать точечный запрос к СУБД.

Рассмотрим пример функции, которая проверяет, изменились ли ключевые поля шапки документа:


Функция ПроверитьИзменениеЗначимыхРеквизитов(ДокументОбъект)
    
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   Контрагент,
        |   СуммаДокумента,
        |   Организация,
        |   Проведен
        |ИЗ
        |   Документ.РеализацияТоваровУслуг
        |ГДЕ
        |   Ссылка = &Ссылка";
        
    Запрос.УстановитьПараметр("Ссылка", ДокументОбъект.Ссылка);
    Выборка = Запрос.Выполнить().Выбрать();
    
    Если Выборка.Следующий() Тогда
        // Сравниваем только те реквизиты, изменение которых критично для обмена
        Если ДокументОбъект.Контрагент <> Выборка.Контрагент
            Или ДокументОбъект.СуммаДокумента <> Выборка.СуммаДокумента
            Или ДокументОбъект.Организация <> Выборка.Организация
            Или ДокументОбъект.Проведен <> Выборка.Проведен Тогда
            
            Возврат Истина; // Данные изменились, нужна регистрация
        КонецЕсли;
    КонецЕсли;
    
    // Если значимые реквизиты шапки совпадают, проверяем табличную часть (опционально)
    Возврат Ложь; // Изменений нет, перепроведение "пустое"
    
КонецФункции

Если у документа сложная структура и много табличных частей, ручное написание запросов сравнения может быть трудоемким. В таком случае применяется метод хеширования. При записи документа рассчитывается хэш-сумма (например, MD5) по значимым полям и сохраняется в дополнительный реквизит или независимый регистр сведений. При повторном проведении хэш рассчитывается заново: если он совпал с сохраненным значением — регистрацию отменяют.

Способ 3. Оптимизация обмена в конфигурациях на базе БСП

В современных типовых конфигурациях (ERP, КА, УТ, Розница) авторегистрация на уровне метаданных почти везде запрещена разработчиками 1С. Регистрацией изменений управляет встроенный механизм БСП через универсальные подписки и Правила регистрации объектов (ПРО).

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


// Пример программного перепроведения документа без его регистрации в БСП
ДокументОбъект = СсылкаНаДокумент.ПолучитьОбъект();
ДокументОбъект.ДополнительныеСвойства.Вставить("ОтключитьМеханизмРегистрацииОбъектов", Истина);
ДокументОбъект.Записать(РежимЗаписиДокумента.Проведение);

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

Определяем контекст выполнения (сервисные операции)

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


// Проверяем, выполняется ли запись в фоновом задании закрытия месяца
Если ПараметрыСеанса.ВыполняетсяЗакрытиеМесяца Тогда 
    Источник.ОбменДанными.Получатели.АвтоЗаполнение = Ложь;
    Возврат;
КонецЕсли;

Важные риски отключения регистрации при перепроведении

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

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

← На главную