Рассмотрим распространенную задачу: нам необходимо написать план обмена между современной конфигурацией (например, «Розница для Украины 2.0» на управляемых формах) и более старой системой (например, «УПП для Украины 1.3» на обычных формах). Основная сложность часто возникает при попытке правильно зарегистрировать к выгрузке записи независимых регистров сведений, таких как Штрихкоды, да еще и с применением определенных фильтров (например, выгружать штрихкоды только для конкретного типа номенклатуры).
Проанализируем ситуацию по шагам, разберем частые ошибки, возникающие в процессе, и выясним причину их появления.
Посмотрим на архитектуру старых конфигураций, таких как УПП 1.3. В них используется устаревшая подсистема обмена данными. Вы не найдете там привычной для современных систем (на базе БСП) команды «Загрузить правила регистрации» и механизма работы с XML-макетами правил регистрации объектов (ПРО).
Все условия регистрации в таких конфигурациях приходится прописывать программно. Как правило, это делается либо в модуле объекта самого плана обмена (в обработчике ПриОтправкеДанныхПодчиненному), либо через подписки на события объекта.
Разберем детально, в какой подписке на событие лучше регистрировать изменения набора записей регистра: ПередЗаписью или ПриЗаписи.
Источник в данном случае является набором записей, который содержит новые данные, висящие в памяти, но физически они еще не сохранены. Если ориентироваться на запросы к ИБ, вы зарегистрируете старый штрихкод.Для передачи данных между событиями ПередЗаписью и ПриЗаписи профессионалы часто используют специальную коллекцию ДополнительныеСвойства объекта. Это позволяет проанализировать набор записей до записи, сохранить нужные флаги (например, список измененной номенклатуры), а после успешной записи выполнить регистрацию без повторных запросов.
Представим, вы настроили регистрацию в ПриЗаписи, штрихкоды регистрируются корректно. Но при загрузке в базу-приемник выпадает ошибка:
«Запись не верна! Значение поля не соответствует установленному отбору: Штрихкод... Поле: Владелец»
Выясним причину этой типовой проблемы при работе с обменами через Конвертацию Данных (КД 2.1). В платформе 1С набор записей регистра сведений всегда записывается с установленным отбором. Если в правилах конвертации объектов (ПКО) приходят записи, где значения измерений (в данном случае Владелец) отсутствуют или отличаются от тех, что установлены в отборе набора, платформа блокирует запись из-за нарушения целостности.
Почему владелец может оказаться пустым? Посмотрим на внутренние механизмы выгрузки XML:
Нпп). Если владелец (Номенклатура) уже выгружался ранее в этом же пакете, система не выгружает его повторно, а просто передает ссылку вида Нпп=1.НайтиОбъектПоНомеру возвращает Неопределено (например, из-за настроек кэширования в правилах), ссылка на владельца теряется, и в набор записей передается пустое значение. Отсюда и возникает конфликт с отбором.В типовой обработке загрузки есть следующий код, который пытается восстановить ссылку по номеру:
ИначеЕсли ИмяУзла = "Нпп" Тогда
ФайлОбмена.Прочитать();
Нпп = Число(ФайлОбмена.Значение);
Если Нпп <> 0 Тогда
Значение = НайтиОбъектПоНомеру(Нпп, Тип);
НаличиеСвойств = Истина;
КонецЕсли;
ФайлОбмена.Прочитать();
Если вы включите флаг «Не запоминать выгруженные объекты» в ПКО Номенклатуры, проблема с Нпп для новых штрихкодов может обойтись, так как система будет искать объект по-другому, но это порождает следующую проблему.
В большинстве типовых конфигураций Штрихкод является измерением регистра сведений (наравне с Владельцем/Номенклатурой и Единицей измерения).
Разберем логику базы данных: если пользователь исправляет штрихкод в карточке товара, с точки зрения СУБД это не изменение существующей записи. Это удаление старой записи (так как изменился первичный ключ) и создание новой.
План обмена регистрирует только факт появления новой записи. При загрузке в приемник новый штрихкод добавится, но старый не удалится! Возникнут дубли. Чтобы этого избежать, при изменении штрихкодов необходимо либо передавать признак очистки по отбору, либо вместе со штрихкодом регистрировать саму Номенклатуру, чтобы правила обмена выгрузили полный актуальный срез штрихкодов по данному владельцу.
Для корректной и стабильной реализации обмена регистрами сведений в подобных условиях мы рекомендуем придерживаться следующего алгоритма:
ПриЗаписи набора записей регистра.ОбменДанными.Загрузка = Ложь в начале обработчика, чтобы не регистрировать данные, которые только что приехали по обмену (защита от зацикливания).Таким образом, вы обойдете проблему с пустыми ссылками (Владелец всегда будет в контексте выгрузки), избавитесь от дублей штрихкодов при их изменении и обеспечите консистентность данных между базами.