Как правильно игнорировать изменения документов в закрытом периоде при обмене через Конвертацию данных 2.1

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

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

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

Разбор проблемы: почему свойство «НеЗамещатьОбъект» может работать некорректно

Рассмотрим ситуацию, с которой столкнулся автор темы. При использовании свойства НеЗамещатьОбъект = Истина в обработчике При загрузке система должна просто пропускать запись текущего объекта. Однако при обмене через COM-соединение или при больших пакетах данных может возникнуть побочный эффект: у последующих, вполне корректных документов, начинают «слетать» реквизиты (склад, счета учета, подразделения).

Проанализируем причину этого явления. Движок «Конвертации данных 2.1» при работе через COM-соединение иногда кэширует внутренние состояния параметров загрузки. Если мы жестко устанавливаем НеЗамещатьОбъект и не сбрасываем его явным образом или если логика поиска объекта зацикливается на определенных ссылках, это состояние может «перекочевать» на другие объекты в рамках одной транзакции. Кроме того, использование НеЗамещатьОбъект не всегда корректно прерывает чтение свойств из входящего потока данных, что и приводит к пропускам заполнения реквизитов у следующих по порядку объектов.

Способ №1: Проверка даты через обработчик «После загрузки»

Самый надежный способ решить задачу — использовать обработчик После загрузки в Правилах конвертации объектов (ПКО). В этом обработчике нам доступны два ключевых параметра:

  1. Объект — это данные, которые только что прилетели из источника (уже заполненный объект, но еще не записанный в базу).
  2. Ссылка — это ссылка на существующий объект в базе-приемнике.

Выясним главную хитрость: до момента вызова метода Объект.Записать(), в переменной Ссылка хранятся старые данные документа, которые реально записаны в текущей информационной базе. Мы можем сравнить дату «прилетевшего» объекта и дату объекта, который уже лежит в базе.

Рассмотрим пример кода для обработчика После загрузки:


// Проверяем, найден ли объект в приемнике
Если ОбъектНайден Тогда
    
    // Получаем текущую дату документа из базы-приемника (до изменений)
    СтараяДата = Ссылка.Дата;
    
    // Определяем дату запрета изменения в приемнике. 
    // Для примера возьмем ее из параметров или константы.
    ДатаЗапрета = Параметры.ДатаЗапрета; 
    
    // Проверяем, попадает ли документ в закрытый период
    Если СтараяДата <= ДатаЗапрета Тогда
        
        // Если документ в закрытом периоде, отменяем загрузку
        Сообщить("Документ " + Ссылка + " находится в закрытом периоде. Загрузка пропущена.");
        Отказ = Истина;
        
    КонецЕсли;
    
КонецЕсли;

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

Способ №2: Оптимизация получения даты запрета

Посмотрим на ситуацию с точки зрения производительности. Если мы будем в каждом документе обращаться к функции ДатыЗапретаИзменения.ПолучитьДатуЗапрета(), это может замедлить обмен, особенно через COM-соединение. Проанализируем, как это оптимизировать.

Рекомендуется один раз получить дату запрета в начале обмена. Это можно сделать в обработчике Перед загрузкой данных (глобальный обработчик правил конвертации):


// В глобальном обработчике "Перед загрузкой данных"
// Если база на БСП, получаем дату для конкретного пользователя или общую
Попытка
    Параметры.Вставить("ДатаЗапрета", ДатыЗапретаИзменения.ПолучитьДатуЗапрета());
Исключение
    Параметры.Вставить("ДатаЗапрета", '00010101');
КонецПопытки;

Теперь во всех ПКО вы сможете просто обращаться к Параметры.ДатаЗапрета, что значительно ускорит процесс.

Решение вопроса с регистрацией изменений в источнике

Одной из задач автора было сделать так, чтобы документ «слетал» с регистрации в источнике, даже если он был проигнорирован в приемнике. При стандартном обмене (через план обмена), если на стороне приемника произошел Отказ или ошибка, объект может не считаться успешно переданным, и при следующем обмене он снова выгрузится.

Чтобы гарантировать снятие с регистрации, можно рассмотреть два варианта:

  1. На стороне приемника: Если мы используем Отказ = Истина, то в протокол обмена может вернуться информация о неудаче. Однако при COM-соединении обмен обычно управляется инициатором. Если инициатор видит, что выгрузка прошла без критических ошибок сессии, он очищает номера сообщений в плане обмена.
  2. На стороне источника: Мы можем проверять дату запрета приемника еще на этапе выгрузки. Для этого в ПВД (Правила выгрузки данных) перед выгрузкой через COM-соединение можно запросить дату запрета из базы-приемника и, если документ в нее попадает, просто удалять его регистрацию программно:

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

Важные нюансы при работе с БСП

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

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

Подведем итог: для решения проблемы игнорирования документов в закрытом периоде без «глюков» с реквизитами других объектов, используйте обработчик После загрузки с проверкой Ссылка.Дата и установкой Отказ = Истина. Это обеспечит чистоту данных и стабильность процесса обмена.

← На главную