При настройке обменов между типовыми или нетиповыми конфигурациями (например, между «Управление торговым предприятием» и «Бухгалтерия предприятия») разработчики часто сталкиваются с задачами несимметричного переноса данных. Типичный сценарий — когда в базе-источнике ведется детальный складской учет по множеству складов, а в базе-приемнике учет свернут до одного основного склада. В процессе реализации таких правил нередко возникают сопутствующие вопросы: как правильно сопоставлять коды без префиксов, почему установка флага «Не замещать существующие объекты» может приводить к неожиданным результатам и из-за чего накапливаются зависшие изменения в планах обмена. Разберем детально каждый из этих вопросов.
Рассмотрим классическую задачу: в источнике существует разветвленная структура складов, а в приемнике все документы должны оформляться строго на один «Основной склад». При этом нельзя допустить создания новых дублирующих складов в базе-приемнике.
Для реализации этой схемы настроим правило конвертации объекта (ПКО) для справочника «Склады»:
ПКО для справочника «Склады» перейдем на вкладку «Настройки» и отключим флаг «Искать объект приемника по внутреннему идентификатору (GUID)». Это необходимо, чтобы система не пыталась найти соответствие по уникальному идентификатору источника.ПКС) данного объекта:
— В ПКС для свойства Наименование снимем признак передачи источника и в поле «Значение» укажем строку: "Основной склад".
— Установим для свойства Наименование флаг «Поле поиска».
— Для свойства ЭтоГруппа также установим флаг «Поле поиска» и зафиксируем значение Ложь (чтобы поиск выполнялся строго среди элементов, а не групп).
Альтернативный и более точный способ — принудительно определить параметры сопоставления в обработчике «Поля поиска» на стороне приемника в ПКО складов:
// В обработчике "Поля поиска" ПКО Склады
СвойстваПоиска.Вставить("Наименование", "Основной склад");
СвойстваПоиска.Вставить("ЭтоГруппа", Ложь);
ПрекратитьПоиск = Ложь;
Проанализируем ситуацию, когда вызывать отдельное ПКО для склада вообще не требуется. Если во всех загружаемых документах склад всегда должен быть одним и тем же, мы можем переопределить реквизит прямо в документе-источнике или документе-приемнике.
Разберем по шагам, как это сделать:
ПКО документа (например, «РеализацияТоваровУслуг») найдем ПКС «Склад» (или «СкладОрдер»).ПКС привязку к правилу конвертации объекта (оставим поле пустым).ПКС пропишем передачу наименования или фиксированного значения:
Значение = "Основной склад";
На стороне приемника при загрузке строковое значение будет сопоставлено со справочником по наименованию, что полностью исключает риск создания лишних элементов.
Часто в базе-источнике коды или номера содержат префиксы (например, «УТ-00001» или «Т0000114»), которые требуется удалить или трансформировать перед записью в базу-приемник.
Важно помнить: вызывать метод Объект.Записать() в обработчике «После загрузки» крайне не рекомендуется, так как это вызывает двойную запись объекта, существенно замедляет обмен и может приводить к блокировкам. Правильнее выполнять модификацию реквизитов в обработчике «При загрузке» (OnLoad) — в этот момент объект уже создан в оперативной памяти, но еще не зафиксирован в базе данных механизмом конвертации.
Посмотрим на пример удаления префикса до разделителя «-» в обработчике «При загрузке» соответствующего ПКО:
КодСПрефиксом = СокрЛП(Объект.Код);
РазделительПрефикса = "-";
Позиция = Найти(КодСПрефиксом, РазделительПрефикса);
Если Позиция > 0 Тогда
Объект.Код = Сред(КодСПрефиксом, Позиция + 1);
КонецЕсли;
// Метод Объект.Записать() вызывать не нужно — КД запишет объект автоматически.
Если же требуется выборочная замена конкретных кодов между базами (сопоставление по таблице соответствий), наиболее производительный подход — инициализировать соответствие при старте конвертации, а не писать множество условий Если...ИначеЕсли:
Параметры.Вставить("ТаблицаКодов", Новый Соответствие);
Параметры.ТаблицаКодов.Вставить("00001", "Т000114");
Параметры.ТаблицаКодов.Вставить("00002", "Т000115");
ПКС «Код» в обработчике «Перед выгрузкой» применим сопоставление:
НовыйКод = Параметры.ТаблицаКодов.Получить(Источник.Код);
Если НовыйКод <> Неопределено Тогда
Значение = НовыйКод;
КонецЕсли;
При использовании флага «Не замещать существующие объекты» в ПКО важно учитывать специфику работы алгоритмов загрузки:
ПКО документа необходимо проверить настройки на вкладке «Настройки»: переключить «Режим проведения» в значение «Не проводить» или управлять процессом через обработчик ПередЗаписьюПолученныхДанных:
Если Не Объект.ЭтоНовый() И Объект.Проведен Тогда
РежимЗаписи = РежимЗаписиДокумента.Запись;
КонецЕсли;
Если при каждом сеансе обмена одни и те же документы непрерывно выгружаются и перезаписываются, причина кроется в механизме регистрации изменений.
Выясним причину такого поведения: в стандартных планах обмена 1С используется квитирование (подтверждение доставки). Каждое сообщение содержит НомерОтправленного и НомерПринятого. База-источник удаляет отправленные записи из таблицы регистрации изменений только тогда, когда получает от базы-приемника пакет с номером принятого сообщения, подтверждающим успешную загрузку.
Если обмен настроен через прямое подключение (COM) или файловый каталог, но обратная загрузка пакета-ответа в источник не выполняется (или завершается аварийно), таблица регистрации изменений не очищается. В результате за недели и годы работы накапливаются сотни тысяч записей, которые раз за разом выгружаются в приемник.
Разберем порядок исправления ситуации:
УзелОбъекта = УзелОбмена.ПолучитьОбъект();
УзелОбъекта.НомерПринятого = УзелОбъекта.НомерОтправленного;
УзелОбъекта.Записать();
После выравнивания номеров сообщений и очистки регистрации следующий сеанс обмена будет выгружать исключительно новые и измененные объекты, а правила конвертации будут отрабатывать корректно и предсказуемо.