Как настроить обмен УПП -> УПП с фильтром по организациям через разные узлы и избежать удаления регистрации изменений?

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

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

В процессе реализации такой схемы возникают две критические технические проблемы:

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

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

---

Часть 1. Решение проблемы с кодами узлов («ЭтотУзел») в базе-приемнике

Выясним причину первой проблемы. В платформе «1С:Предприятие 8» для любого плана обмена в конкретной информационной базе может существовать только один предопределенный узел. В коде конфигурации он доступен через метод ПланыОбмена.ИмяПлана.ЭтотУзел(). Этот узел олицетворяет саму текущую базу.

Когда вы пытаетесь настроить два разных узла в источнике (например, код 002 для Организации 1 и код 003 для Организации 2), база-источник (код 001) генерирует файлы с именами Message_001_002.zip и Message_001_003.zip. Чтобы база-приемник успешно считала эти файлы стандартным механизмом, код ее предопределенного узла («ЭтотУзел») должен совпадать с кодом получателя в имени файла. Но узел в приемнике один, и его код не может быть одновременно и 002, и 003.

Рассмотрим три способа решения этой проблемы.

Способ 1.1. Использование единого узла обмена и разделение логики в правилах (Рекомендуемый подход)

Поскольку база-приемник у нас одна, наиболее архитектурно правильным решением будет создание **одного** узла обмена (например, с кодом 002) как на стороне источника, так и на стороне приемника. Различающуюся логику для организаций мы перенесем непосредственно в правила конвертации данных (КД 2.1).

Для этого выполним следующие действия:

Способ 1.2. Создание копии плана обмена в конфигураторе

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

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

Способ 1.3. Модификация транспортного модуля обмена (Кастомизация имен файлов)

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

---

Часть 2. Предотвращение удаления регистрации изменений при использовании фильтров

Проанализируем вторую, более коварную проблему. Допустим, к обмену зарегистрировано 4 документа: 2 по Организации 1 и 2 по Организации 2. Мы запускаем выгрузку для Организации 1. В правилах конвертации (ПКО) у нас написан код проверки ИНН организации, и для документов Организации 2 срабатывает Отказ = Истина.

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

Это стандартное поведение платформы «1С:Предприятие 8». Процесс обмена выглядит так:

  1. При выгрузке платформа вызывает метод ПланыОбмена.ВыбратьИзменения(Узел, НомерСообщения). Все зарегистрированные на данный момент объекты на этом узле привязываются к номеру отправляемого сообщения (например, №10).
  2. Выборка передается в обработку выгрузки. Обработка обходит объекты. Те объекты, для которых в правилах сработал Отказ = Истина, просто игнорируются и не записываются в XML-файл.
  3. Приемник успешно загружает файл и возвращает квитанцию с подтверждением получения сообщения №10.
  4. При обработке квитанции в источнике вызывается метод ПланыОбмена.УдалитьРегистрациюИзменений(Узел, 10). Платформа удаляет из таблицы регистрации изменений все записи, которые были ассоциированы с сообщением №10, независимо от того, попали они физически в XML-файл или были отсечены правилами конвертации.

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

Рассмотрим, как правильно решить эту проблему.

Способ 2.1. Использование Правил регистрации объектов (ПРО)

В конфигурации «Конвертация данных 2.1» помимо правил конвертации объектов (ПКО) создаются так называемые **Правила регистрации объектов (ПРО)**. Это наиболее гибкий и правильный инструмент:

При таком подходе документы Организации 2 физически никогда не будут зарегистрированы на узле Организации 1. Соответственно, они не попадут в выборку изменений для этого узла и их регистрация не пострадает при получении подтверждения.

Способ 2.2. Программная регистрация в подписках на события

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


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

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

    // Определяем узлы обмена
    УзелОрг1 = ПланыОбмена.ОбменУППУПП.НайтиПоКоду("002");
    УзелОрг2 = ПланыОбмена.ОбменУППУПП.НайтиПоКоду("003");

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

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

Этот способ гарантирует идеальную чистоту таблиц регистрации изменений. На узле Организации 1 будут находиться только изменения по Организации 1.

Способ 2.3. Программная перерегистрация при отказе (Быстрый обходной путь)

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

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


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

Важное предупреждение о производительности: этот метод имеет существенный минус. Объект при каждом обмене будет попадать в выборку изменений, считываться из базы данных, тратить процессорное время на обработку в КД, отбрасываться и заново регистрироваться. При больших объемах данных это приведет к лавинообразному снижению скорости обмена. Используйте его только в крайних случаях и для небольших справочников. Для документов всегда используйте Способ 2.1 или Способ 2.2.

---

Резюме

Мы подробно проанализировали особенности работы планов обмена в «1С:Предприятие 8». При планировании архитектуры обмена данными помните:

← На главную