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