При настройке обмена данными между конфигурациями 1С (например, из ЗУП 2.5 в Розницу 2.2) с использованием механизма Конвертации данных 2.1 разработчики часто сталкиваются с ситуацией, когда обмен через файл работает безупречно, а при переходе на COM-соединение часть алгоритмов в обработчиках ПКО (Правил конвертации объектов) перестает выполняться. Типичный пример — создание связанных объектов, таких как дисконтные карты или записи в регистрах сведений (штрихкоды), непосредственно в обработчике После загрузки.
В этой статье мы подробно разберем, почему возникает такая проблема, как контекст выполнения влияет на работу кода и какие шаги необходимо предпринять, чтобы ваши алгоритмы гарантированно отрабатывали при любом способе синхронизации.
Разберем, что происходит «под капотом» в обоих случаях. При обмене через файл вы сначала выгружаете данные в XML, а затем интерактивно загружаете их в приемнике через обработку «Универсальный обмен данными». В этом случае код выполняется в контексте вашего текущего сеанса (толстый или тонкий клиент), со всеми доступными правами и инициализированными модулями.
При использовании COM-соединения (внешнего соединения) база-источник подключается к базе-приемнику программно. Весь код обработчиков загрузки выполняется в специальном сеансе — сеансе внешнего соединения. Рассмотрим основные причины, по которым код может «молча» игнорироваться или вызывать ошибки в этом режиме.
Проанализируем, как Розница 2.2 (и другие конфигурации на БСП) работает с правилами обмена. В современных конфигурациях правила часто хранятся внутри самой информационной базы. Даже если вы подключаетесь из ЗУП 2.5 и указываете локальный файл правил, система при COM-соединении может использовать так называемые правила конфигурации корреспондента (CorrespondentExchangeRules.XML), которые уже загружены в базу-приемник.
Если вы внесли изменения в обработчик После загрузки в файл правил на стороне источника, но не обновили правила в самой Рознице (в регистре сведений «Правила обмена данными» или в настройках узла обмена), то при COM-запросе приемник выполнит старую версию кода, где вашего алгоритма создания штрихкода просто нет.
Решение: Обязательно загрузите обновленные правила обмена в базу-приемник. Убедитесь, что в настройках синхронизации данных в Рознице 2.2 используются именно актуальные правила.
В обработчике После загрузки мы часто оперируем переменной Объект и пытаемся создать подчиненные элементы. Рассмотрим важный нюанс: если объект является новым, его ссылка может быть еще не «зафиксирована» в базе данных в нужный момент для создания связанных записей в регистрах.
Посмотрим на пример кода, который может вызвать проблему:
// Создаем новый штрихкод
ЗаписьШтрихкода = РегистрыСведений.Штрихкоды.СоздатьМенеджерЗаписи;
ЗаписьШтрихкода.Владелец = НоваяКарта.Ссылка;
ЗаписьШтрихкода.ТипШтрихкода = ПланыВидовХарактеристик.ТипыШтрихкодов.EAN13;
ЗаписьШтрихкода.Штрихкод = ИмяКарты;
Попытка
ЗаписьШтрихкода.Записать;
Исключение
// Ошибка может быть подавлена во внешнем соединении
КонецПопытки;
Если НоваяКарта была только что создана, перед созданием записи в регистре сведений необходимо убедиться, что карта физически записана. Кроме того, в режиме COM-соединения рекомендуется явно вызывать Объект.Записать(), если вы планируете использовать _Ссылка (ссылку на загружаемый объект) для связи с другими данными.
Выясним причину, связанную с программной средой. Внешнее соединение имеет ряд ограничений:
Предупреждение(), Вопрос() или методы, помеченные директивой &НаКлиенте, приведут к немедленному прерыванию выполнения кода.Сообщить() во внешнем соединении часто уходит «в никуда». Для отладки используйте ЗаписьЖурналаРегистрации().Для регистров сведений в 1С существует два способа записи: МенеджерЗаписи и НаборЗаписей. Практика показывает, что при работе через COM-соединение использование СоздатьМенеджерЗаписи() может быть менее стабильным из-за особенностей блокировок в транзакции. Рассмотрим более надежный вариант с использованием набора записей:
НаборШтрихкодов = РегистрыСведений.Штрихкоды.СоздатьНаборЗаписей();
НаборШтрихкодов.Отбор.Владелец.Установить(НоваяКарта.Ссылка);
НаборШтрихкодов.Отбор.Штрихкод.Установить(ИмяКарты);
НоваяЗапись = НаборШтрихкодов.Добавить();
НоваяЗапись.Владелец = НоваяКарта.Ссылка;
НоваяЗапись.Штрихкод = ИмяКарты;
НоваяЗапись.ТипШтрихкода = ПланыВидовХарактеристик.ТипыШтрихкодов.EAN13;
НаборШтрихкодов.ОбменДанными.Загрузка = Истина;
НаборШтрихкодов.Записать();
Обратите внимание на использование свойства ОбменДанными.Загрузка = Истина. Это отключает лишние проверки в модуле набора записей, что критически важно при автоматическом создании данных во время обмена.
Поскольку стандартная отладка не заходит в код приемника при COM-обмене, выполним следующие шаги для поиска ошибки:
Подведем итог и составим правильную структуру кода для создания зависимых объектов:
// 1. Проверяем, что объект записан (особенно важно для новых объектов)
Если Объект.Ссылка.Пустая() Тогда
Попытка
Объект.Записать();
Исключение
ЗаписьЖурналаРегистрации("Обмен_Данными", УровеньЖурналаРегистрации.Ошибка, , , ОписаниеОшибки());
Возврат;
КонецПопытки;
КонецЕсли;
// 2. Логика создания дисконтной карты
// Используем переменную _Ссылка, так как это ссылка на текущий загруженный объект
ИмяКарты = Объект.ИдентификационныйКодЛичности;
КартаСотрудника = Справочники.ИнформационныеКарты.НайтиПоНаименованию(ИмяКарты);
Если КартаСотрудника.Пустая() Тогда
НоваяКарта = Справочники.ИнформационныеКарты.СоздатьЭлемент();
НоваяКарта.Наименование = СокрЛП(ИмяКарты);
НоваяКарта.ВладелецКарты = Объект.Ссылка;
// ... заполнение остальных реквизитов ...
Попытка
НоваяКарта.ОбменДанными.Загрузка = Истина;
НоваяКарта.Записать();
// 3. Создание штрихкода через НаборЗаписей
Набор = РегистрыСведений.Штрихкоды.СоздатьНаборЗаписей();
Набор.Отбор.Владелец.Установить(НоваяКарта.Ссылка);
НоваяЗапись = Набор.Добавить();
НоваяЗапись.Владелец = НоваяКарта.Ссылка;
НоваяЗапись.Штрихкод = ИмяКарты;
НоваяЗапись.ТипШтрихкода = ПланыВидовХарактеристик.ТипыШтрихкодов.EAN13;
Набор.Записать();
Исключение
ЗаписьЖурналаРегистрации("Обмен_Данными", УровеньЖурналаРегистрации.Ошибка, , , "Ошибка создания карты: " + ОписаниеОшибки());
КонецПопытки;
КонецЕсли;
Используя такой подход, вы минимизируете риски возникновения «невидимых» ошибок и обеспечите стабильную работу обмена данными как через файлы, так и через COM-соединение.