Как объединить дублирующиеся элементы справочника при обмене данными в 1С без потери информации?

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

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

Разберем подробно причины возникновения этой проблемы, правильную архитектуру хранения подобных данных и программные способы сопоставления и слияния информации.

Почему стандартный механизм обмена создает дубли и затирает реквизиты

Проанализируем базовые принципы работы синхронизации в платформе 1С:Предприятие 8.3:

  1. Идентификация по GUID: В механизмах распределенных информационных баз (РИБ) сопоставление элементов выполняется строго по внутреннему уникальному идентификатору (УникальныйИдентификатор). Если один и тот же физический объект создается независимо в двух разных узлах, платформа присваивает им разные идентификаторы. При обмене система считает их двумя абсолютно независимыми элементами и не выполняет автоматический поиск по полям Наименование или ЗаводскойНомер.
  2. Запись объекта целиком: В 1С объект справочника сериализуется и передается в пакете обмена в полном объеме. Если в двух базах изменили разные реквизиты одного элемента, то при возникновении коллизии побеждает одна из версий (например, по приоритету главного узла), полностью перезаписывая значения всех реквизитов и строк табличных частей.

Архитектурное решение: разделение НСИ и перенос показателей в регистры

Выясним, как правильно организовать структуру хранения данных, чтобы исключить конфликты синхронизации на уровне проектирования конфигурации.

Хранить эксплуатационные показатели (пробег, наработку, историю ТО, ремонты) непосредственно в реквизитах или табличных частях справочника техники — грубая архитектурная ошибка. Для решения проблемы применим следующий подход:

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

    - Измерение: Техника (ссылка на справочник);

    - Измерение: Филиал (подразделение);

    - Период: дата фиксации показателя;

    - Ресурс: Пробег, ВидОбслуживания и другие параметры.

При обмене записями регистров сведений платформенный механизм не перезаписывает весь объект целиком, а дополняет таблицу новыми строками с уникальными комбинациями измерений и периодов. Данные филиала №1 и филиала №2 объединяются без конфликтов.

Программный перехват и слияние объектов в модуле плана обмена

Если специфика бизнеса требует автономного ввода объектов в филиалах, настроим перехват входящих данных на уровне событий плана обмена. Рассмотрим реализацию с использованием обработчиков ПриПолученииДанныхОтГлавного и ПриПолученииДанныхОтПодчиненного в модуле соответствующего плана обмена.

Разберем по шагам логику перехвата: перед тем как записать полученный объект, выполним поиск существующего аналога по уникальным бизнес-ключам (заводской номер и модель). Если элемент найден, перенесем недостающие данные и отменим стандартную запись нового объекта.


Процедура ПриПолученииДанныхОтПодчиненного(ЭлементДанных, ПолучениеЭлемента, ОтправкаНазад, Неотправленные)
    
    // Проверяем тип входящего объекта
    Если ТипЗнч(ЭлементДанных) = Тип("СправочникОбъект.Номенклатура") Тогда
        
        // Проверяем, существует ли уже элемент с таким заводским номером
        Запрос = Новый Запрос;
        Запрос.Текст = 
            "ВЫБРАТЬ
            |	Номенклатура.Ссылка КАК Ссылка
            |ИЗ
            |	Справочник.Номенклатура КАК Номенклатура
            |ГДЕ
            |	Номенклатура.ЗаводскойНомер = &ЗаводскойНомер
            |	И Номенклатура.Наименование = &Наименование
            |	И Номенклатура.Ссылка <> &ТекущаяСсылка";
            
        Запрос.УстановитьПараметр("ЗаводскойНомер", ЭлементДанных.ЗаводскойНомер);
        Запрос.УстановитьПараметр("Наименование", ЭлементДанных.Наименование);
        Запрос.УстановитьПараметр("ТекущаяСсылка", ЭлементДанных.Ссылка);
        
        Выборка = Запрос.Выполнить().Выбрать();
        
        Если Выборка.Следующий() Тогда
            // Объект-дубль обнаружен в базе. Дополняем существующий эталон
            ЭталонОбъект = Выборка.Ссылка.ПолучитьОбъект();
            
            // Заполняем только те реквизиты, которые пусты в базе-приемнике
            Если Не ЗначениеЗаполнено(ЭталонОбъект.ДатаВыпуска) И ЗначениеЗаполнено(ЭлементДанных.ДатаВыпуска) Тогда
                ЭталонОбъект.ДатаВыпуска = ЭлементДанных.ДатаВыпуска;
            КонецЕсли;
            
            // Выполняем запись обновленного эталона
            ЭталонОбъект.Записать();
            
            // Отменяем стандартное создание дублирующего объекта из пакета обмена
            ПолучениеЭлемента = ТипПолученияЭлементаДанных.Игнорировать;
        КонецЕсли;
        
    КонецЕсли;

КонецПроцедуры

Слияние дублей после завершения обмена

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

  1. Поиск дублей: Формируется запрос по совпадающим ключевым реквизитам (ЗаводскойНомер, Артикул). Определяется эталонный элемент (созданный ранее) и элемент-дубль.
  2. Слияние значений: Программно переносятся недостающие реквизиты, строки табличных частей и движения по регистрам с дубля на эталон.
  3. Замена ссылок: Используется платформенный механизм замены ссылок во всех таблицах базы данных:

// Массив с ссылкой на дублирующий элемент
МассивДублей = Новый Массив;
МассивДублей.Добавить(СсылкаДубль);

// Выполняем глобальную замену дубля на эталонную ссылку во всей базе
НайденоСсылок = НайтиПоСсылкам(МассивДублей);
Если НайденоСсылок.Количество() > 0 Тогда
    Дело = Новый Структура("Дубль, Эталон", СсылкаДубль, СсылкаЭталон);
    ПараметрыЗамены = Новый Массив;
    ПараметрыЗамены.Добавить(Дело);
    
    // Вызов стандартной процедуры замены ссылок
    // (или использование платформенного метода ЗаблокироватьДанныеДляРедактирования и ручной перезаписи)
КонецЕсли;

// Помечаем дубль на удаление
ОбъектДубль = СсылкаДубль.ПолучитьОбъект();
ОбъектДубль.УстановитьПометкуУдаления(Истина);

Использование связки из правильной архитектуры регистров и событий перехвата пакетов обмена позволяет полностью исключить потерю учетных данных при временной автономной работе филиалов.

← На главную