Настройка обмена данными между конфигурациями «1С:Управление торговлей» (УТ) и «1С:Бухгалтерия предприятия» (БП) — классическая задача для разработчика. Однако при использовании правил конвертации данных версии 2.1 (КД 2) и обработки УниверсальныйОбменДаннымиXML часто возникают неожиданные проблемы. В этой статье мы подробно разберем две крайне популярные ошибки: почему при загрузке документов все они «схлопываются» на одну организацию и откуда берется ошибка формата с сообщением «ИмяУзла = УдалениеОбъекта».
Рассмотрим типичную ситуацию. В базе-источнике (например, УТ) ведется учет по двум организациям. При выгрузке документов в XML-файл мы видим, что в нем присутствуют обе организации. Однако после загрузки в базу-приемник (например, БП) все документы почему-то оказываются оформленными на одну и ту же организацию. При этом в самом справочнике Организации обе записи остаются на месте, они не заменяются и не дублируются.
Выясним истинную техническую причину такого поведения. При обмене данными через КД 2 сопоставление объектов может происходить по двум сценариям: по внутреннему идентификатору (UUID/GUID) или по полям поиска. Сбой происходит на одном из этих этапов.
1. Совпадение уникальных идентификаторов (UUID)
По умолчанию в правилах конвертации объектов (ПКО) для справочников включена опция «Искать объект приемника по внутреннему идентификатору источника». Если база-приемник когда-то была создана копированием базы-источника (или наоборот), либо если элементы справочника Организации создавались копированием внутри одной базы, у двух разных организаций в разных базах может оказаться абсолютно одинаковый UUID. При чтении файла загрузки система находит объект по UUID на самом первом шаге и сразу подставляет его в документ, даже не доходя до сравнения ИНН, КПП или наименования.
2. Некорректный переход по вариантам поиска
В типовых правилах обмена поиск организаций часто настраивается в несколько последовательных попыток (вариантов поиска) в обработчике Поля поиска:
Если в алгоритме обработки переходов между попытками допущена ошибка, или если свойства поиска на очередном шаге оказались незаполненными, платформа выполняет запрос к базе данных без жестких отборов. СУБД возвращает первую попавшуюся запись из таблицы справочника. В итоге все загружаемые документы привязываются к одной случайной организации.
Для начала проанализируем UUID организаций в обеих базах с помощью любой стандартной обработки «Просмотр и изменение GUID». Если они совпадают у разных юридических лиц, их необходимо скорректировать.
Если дело в логике поиска, нам необходимо настроить безопасный откат (fallback) в обработчике Поля поиска для ПКО «Организации» в конфигурации «Конвертация данных 2.1». Разберем по шагам правильный алгоритм написания кода:
Если НомерВариантаПоиска = 1 Тогда
// Проверяем заполненность ИНН, чтобы избежать поиска по пустым строкам
Если ЗначениеЗаполнено(СвойстваПоиска["ИНН"]) Тогда
СтрокаИменСвойствПоиска = "ИНН, КПП";
КонецЕсли;
ИначеЕсли НомерВариантаПоиска = 2 Тогда
// Если по ИНН/КПП не нашли, пробуем сопоставить по наименованию
Если ЗначениеЗаполнено(СвойстваПоиска["Наименование"]) Тогда
СтрокаИменСвойствПоиска = "Наименование";
КонецЕсли;
Иначе
// Важнейший шаг: если ключевые свойства пусты, принудительно прекращаем поиск.
// Это предотвратит ошибочное сопоставление со случайным элементом базы.
ПрекратитьПоиск = Истина;
КонецЕсли;
Использование флага ПрекратитьПоиск = Истина гарантирует, что если система не смогла однозначно идентифицировать организацию по заданным правилам, она не подставит вместо нее первый попавшийся элемент из базы данных.
---
Перейдем ко второй проблеме. При ручной загрузке данных через внешнюю обработку Универсальный обмен данными в формате XML (файл V8Exchan82.epf) на экран несколько раз выводится системное сообщение:
«Ошибка формата сообщения обмена. ИмяУзла = УдалениеОбъекта»
При этом сам обмен может завершаться без жесткого прерывания, но данное предупреждение сильно усложняет анализ логов и пугает конечных пользователей. Выясним причину этого явления.
Современные типовые правила обмена разрабатываются вендором для использования в механизме Синхронизации данных, работающем на базе Библиотеки Стандартных Подсистем (БСП). В этом механизме активно задействованы планы обмена, которые фиксируют не только изменения объектов, но и их физическое удаление из базы-источника. БСП умеет обрабатывать XML-теги вида <УдалениеОбъекта> и корректно удаляет соответствующие сущности в базе-приемнике.
Однако старая универсальная обработка V8Exchan82.epf работает по упрощенному алгоритму. Ее парсер XML-файла последовательно читает узлы и ожидает увидеть там только стандартные данные (справочники, документы, регистры). Встречая тег удаления, обработка выдает исключение «Ошибка формата», поскольку структура этого узла ей неизвестна.
Рассмотрим подробнее три варианта решения этой проблемы — от простых организационных мер до точечного изменения кода.
Самый простой способ избавиться от ошибки без изменения программного кода — предотвратить попадание тегов удаления в выгружаемый XML-файл. Для этого перед выгрузкой выполним следующие действия:
Поскольку в очереди на отправку больше не будет удаленных объектов, правила обмена не станут генерировать проблемные теги в XML-файле.
Если мы используем правила конвертации, адаптированные под БСП, но выгружаем данные только вручную через универсальную обработку, логику удаления можно полностью отключить в самой конвертации. Для этого:
ПередОтправкойИнформацииОбУдалении или ЗаписатьУдалениеОбъектаВФайл.После сохранения измененных правил XML-файл перестанет содержать узлы <УдалениеОбъекта>, и загрузка пройдет абсолютно гладко.
Если правила обмена регулярно обновляются и менять их вручную каждый раз не хочется, лучшим решением будет научить саму обработку загрузки игнорировать этот тег. Проанализируем структуру модуля обработки загрузки и внесем изменения.
Откроем обработку V8Exchan82.epf в конфигураторе, найдем модуль объекта и перейдем к процедуре чтения данных XML. Нам нужно найти ветку условий, в которой анализируется переменная ИмяУзла, и добавить туда обходной путь:
ИначеЕсли ИмяУзла = "УдалениеОбъекта" Тогда
// Вызываем стандартный метод пропуска нечитаемых узлов XML
одПропустить(ФайлОбмена, "УдалениеОбъекта");
Такой лаконичный код позволит парсеру обработки встретить узел удаления, корректно «пролистать» его до закрывающего тега и продолжить чтение файла без вызова исключений и вывода сообщений об ошибках формата. Это наиболее изящный способ совместить современные правила обмена БСП со старой универсальной обработкой выгрузки.