Как запретить загрузку документов по конкретной организации при использовании Конвертации данных 2.1?

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

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

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

Почему фильтрация при выгрузке не всегда эффективна

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


Если Источник.Организация = Параметры.ОрганизацияКоторуюНеНадоВыгружать Тогда
    Отказ = Истина;
КонецЕсли;

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

Решение через обработчик «После загрузки»

Проанализируем работу механизма загрузки в КД 2.1. Для того чтобы документ был прочитан, но не записан в базу данных, если он принадлежит «чужой» организации, лучше всего подходит обработчик события После загрузки.

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

Рассмотрим алгоритм действий:

  1. Откройте правила конвертации в конфигурации «Конвертация данных 2.1».
  2. Найдите ПКО (Правило конвертации объекта) для нужного типа документа.
  3. Перейдите на закладку «Обработчики событий» и выберите После загрузки.
  4. Напишите код, проверяющий соответствие организации.

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


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

Использование Отказ = Истина в этом месте гарантирует, что объект не будет создан или обновлен в базе данных приемника.

Оптимизация: определение «своей» организации

Чтобы не использовать жесткое кодирование наименований (hardcode), которое является плохим тоном в разработке, выясним, как правильно определить целевую организацию в базе-приемнике. Мы можем использовать несколько подходов:

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

Модифицированный и более универсальный пример кода:


// Пытаемся получить организацию, которая закреплена за этой базой
// Например, через предопределенную константу
НашаОрганизация = Константы.ОсновнаяОрганизация.Получить();

Если ЗначениеЗаполнено(НашаОрганизация) И Объект.Организация <> НашаОрганизация Тогда
    Отказ = Истина;
КонецЕсли;

Проблема связанных данных (справочников)

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

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

Поэтому мы рекомендуем дублировать проверку организации в ПКО для зависимых справочников. Рассмотрим пример для справочника ДоговорыКонтрагентов в обработчике После загрузки:


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

Архитектурные риски: один узел на две базы

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

Механизм планов обмена в 1С работает на основе номеров сообщений. Когда База-Источник выгружает данные для Узла №1, она фиксирует номер исходящего сообщения (например, 100). Когда База-Приемник загружает этот файл, она отправляет ответное сообщение (квитирование), подтверждающее получение пакета №100. После получения этого подтверждения База-Источник очищает регистрацию изменений для этого узла, считая данные успешно переданными.

Если у вас две базы-приемника «стучатся» в один и тот же узел:

  1. База №1 забирает сообщение №100 и подтверждает его.
  2. Источник удаляет регистрацию изменений.
  3. База №2 приходит за данными, но для Узла №1 больше нет зарегистрированных изменений.

Результат: База №2 никогда не получит те данные, которые первой успела забрать и подтвердить База №1. Это приведет к полной рассинхронизации данных.

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

Резюме

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

← На главную