До сих пор мы обменивались только вновь создаваемыми данными, поэтому у нас не возникало ситуаций, когда одни и те же данные изменялись бы сразу несколькими участниками обмена. На самом деле вполне возможна ситуация, когда, например, в один и тот же существующий документ вносятся изменения и в центральной базе, и в подчиненном узле. Такая ситуация называется «коллизией».
В результате, если ничего не предпринимать, после обмена данными в документе останутся только те изменения, которые были внесены в центральной базе. Изменения документа, сделанные в подчиненном узле, будут проигнорированы.
Это стандартный вариант разрешения коллизий, основанный на том, что главный узел обмена (в нашем примере это центральная база) имеет более высокий приоритет (его изменения более важны), чем подчиненный. Такой сценарий обмена данными в распределенной информационной базе заложен изначально и не требует никакого программирования.
Но бывают случаи, когда требуется реализовать какой-то особенный сценарий обмена. Например, вся нормативно-справочная информация ведется в центральной базе, а расходные и приходные накладные составляются в подчиненных узлах.
В этом случае коллизия должна быть разрешена ровно наоборот – когда изменения подчиненного узла имеют более высокий приоритет над главным. Но это касается только документов и их движений в регистрах. Обмен всеми остальными объектами происходит «по правилам».
Для решения данной задачи поместим в модуле плана обмена Магазины обработчик события ПриПолученииДанныхОтГлавного и дополним обработчик ПриПолученииДанныхОтПодчиненного.
Эти обработчики были подробно рассмотрены выше в листингах 3.28, 3.29, за исключением функции ПринятьИзменения() для определения типа элемента данных обмена, который содержится в параметре ЭлементДанных. Эта функция будет возвращать Истина, в случае если элемент данных имеет тип расходной или приходной накладных или связанных с ними регистров. В противном случае функция вернет Ложь. Поместим эту функцию в модуле плана обмена и заполним следующим образом (листинг 3.42).
Листинг 3.42. Функция «ПринятьИзменения»
Функция ПринятьИзменения(ЭлементДанных)
Прием = Ложь;
ТипДанных = ТипЗнч(ЭлементДанных);
Если ТипЗнч(ЭлементДанных) = Тип("ДокументОбъект.ПриходнаяНакладная")
Или ТипЗнч(ЭлементДанных) = Тип("ДокументОбъект.РасходнаяНакладная")
Или ТипЗнч(ЭлементДанных) = Тип("РегистрНакопленияНаборЗаписей.УчетНоменклатуры") Тогда
Прием = Истина;
КонецЕсли;
Возврат Прием;
КонецФункции
Обработчик ПриПолученииДанныхОтПодчиненного дополним следующим фрагментом, выделенным жирным шрифтом (листинг 3.43).
Листинг 3.43. Процедура «ПриПолученииДанныхОтПодчиненного()»
Процедура ПриПолученииДанныхОтПодчиненного(ЭлементДанных, ПолучениеЭлемента, ОтправкаНазад)
Если ПринятьИзменения(ЭлементДанных) Тогда
ПолучениеЭлемента = ПолучениеЭлементаДанных.Принять;
КонецЕсли;
// Определить Склад, которому принадлежат получаемые данные.
СкладДанных = ОпределитьСклад(ЭлементДанных);
// Получить данные, у которых Склад соответствует складу подчиненного узла плана обмена.
…
КонецПроцедуры
В этом обработчике определяется, что от подчиненного узла будут безусловно приниматься все изменения интересующих нас документов и их движений. Для остальных элементов обмена никаких действий предпринято не будет, что равносильно стандартному варианту разрешения коллизий.
Обработчик события ПриПолученииДанныхОтГлавного заполним следующим образом (листинг 3.44).
Листинг 3.44. Процедура «ПриПолученииДанныхОтГлавного()»
Процедура ПриПолученииДанныхОтГлавного(ЭлементДанных, ПолучениеЭлемента, ОтправкаНазад)
Если ПланыОбмена.ИзменениеЗарегистрировано(Ссылка, ЭлементДанных)
И ПринятьИзменения(ЭлементДанных) Тогда
ПолучениеЭлемента = ПолучениеЭлементаДанных.Игнорировать;
КонецЕсли;
КонецПроцедуры
В этом обработчике определяется, что если в базе подчиненного узла зарегистрированы изменения интересующих нас документов и их движений для главного узла, то при получении данных от главного узла соответствующие изменения будут проигнорированы. В результате прочитанный элемент данных не записывается в базу подчиненного узла, а регистрация изменений сохраняется, что позволит поместить этот элемент данных в сообщение, отправляемое главному узлу.
Убедимся, что все работает правильно для всех узлов обмена, причем и программным, и интерактивным способом. Поскольку такой вариант разрешения коллизий реализован в модуле плана обмена Магазины, он будет «работать» независимо от способа обмена данными.