Как выгрузить один заказ в два документа при обмене данными в 1С и избежать перезаписи по УИД?

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

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

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

Почему происходит перезапись документа в базе-приемнике?

Выясним причину такого поведения типовых механизмов обмена данными:

  1. Поиск по уникальному идентификатору (УИД). По умолчанию, когда в функции ВыгрузитьПоПравилу передается ссылка на объект-источник, механизм сериализации помещает в выгружаемый узел XML уникальный идентификатор этого объекта. При загрузке в базу-приемник платформа сначала пытается найти документ по полученному УИД. Когда обрабатывается второй документ, обработчик загрузки находит только что созданный первый документ (ведь у них одинаковый УИД источника) и полностью перезаписывает его новыми данными.
  2. Работа регистра соответствий. В обменах на планах обмена сопоставление ссылок фиксируется в регистре сведений СоответствияОбъектовИнформационныхБаз. Данный регистр оперирует связью «один к одному». При попытке записать два объекта-приемника для одного источника регистр связывает ссылку источника только с последним созданным документом.

Способ 1. Выгрузка второго документа через ИсходящиеДанные (рекомендуемый)

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

Разберем по шагам, как настроить такую схему:

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

// Формируем структуру данных для второго документа
СтруктураДанных = Новый Структура;
СтруктураДанных.Вставить("Организация", Источник.Организация);
СтруктураДанных.Вставить("Контрагент", Источник.Контрагент);
СтруктураДанных.Вставить("ДоговорКонтрагента", Источник.ДоговорКонтрагента);
СтруктураДанных.Вставить("Дата", Источник.Дата);
СтруктураДанных.Вставить("Номер", ПрефиксНомера + Источник.Номер);
СтруктураДанных.Вставить("Комментарий", "Вторая часть заказа " + Строка(Источник.Номер));

// Табличная часть также передается через структуру или таблицу значений
СтруктураДанных.Вставить("Товары", ПолучитьТабличнуюЧастьВторогоЗаказа(Источник));

// Выгружаем второй документ, передав Источник как Неопределено
ВыгрузитьПоПравилу(Неопределено, , СтруктураДанных, , "ЗаказПокупателя_Второй");

Так как параметр Источник передан как Неопределено, обработчик выгрузки не добавит УИД основного заказа во второй узел XML. База-приемник корректно создаст новый независимый документ.

Способ 2. Программное переопределение полей поиска при загрузке

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

Рассмотрим, как отключить стандартный поиск по УИД для второго ПКО:

  1. В ПКО для второго документа перейдем в обработчик «Поля поиска».
  2. Установим флаг ПрекратитьПоиск = Истина;, чтобы отключить типовой поиск по УИД.
  3. Пропишем собственный запрос для поиска существующего второго документа по реквизитам (например, по префиксу номера или ссылке на исходный заказ в реквизите Сделка):

// Отключаем типовой поиск по УИД и стандартным полям
ПрекратитьПоиск = Истина;

Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ ПЕРВЫЕ 1
    |   Заказ.Ссылка КАК Ссылка
    |ИЗ
    |   Документ.ЗаказПокупателя КАК Заказ
    |ГДЕ
    |   Заказ.Организация = &Организация
    |   И Заказ.Номер = &Номер
    |   И Заказ.Дата МЕЖДУ &ДатаНачала И &ДатаОкончания";

Запрос.УстановитьПараметр("Организация", СвойстваПоиска["Организация"]);
Запрос.УстановитьПараметр("Номер", СвойстваПоиска["Номер"]);
Запрос.УстановитьПараметр("ДатаНачала", НачалоДня(СвойстваПоиска["Дата"]));
Запрос.УстановитьПараметр("ДатаОкончания", КонецДня(СвойстваПоиска["Дата"]));

Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
    СсылкаНаОбъект = Выборка.Ссылка;
Иначе
    СсылкаНаОбъект = Неопределено;
КонецЕсли;

Способ 3. Генерация детерминированного УИД для второго документа

Для обеспечения надежной синхронизации при повторных обменах можно вычислять стабильный УИД для второго документа на основе УИД первого. Это гарантирует, что даже при изменении номера или даты документ в приемнике не задублируется.

Посмотрим на пример генерации производного идентификатора:


// Получаем строковое представление исходного УИД
СтрокаУИД = Строка(Источник.УникальныйИдентификатор());

// Модифицируем символы для получения уникального, но постоянного хеша
СкорректированныйУИД = "b" + Сред(СтрокаУИД, 2);
НовыйУИД = Новый УникальныйИдентификатор(СкорректированныйУИД);

// Передаем сгенерированный идентификатор в исходящие данные
ИсходящиеДанные = Новый Структура;
ИсходящиеДанные.Вставить("УИДВторогоДокумента", НовыйУИД);

Важные архитектурные ограничения

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

  1. Регистрация изменений. При повторном проведении заказа в источнике план обмена регистрирует к отправке только один объект. Правила должны быть настроены так, чтобы логика распределения строк и сумм повторно применялась к обоим документам без потери данных.
  2. Пометка на удаление. Если исходный заказ будет помечен на удаление в базе-источнике, стандартный обмен пометит на удаление только один документ в приемнике. Удаление или отмену проведения второго заказа необходимо дополнительно обрабатывать через обработчик ПослеЗагрузки.
  3. Двусторонний обмен. При разделении сущностей «1 к 2» невозможно организовать типовой двусторонний обмен. Рекомендуется настроить регистрацию изменений так, чтобы созданные в базе-приемнике разделенные документы не регистрировались к обратной выгрузке.
← На главную