Как правильно настроить регистрацию регистра сведений для плана обмена в 1С?

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

Рассмотрим распространенную задачу: нам необходимо написать план обмена между современной конфигурацией (например, «Розница для Украины 2.0» на управляемых формах) и более старой системой (например, «УПП для Украины 1.3» на обычных формах). Основная сложность часто возникает при попытке правильно зарегистрировать к выгрузке записи независимых регистров сведений, таких как Штрихкоды, да еще и с применением определенных фильтров (например, выгружать штрихкоды только для конкретного типа номенклатуры).

Проанализируем ситуацию по шагам, разберем частые ошибки, возникающие в процессе, и выясним причину их появления.

Особенности регистрации в старых конфигурациях

Посмотрим на архитектуру старых конфигураций, таких как УПП 1.3. В них используется устаревшая подсистема обмена данными. Вы не найдете там привычной для современных систем (на базе БСП) команды «Загрузить правила регистрации» и механизма работы с XML-макетами правил регистрации объектов (ПРО).

Все условия регистрации в таких конфигурациях приходится прописывать программно. Как правило, это делается либо в модуле объекта самого плана обмена (в обработчике ПриОтправкеДанныхПодчиненному), либо через подписки на события объекта.

Выбор события: ПередЗаписью или ПриЗаписи?

Разберем детально, в какой подписке на событие лучше регистрировать изменения набора записей регистра: ПередЗаписью или ПриЗаписи.

  1. Событие ПередЗаписью: Если вы попытаетесь использовать это событие и сделаете запрос к базе данных для проверки каких-либо условий (например, отбор по номенклатуре), вы столкнетесь с проблемой: в базе всё еще лежат старые данные. Объект Источник в данном случае является набором записей, который содержит новые данные, висящие в памяти, но физически они еще не сохранены. Если ориентироваться на запросы к ИБ, вы зарегистрируете старый штрихкод.
  2. Событие ПриЗаписи: Это более подходящий момент. Данные уже физически записаны в таблицы регистра, и их можно смело регистрировать. Однако здесь важно учитывать структуру обмена, иначе при загрузке в базу-приемник вы можете получить критическую ошибку.

Для передачи данных между событиями ПередЗаписью и ПриЗаписи профессионалы часто используют специальную коллекцию ДополнительныеСвойства объекта. Это позволяет проанализировать набор записей до записи, сохранить нужные флаги (например, список измененной номенклатуры), а после успешной записи выполнить регистрацию без повторных запросов.

Ошибка при загрузке: «Значение поля не соответствует установленному отбору»

Представим, вы настроили регистрацию в ПриЗаписи, штрихкоды регистрируются корректно. Но при загрузке в базу-приемник выпадает ошибка:

«Запись не верна! Значение поля не соответствует установленному отбору: Штрихкод... Поле: Владелец»

Выясним причину этой типовой проблемы при работе с обменами через Конвертацию Данных (КД 2.1). В платформе 1С набор записей регистра сведений всегда записывается с установленным отбором. Если в правилах конвертации объектов (ПКО) приходят записи, где значения измерений (в данном случае Владелец) отсутствуют или отличаются от тех, что установлены в отборе набора, платформа блокирует запись из-за нарушения целостности.

Почему владелец может оказаться пустым? Посмотрим на внутренние механизмы выгрузки XML:

  1. Механизм Npp: Обработка универсального обмена использует нумерацию объектов (Нпп). Если владелец (Номенклатура) уже выгружался ранее в этом же пакете, система не выгружает его повторно, а просто передает ссылку вида Нпп=1.
  2. Если при загрузке функция НайтиОбъектПоНомеру возвращает Неопределено (например, из-за настроек кэширования в правилах), ссылка на владельца теряется, и в набор записей передается пустое значение. Отсюда и возникает конфликт с отбором.

В типовой обработке загрузки есть следующий код, который пытается восстановить ссылку по номеру:


ИначеЕсли ИмяУзла = "Нпп" Тогда 
    ФайлОбмена.Прочитать(); 
    Нпп = Число(ФайлОбмена.Значение); 
    Если Нпп <> 0 Тогда 
        Значение = НайтиОбъектПоНомеру(Нпп, Тип); 
        НаличиеСвойств = Истина; 
    КонецЕсли; 
    ФайлОбмена.Прочитать();

Если вы включите флаг «Не запоминать выгруженные объекты» в ПКО Номенклатуры, проблема с Нпп для новых штрихкодов может обойтись, так как система будет искать объект по-другому, но это порождает следующую проблему.

Штрихкод как измерение регистра

В большинстве типовых конфигураций Штрихкод является измерением регистра сведений (наравне с Владельцем/Номенклатурой и Единицей измерения).

Разберем логику базы данных: если пользователь исправляет штрихкод в карточке товара, с точки зрения СУБД это не изменение существующей записи. Это удаление старой записи (так как изменился первичный ключ) и создание новой.

План обмена регистрирует только факт появления новой записи. При загрузке в приемник новый штрихкод добавится, но старый не удалится! Возникнут дубли. Чтобы этого избежать, при изменении штрихкодов необходимо либо передавать признак очистки по отбору, либо вместе со штрихкодом регистрировать саму Номенклатуру, чтобы правила обмена выгрузили полный актуальный срез штрихкодов по данному владельцу.

Итоговое решение

Для корректной и стабильной реализации обмена регистрами сведений в подобных условиях мы рекомендуем придерживаться следующего алгоритма:

  1. Регистрируйте изменения в подписке на событие ПриЗаписи набора записей регистра.
  2. Обязательно проверяйте условие ОбменДанными.Загрузка = Ложь в начале обработчика, чтобы не регистрировать данные, которые только что приехали по обмену (защита от зацикливания).
  3. Вместо сложной фильтрации самих штрихкодов, инициируйте в этой же подписке фоновую регистрацию владельца (Номенклатуры), если она удовлетворяет вашим фильтрам (например, по типу номенклатуры).
  4. В правилах конвертации данных настройте ПВД (правило выгрузки данных) для Номенклатуры так, чтобы оно попутно вытягивало связанные актуальные штрихкоды из базы-источника.

Таким образом, вы обойдете проблему с пустыми ссылками (Владелец всегда будет в контексте выгрузки), избавитесь от дублей штрихкодов при их изменении и обеспечите консистентность данных между базами.

← На главную