Files
SSL/SSL/src/CommonModules/ОбменДаннымиСобытия/Module.bsl
T
2021-11-19 11:10:00 +03:00

3862 lines
245 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
///////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2021, ООО 1С-Софт
// Все права защищены. Эта программа и сопроводительные материалы предоставляются
// в соответствии с условиями лицензии Attribution 4.0 International (CC BY 4.0)
// Текст лицензии доступен по ссылке:
// https://creativecommons.org/licenses/by/4.0/legalcode
///////////////////////////////////////////////////////////////////////////////////////////////////////
#Область ПрограммныйИнтерфейс
// Процедура-обработчик события "ПередЗаписью" документов для механизма регистрации объектов на узлах.
//
// Параметры:
// ИмяПланаОбмена - Строка - имя плана обмена, для которого выполняется механизм регистрации.
// Источник - ДокументОбъект - источник события.
// Отказ - Булево - флаг отказа от выполнения обработчика.
// РежимЗаписи - РежимЗаписиДокумента - см. в синтакс-помощнике РежимЗаписиДокумента.
// РежимПроведения - РежимПроведенияДокумента - см. в синтакс-помощнике РежимПроведенияДокумента.
//
Процедура МеханизмРегистрацииОбъектовПередЗаписьюДокумента(ИмяПланаОбмена, Источник, Отказ, РежимЗаписи, РежимПроведения) Экспорт
Если Источник.ДополнительныеСвойства.Свойство("ОтключитьМеханизмРегистрацииОбъектов")
И Не Источник.ДополнительныеСвойства.Свойство("РегистрироватьНаУзлахПлановОбменаПриОбновленииИБ") Тогда
Возврат;
КонецЕсли;
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.ЗащитаПерсональныхДанных") Тогда
Модуль = ОбщегоНазначения.ОбщийМодуль("ЗащитаПерсональныхДанных");
Если Модуль.ПропуститьРегистрациюОбъекта(ИмяПланаОбмена, Источник) Тогда
Возврат;
КонецЕсли;
КонецЕсли;
ДополнительныеПараметры = Новый Структура("РежимЗаписи", РежимЗаписи);
ЗарегистрироватьИзменениеОбъекта(ИмяПланаОбмена, Источник, Отказ, ДополнительныеПараметры);
КонецПроцедуры
// Процедура-обработчик события "ПередЗаписью" ссылочных типов данных (кроме документов) для механизма регистрации
// объектов на узлах.
//
// Параметры:
// ИмяПланаОбмена - Строка - имя плана обмена, для которого выполняется механизм регистрации.
// Источник - СправочникОбъект
// - ПланВидовХарактеристикОбъект - источник события, кроме типа ДокументОбъект.
// Отказ - Булево - флаг отказа от выполнения обработчика.
//
Процедура МеханизмРегистрацииОбъектовПередЗаписью(ИмяПланаОбмена, Источник, Отказ) Экспорт
Если Источник.ДополнительныеСвойства.Свойство("ОтключитьМеханизмРегистрацииОбъектов")
И Не Источник.ДополнительныеСвойства.Свойство("РегистрироватьНаУзлахПлановОбменаПриОбновленииИБ") Тогда
Возврат;
КонецЕсли;
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.ЗащитаПерсональныхДанных") Тогда
Модуль = ОбщегоНазначения.ОбщийМодуль("ЗащитаПерсональныхДанных");
Если Модуль.ПропуститьРегистрациюОбъекта(ИмяПланаОбмена, Источник) Тогда
Возврат;
КонецЕсли;
КонецЕсли;
ЗарегистрироватьИзменениеОбъекта(ИмяПланаОбмена, Источник, Отказ);
КонецПроцедуры
// Процедура-обработчик события "ПередЗаписью" регистров для механизма регистрации объектов на узлах.
//
// Параметры:
// ИмяПланаОбмена - Строка - имя плана обмена, для которого выполняется механизм регистрации.
// Источник - НаборЗаписейРегистра - источник события.
// Отказ - Булево - флаг отказа от выполнения обработчика.
// Замещение - Булево - признак замещения существующего набора записей.
//
Процедура МеханизмРегистрацииОбъектовПередЗаписьюРегистра(ИмяПланаОбмена, Источник, Отказ, Замещение) Экспорт
Если Источник.ДополнительныеСвойства.Свойство("ОтключитьМеханизмРегистрацииОбъектов")
И Не Источник.ДополнительныеСвойства.Свойство("РегистрироватьНаУзлахПлановОбменаПриОбновленииИБ") Тогда
Возврат;
КонецЕсли;
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.ЗащитаПерсональныхДанных") Тогда
Модуль = ОбщегоНазначения.ОбщийМодуль("ЗащитаПерсональныхДанных");
Если Модуль.ПропуститьРегистрациюОбъекта(ИмяПланаОбмена, Источник) Тогда
Возврат;
КонецЕсли;
КонецЕсли;
ДополнительныеПараметры = Новый Структура("ЭтоРегистр,Замещение", Истина, Замещение);
ЗарегистрироватьИзменениеОбъекта(ИмяПланаОбмена, Источник, Отказ, ДополнительныеПараметры);
КонецПроцедуры
// Процедура-обработчик события "ПередЗаписью" константы для механизма регистрации объектов на узлах.
//
// Параметры:
// ИмяПланаОбмена - Строка - имя плана обмена, для которого выполняется механизм регистрации.
// Источник - КонстантаМенеджерЗначения - источник события.
// Отказ - Булево - флаг отказа от выполнения обработчика.
//
Процедура МеханизмРегистрацииОбъектовПередЗаписьюКонстанты(ИмяПланаОбмена, Источник, Отказ) Экспорт
Если Источник.ДополнительныеСвойства.Свойство("ОтключитьМеханизмРегистрацииОбъектов")
И Не Источник.ДополнительныеСвойства.Свойство("РегистрироватьНаУзлахПлановОбменаПриОбновленииИБ") Тогда
Возврат;
КонецЕсли;
ДополнительныеПараметры = Новый Структура("ЭтоКонстанта", Истина);
ЗарегистрироватьИзменениеОбъекта(ИмяПланаОбмена, Источник, Отказ, ДополнительныеПараметры);
КонецПроцедуры
// Процедура-обработчик события "ПередУдалением" ссылочных типов данных для механизма регистрации объектов на узлах.
//
// Параметры:
// ИмяПланаОбмена - Строка - имя плана обмена, для которого выполняется механизм регистрации.
// Источник - СправочникОбъект
// - ДокументОбъект
// - ПланВидовХарактеристикОбъект - источник события.
// Отказ - Булево - флаг отказа от выполнения обработчика.
//
Процедура МеханизмРегистрацииОбъектовПередУдалением(ИмяПланаОбмена, Источник, Отказ) Экспорт
Если Источник.ДополнительныеСвойства.Свойство("ОтключитьМеханизмРегистрацииОбъектов")
И Не Источник.ДополнительныеСвойства.Свойство("РегистрироватьНаУзлахПлановОбменаПриОбновленииИБ") Тогда
Возврат;
КонецЕсли;
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.ЗащитаПерсональныхДанных") Тогда
Модуль = ОбщегоНазначения.ОбщийМодуль("ЗащитаПерсональныхДанных");
Если Модуль.ПропуститьРегистрациюОбъекта(ИмяПланаОбмена, Источник) Тогда
Возврат;
КонецЕсли;
КонецЕсли;
ДополнительныеПараметры = Новый Структура("ЭтоУдалениеОбъекта", Истина);
ЗарегистрироватьИзменениеОбъекта(ИмяПланаОбмена, Источник, Отказ, ДополнительныеПараметры);
КонецПроцедуры
////////////////////////////////////////////////////////////////////////////////
// Процедуры и функции дли использования в обработчиках событий правил регистрации.
// Процедура дополняет список узлов-получателей объекта переданными значениями.
//
// Параметры:
// Объект - СправочникОбъект
// - ДокументОбъект - объект, для которого выполняется правило регистрации.
// Узлы - Массив из ПланОбменаСсылка - узлы плана обмена, которые необходимо добавить в список узлов-получателей объекта.
//
Процедура ДополнитьПолучателей(Объект, Узлы) Экспорт
Для Каждого Элемент Из Узлы Цикл
Попытка
Объект.ОбменДанными.Получатели.Добавить(Элемент);
Исключение
ИмяПланаОбмена = ОбменДаннымиПовтИсп.ПолучитьИмяПланаОбмена(Элемент);
ОбъектМетаданных = Объект.Метаданные();
СтрокаСообщения = НСтр("ru = 'Для состава плана обмена [ИмяПланаОбмена] не указана регистрация объекта [ПолноеИмя]'");
СтрокаСообщения = СтрЗаменить(СтрокаСообщения, "[ИмяПланаОбмена]", ИмяПланаОбмена);
СтрокаСообщения = СтрЗаменить(СтрокаСообщения, "[ПолноеИмя]", ОбъектМетаданных.ПолноеИмя());
ВызватьИсключение СтрокаСообщения;
КонецПопытки;
КонецЦикла;
КонецПроцедуры
// Процедура вычитает из списка узлов-получателей объекта переданные значения.
//
// Параметры:
// Объект - СправочникОбъект
// - ДокументОбъект - объект, для которого выполняется правило регистрации.
// Узлы - Массив из ПланОбменаСсылка - узлы плана обмена, которые необходимо вычесть из списка узлов-получателей объекта.
//
Процедура СократитьПолучателей(Объект, Узлы) Экспорт
Получатели = СократитьМассив(Объект.ОбменДанными.Получатели, Узлы);
// Очищаем список получателей и заполняем его заново.
Объект.ОбменДанными.Получатели.Очистить();
// Добавляем узлы для регистрации объекта.
ДополнитьПолучателей(Объект, Получатели);
КонецПроцедуры
// Определяет массив узлов-получателей для объекта при заданном плане обмена и выполняет регистрацию объекта на
// полученных узлах.
//
// Параметры:
// Объект - Произвольный - СправочникОбъект, ДокументОбъект и т.п. объект, для которого необходимо выполнить
// правила регистрации, и выполнить регистрацию на узлах.
// ИмяПланаОбмена - Строка - имя плана обмена как оно задано в конфигураторе.
// Отправитель - ПланОбменаСсылка - узел плана обмена от которого принимается сообщение обмена.
// Если задан, то регистрация объекта не этом узле выполнятся не будет.
//
Процедура ВыполнитьПравилаРегистрацииДляОбъекта(Объект, ИмяПланаОбмена, Отправитель = Неопределено) Экспорт
Получатели = ОпределитьПолучателей(Объект, ИмяПланаОбмена);
ОбщегоНазначенияКлиентСервер.УдалитьЗначениеИзМассива(Получатели, Отправитель);
Если Получатели.Количество() > 0 Тогда
ПланыОбмена.ЗарегистрироватьИзменения(Получатели, Объект);
КонецЕсли;
КонецПроцедуры
// Вычитает один массив элементов из другого массива. Возвращает результат вычитания.
//
// Параметры:
// Массив - Массив из Произвольный - исходный массив.
// МассивВычитания - Массив из Произвольный - массив, вычитаемый из исходного массива.
//
// Возвращаемое значение:
// Массив из Произвольный - результат вычитания.
//
Функция СократитьМассив(Массив, МассивВычитания) Экспорт
Возврат ОбщегоНазначенияКлиентСервер.РазностьМассивов(Массив, МассивВычитания);
КонецФункции
// Функция возвращает список всех узлов заданного плана обмена кроме предопределенного узла.
//
// Параметры:
// ИмяПланаОбмена - Строка - имя плана обмена, как оно задано в конфигураторе,
// список узлов для которого необходимо получить.
//
// Возвращаемое значение:
// Массив из ПланОбменаСсылка - список всех узлов заданного плана обмена.
//
Функция ВсеУзлыПланаОбмена(ИмяПланаОбмена) Экспорт
УстановитьПривилегированныйРежим(Истина);
Возврат ОбменДаннымиСервер.УзлыПланаОбмена(ИмяПланаОбмена);
КонецФункции
// Функция определяет массив узлов-получателей для объекта при заданном плане обмена.
//
// Параметры:
// Объект - Произвольный - СправочникОбъект, ДокументОбъект и т.п. объект, для которого необходимо выполнить
// правила регистрации, и определить список узлов-получателей.
// ИмяПланаОбмена - Строка - имя плана обмена как оно задано в конфигураторе.
//
// Возвращаемое значение:
// Массив из ПланОбменаСсылка - массив узлов-получателей для объекта.
//
Функция ОпределитьПолучателей(Объект, ИмяПланаОбмена) Экспорт
МассивУзловРезультат = Новый Массив;
ДополнительныеПараметры = Новый Структура;
ДополнительныеПараметры.Вставить("ОбъектМетаданных", Объект.Метаданные());
ДополнительныеПараметры.Вставить("ЭтоРегистр", ОбщегоНазначения.ЭтоРегистр(ДополнительныеПараметры.ОбъектМетаданных));
ВыполнитьПравилаРегистрацииОбъектовДляПланаОбмена(МассивУзловРезультат, Объект, ИмяПланаОбмена, ДополнительныеПараметры);
Возврат МассивУзловРезультат;
КонецФункции
// Определяет признак авторегистрации объекта метаданных в составе плана обмена.
//
// Параметры:
// ОбъектМетаданных - ОбъектМетаданных - объект, для которого требуется получить признак авторегистрации.
// ИмяПланаОбмена - Строка - имя плана обмена, как оно задано в конфигураторе, в состав которого входит
// объект метаданных.
//
// Возвращаемое значение:
// Булево - признак наличия авторегистрации в плане обмена:
// * Истина - объект метаданных имеет признак авторегистрации "Разрешена" в составе плана обмена;
// * Ложь - объект метаданных имеет признак авторегистрации "Запрещена" в составе плана обмена
// или объект метаданных не входит в состав плана обмена.
//
Функция АвтоРегистрацияРазрешена(ОбъектМетаданных, ИмяПланаОбмена) Экспорт
Возврат ОбменДаннымиПовтИсп.АвтоРегистрацияРазрешена(ИмяПланаОбмена, ОбъектМетаданных.ПолноеИмя());
КонецФункции
// Проверяет наличие запрета загрузки элемента данных.
// Для работы функции требуется настройка процедуры ДанныеДляПроверкиЗапретаИзменения
// модуля ДатыЗапретаИзмененияПереопределяемый.
//
// Параметры:
// Данные - Произвольный - СправочникОбъект.<Имя>,
// ДокументОбъект.<Имя>,
// ПланВидовХарактеристикОбъект.<Имя>,
// ПланСчетовОбъект.<Имя>,
// ПланВидовРасчетаОбъект.<Имя>,
// БизнесПроцессОбъект.<Имя>,
// ЗадачаОбъект.<Имя>,
// ПланОбменаОбъект.<Имя>,
// УдалениеОбъекта - объект данных.
// РегистрСведенийНаборЗаписей.<Имя>,
// РегистрНакопленияНаборЗаписей.<Имя>,
// РегистрБухгалтерииНаборЗаписей.<Имя>,
// РегистрРасчетаНаборЗаписей.<Имя> - набор записей.
//
// УзелПланаОбмена - ПланыОбменаОбъект - узел,
// для которого будет выполнена проверка.
//
// Возвращаемое значение:
// Булево - если Истина, загрузка запрещена.
//
Функция ЗагрузкаЗапрещена(Данные, Знач УзелПланаОбмена) Экспорт
ЭтоУдалениеОбъекта = (ТипЗнч(Данные) = Тип("УдалениеОбъекта"));
Если Не ЭтоУдалениеОбъекта
И Данные.ДополнительныеСвойства.Свойство("НайденЗапретЗагрузкиДанных") Тогда
Возврат Истина;
КонецЕсли;
ПолучениеЭлемента = ПолучениеЭлементаДанных.Авто;
ПроверитьНаличиеЗапретаЗагрузкиПоДате(Данные, ПолучениеЭлемента, УзелПланаОбмена);
Возврат ПолучениеЭлемента = ПолучениеЭлементаДанных.Игнорировать;
КонецФункции
#КонецОбласти
#Область СлужебныйПрограммныйИнтерфейс
// Процедура предназначена для определения вида отправки выгружаемого элемента данных.
// Вызывается из обработчиков планов обмена: ПриОтправкеДанныхГлавному(), ПриОтправкеДанныхПодчиненному().
//
// Параметры:
// ЭлементДанных - КонстантаМенеджерЗначения
// - СправочникОбъект
// - ДокументОбъект
// - РегистрСведенийНаборЗаписей
// - и т.п. -
// элемент данных.
// ОтправкаЭлемента - ОтправкаЭлементаДанных - см. описание параметра "ОтправкаЭлемента" в синтаксис помощнике
// для методов ПриОтправкеДанныхГлавному() и ПриОтправкеДанныхПодчиненному().
// СозданиеНачальногоОбраза - Булево - признак вызова процедуры при создании начального образа РИБ.
// Получатель - ПланОбменаСсылка
// - Неопределено - узел получателя.
// Анализ - Булево - признак вызова процедуры при анализе.
//
Процедура ПриОтправкеДанныхКорреспонденту(ЭлементДанных,
ОтправкаЭлемента,
Знач СозданиеНачальногоОбраза = Ложь,
Знач Получатель = Неопределено,
Знач Анализ = Истина) Экспорт
Если Получатель = Неопределено Тогда
//
ИначеЕсли ОтправкаЭлемента = ОтправкаЭлементаДанных.Удалить
ИЛИ ОтправкаЭлемента = ОтправкаЭлементаДанных.Игнорировать Тогда
// Стандартную обработку не переопределяем.
ИначеЕсли ОбменДаннымиПовтИсп.ЭтоУзелОбменаДаннымиБСП(Получатель.Ссылка) Тогда
ПриОтправкеДанных(ЭлементДанных, ОтправкаЭлемента, Получатель.Ссылка, СозданиеНачальногоОбраза, Анализ);
КонецЕсли;
Если Анализ Тогда
Возврат;
КонецЕсли;
// Фиксируем выгруженные предопределенные данные (только для РИБ).
Если Не СозданиеНачальногоОбраза
И ОтправкаЭлемента <> ОтправкаЭлементаДанных.Игнорировать
И ОбменДаннымиПовтИсп.ЭтоУзелРаспределеннойИнформационнойБазы(Получатель.Ссылка)
И ТипЗнч(ЭлементДанных) <> Тип("УдалениеОбъекта") Тогда
ОбъектМетаданных = ЭлементДанных.Метаданные();
Если ОбщегоНазначения.ЭтоСправочник(ОбъектМетаданных)
ИЛИ ОбщегоНазначения.ЭтоПланВидовХарактеристик(ОбъектМетаданных)
ИЛИ ОбщегоНазначения.ЭтоПланСчетов(ОбъектМетаданных)
ИЛИ ОбщегоНазначения.ЭтоПланВидовРасчета(ОбъектМетаданных) Тогда
Если ЭлементДанных.Предопределенный Тогда
ОбменДаннымиСлужебный.ДополнитьПриоритетныеДанныеОбмена(ЭлементДанных.Ссылка);
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
// Процедура является обработчиком одноименного события, возникающего при обмене данными в распределенной
// информационной базе.
//
// Параметры:
// см. описание обработчика события ПриПолученииДанныхОтГлавного() в синтакс-помощнике.
//
Процедура ПриПолученииДанныхОтГлавногоВНачале(ЭлементДанных, ПолучениеЭлемента, ОтправкаНазад, Отправитель) Экспорт
Если ОбменДаннымиСлужебный.РежимЗагрузкиСообщенияОбменаДаннымиПередЗапуском(
"ЗагрузкаПараметровРаботыПрограммы") Тогда
// В режиме загрузки параметров работы программы игнорируем получение всех данных.
ПолучениеЭлемента = ПолучениеЭлементаДанных.Игнорировать;
Иначе
Если ТипЗнч(ЭлементДанных) = Тип("КонстантаМенеджерЗначения.ДанныеДляОтложенногоОбновления") Тогда
ПолучениеЭлемента = ПолучениеЭлементаДанных.Игнорировать;
ОбменДаннымиСервер.ОбработатьДанныеДляОбновленияВПодчиненномУзле(ЭлементДанных);
КонецЕсли;
КонецЕсли;
КонецПроцедуры
// Процедура предназначена для выполнения проверок на наличие коллизий запрета загрузки и изменения данных.
// Вызывается из обработчика плана обмена: ПриПолученииДанныхОтГлавного.
//
// Параметры:
// см. описание обработчика события ПриПолученииДанныхОтГлавного() в синтакс-помощнике.
//
Процедура ПриПолученииДанныхОтГлавногоВКонце(ЭлементДанных, ПолучениеЭлемента, Знач Отправитель) Экспорт
// Проверка на запрет загрузки по дате запрета.
ПроверитьНаличиеЗапретаЗагрузкиПоДате(ЭлементДанных, ПолучениеЭлемента, Отправитель);
Если ПолучениеЭлемента = ПолучениеЭлементаДанных.Игнорировать Тогда
Возврат;
КонецЕсли;
// Проверка на коллизию изменения данных.
ПроверитьКоллизиюИзмененийДанных(ЭлементДанных, ПолучениеЭлемента, Отправитель, Истина);
КонецПроцедуры
// Процедура предназначена для выполнения проверок на наличие коллизий запрета загрузки и изменения данных.
// Вызывается из обработчика плана обмена: ПриПолученииДанныхОтПодчиненного.
//
// Параметры:
// см. описание обработчика события ПриПолученииДанныхОтПодчиненного() в синтакс-помощнике.
//
Процедура ПриПолученииДанныхОтПодчиненногоВКонце(ЭлементДанных, ПолучениеЭлемента, Знач Отправитель) Экспорт
// Проверка на запрет загрузки по дате запрета.
ПроверитьНаличиеЗапретаЗагрузкиПоДате(ЭлементДанных, ПолучениеЭлемента, Отправитель);
Если ПолучениеЭлемента = ПолучениеЭлементаДанных.Игнорировать Тогда
Возврат;
КонецЕсли;
// Проверка на коллизию изменения данных.
ПроверитьКоллизиюИзмененийДанных(ЭлементДанных, ПолучениеЭлемента, Отправитель, Ложь);
КонецПроцедуры
// Регистрирует изменение одного элемента данных для последующей отправки в адрес узла-получателя.
// Элемент данных будет зарегистрирован только в том случае, если он соответствует фильтрам правил регистрации
// объектов,установленным в свойствах узла-получателя.
// Элементы данных, которые выгружаются при необходимости, регистрируются безусловно.
// Объект УдалениеОбъекта регистрируется безусловно.
//
// Параметры:
// Получатель - ПланОбменаСсылка - узел плана обмена, для которого выполняется регистрация изменений
// данных.
// Данные - СправочникОбъект
// - ДокументОбъект
// - Произвольный
// - УдалениеОбъекта - объект, представляющий данные,
// хранимые в базе данных, такой как документ, элемент справочника, счет бухгалтерского учета, менеджер
// записи константы, набор записей регистра и т. п.
// ПроверятьРазрешениеВыгрузки - Булево - флаг. Если установить в Ложь, то дополнительная проверка
// на соответствие общим настройкам узла при регистрации производится не
// будет.
//
Процедура ЗарегистрироватьИзмененияДанных(Знач Получатель, Знач Данные, Знач ПроверятьРазрешениеВыгрузки=Истина) Экспорт
Если ТипЗнч(Данные) = Тип("УдалениеОбъекта") Тогда
// Удаление объекта регистрируем безусловно.
ПланыОбмена.ЗарегистрироватьИзменения(Получатель, Данные);
Иначе
РежимВыгрузкиОбъекта = ОбменДаннымиПовтИсп.РежимВыгрузкиОбъекта(Данные.Метаданные().ПолноеИмя(), Получатель);
Если РежимВыгрузкиОбъекта = Перечисления.РежимыВыгрузкиОбъектовОбмена.ВыгружатьПриНеобходимости Тогда
Если ОбщегоНазначения.ЗначениеСсылочногоТипа(Данные) Тогда
ЭтоНовыйОбъект = Данные.Пустая();
Иначе
ЭтоНовыйОбъект = Данные.ЭтоНовый();
КонецЕсли;
Если ЭтоНовыйОбъект Тогда
ВызватьИсключение НСтр("ru = 'Регистрация незаписанных объектов, выгружаемых по ссылке, не поддерживается.'");
КонецЕсли;
НачатьТранзакцию();
Попытка
// Выполняем регистрацию данных на узле-получателе.
ПланыОбмена.ЗарегистрироватьИзменения(Получатель, Данные);
// Для данных, выгружаемых по ссылке, дополнительно заносим сведения в фильтр разрешенных к выгрузке объектов.
// Это нужно для того, чтобы данные прошли фильтр при выгрузке и были выгружены в сообщение обмена.
Если ОбменДаннымиСервер.ЭтоПланОбменаXDTO(Получатель) Тогда
ОбменДаннымиXDTOСервер.ДобавитьОбъектВФильтрРазрешенныхОбъектов(Данные.Ссылка, Получатель);
Иначе
РегистрыСведений.СоответствияОбъектовИнформационныхБаз.ДобавитьОбъектВФильтрРазрешенныхОбъектов(Данные.Ссылка, Получатель);
КонецЕсли;
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
ВызватьИсключение;
КонецПопытки;
ИначеЕсли Не ПроверятьРазрешениеВыгрузки Тогда
// Регистрируем безусловно
ПланыОбмена.ЗарегистрироватьИзменения(Получатель, Данные);
ИначеЕсли ВыгрузкаОбъектаРазрешена(Получатель, Данные) Тогда
// Регистрируем, только если объект удовлетворяет общим ограничениям.
ПланыОбмена.ЗарегистрироватьИзменения(Получатель, Данные);
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Процедура УстановитьЗначенияОтборовНаУзле(УзелПланаОбмена, Настройки) Экспорт
УстановитьЗначенияНаУзле(УзелПланаОбмена, Настройки);
КонецПроцедуры
Процедура УстановитьЗначенияПоУмолчаниюНаУзле(УзелПланаОбмена, Настройки) Экспорт
УстановитьЗначенияНаУзле(УзелПланаОбмена, Настройки);
КонецПроцедуры
// Создает и записывает версию объекта в информационную базу.
//
// Параметры:
// Объект - записываемый объект ИБ.
// СсылкаСуществует - Булево - признак наличия объекта по ссылке в информационной базе.
// СведенияОВерсииОбъекта - Структура:
// * АвторВерсии - Пользователь, УзелПланаОбмена - источник версии.
// Необязательный, значение по умолчанию Неопределено.
// * ТипВерсииОбъекта - Строка - тип создаваемой версии.
// Необязательный, значение по умолчанию "ИзмененоПользователем".
// * ПредупреждениеСинхронизации - Строка - предупреждение синхронизации к создаваемой версии.
// Необязательный, значение по умолчанию "".
//
Процедура ПриСозданииВерсииОбъекта(Объект, СведенияОВерсииОбъекта, СсылкаСуществует, Отправитель) Экспорт
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.ВерсионированиеОбъектов") Тогда
СведенияОНовойВерсииОбъекта = Новый Структура;
СведенияОНовойВерсииОбъекта.Вставить("АвторВерсии", Неопределено);
СведенияОНовойВерсииОбъекта.Вставить("ТипВерсииОбъекта", "ИзмененоПользователем");
СведенияОНовойВерсииОбъекта.Вставить("Комментарий", "");
СведенияОНовойВерсииОбъекта.Вставить("ПредупреждениеСинхронизации", "");
ЗаполнитьЗначенияСвойств(СведенияОНовойВерсииОбъекта, СведенияОВерсииОбъекта);
МодульВерсионированиеОбъектов = ОбщегоНазначения.ОбщийМодуль("ВерсионированиеОбъектов");
МодульВерсионированиеОбъектов.СоздатьВерсиюОбъектаПоОбменуДанными(Объект, СведенияОНовойВерсииОбъекта, СсылкаСуществует, Отправитель);
КонецЕсли;
КонецПроцедуры
#КонецОбласти
#Область СлужебныеПроцедурыИФункции
#Область ОбработчикиПодписокНаСобытия
Процедура ЗарегистрироватьИзмененияФильтровОграниченияМиграцииДанных(Источник, Отказ) Экспорт
Если Источник.ОбменДанными.Загрузка Тогда
Возврат;
КонецЕсли;
Если Источник.ЭтоНовый() Тогда
Возврат;
ИначеЕсли Источник.ДополнительныеСвойства.Свойство("ПолучениеСообщенияОбмена") Тогда
Возврат; // Запись узла при получении сообщения обмена (универсальный обмен данными).
ИначеЕсли Не ОбменДаннымиПовтИсп.ЭтоУзелОбменаДаннымиБСП(Источник.Ссылка) Тогда
Возврат;
ИначеЕсли Источник.ЭтотУзел Тогда
Возврат;
КонецЕсли;
ИсточникСсылка = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(Источник.Ссылка, "НомерОтправленного, НомерПринятого");
Если ИсточникСсылка.НомерОтправленного <> Источник.НомерОтправленного Тогда
Возврат; // Запись узла при отправке сообщения обмена.
ИначеЕсли ИсточникСсылка.НомерПринятого <> Источник.НомерПринятого Тогда
Возврат; // Запись узла при получении сообщения обмена.
КонецЕсли;
ИмяПланаОбмена = ОбменДаннымиПовтИсп.ПолучитьИмяПланаОбмена(Источник.Ссылка);
// Получает реквизиты ссылочного типа, которые предположительно используются как фильтры фильтров правил регистрации.
ТаблицаРеквизитовСсылочногоТипа = РеквизитыОбъектаСсылочногоТипа(Источник, ИмяПланаОбмена);
// Определяем признак модифицированности узла относительно выбранных реквизитов.
ОбъектМодифицирован = ОбъектМодифицированПоРеквизитам(Источник, ТаблицаРеквизитовСсылочногоТипа);
Если ОбъектМодифицирован Тогда
Источник.ДополнительныеСвойства.Вставить("ТаблицаРеквизитовУзла", ТаблицаРеквизитовСсылочногоТипа);
КонецЕсли;
КонецПроцедуры
Процедура ПроверитьИзменениеФильтровОграниченияМиграцииДанныхПриЗаписи(Источник, Отказ) Экспорт
Если Источник.ОбменДанными.Загрузка Тогда
Возврат;
КонецЕсли;
Если Не ОбменДаннымиПовтИсп.ЭтоУзелОбменаДаннымиБСП(Источник.Ссылка) Тогда
Возврат;
КонецЕсли;
ЗарегистрированныеКВыгрузкеОбъекты = Неопределено;
Если Источник.ДополнительныеСвойства.Свойство("ЗарегистрированныеКВыгрузкеОбъекты", ЗарегистрированныеКВыгрузкеОбъекты) Тогда
ОбменДаннымиСлужебный.ОбновитьКэшМеханизмаРегистрацииОбъектов();
Для Каждого ЭлементНабор Из ЗарегистрированныеКВыгрузкеОбъекты Цикл
Если ОбщегоНазначения.ЭтоОбъектСсылочногоТипа(ЭлементНабор.Ключ) Тогда
Пока ЭлементНабор.Значение.Количество() > 0 Цикл
Объект = ЭлементНабор.Значение[0].ПолучитьОбъект();
Если Не ВыгрузкаОбъектаРазрешена(Источник.Ссылка, Объект) Тогда
ПланыОбмена.УдалитьРегистрациюИзменений(Источник.Ссылка, Объект);
КонецЕсли;
Объект = Неопределено;
ЭлементНабор.Значение.Удалить(0);
КонецЦикла;
ИначеЕсли ОбщегоНазначения.ЭтоКонстанта(ЭлементНабор.Ключ) Тогда
Объект = ЭлементНабор.Значение;
Если Не ВыгрузкаОбъектаРазрешена(Источник.Ссылка, Объект) Тогда
ПланыОбмена.УдалитьРегистрациюИзменений(Источник.Ссылка, Объект);
КонецЕсли;
Объект = Неопределено;
Иначе
МенеджерОбъекта = ОбщегоНазначения.МенеджерОбъектаПоПолномуИмени(ЭлементНабор.Ключ.ПолноеИмя());
ТаблицаОтборы = ЭлементНабор.Значение; // ТаблицаЗначений
Пока ТаблицаОтборы.Количество() > 0 Цикл
Объект = МенеджерОбъекта.СоздатьНаборЗаписей();
Для Каждого ЭлементОтбора Из ТаблицаОтборы.Колонки Цикл
ОбменДаннымиСлужебный.УстановитьЗначениеЭлементаОтбора(
Объект.Отбор, ЭлементОтбора.Имя, ТаблицаОтборы[0][ЭлементОтбора.Имя]);
КонецЦикла;
Объект.Прочитать();
Если Не ВыгрузкаОбъектаРазрешена(Источник.Ссылка, Объект) Тогда
ПланыОбмена.УдалитьРегистрациюИзменений(Источник.Ссылка, Объект);
КонецЕсли;
Объект = Неопределено;
ТаблицаОтборы.Удалить(0);
КонецЦикла;
КонецЕсли;
КонецЦикла;
КонецЕсли;
ТаблицаРеквизитовСсылочногоТипа = Неопределено;
Если Источник.ДополнительныеСвойства.Свойство("ТаблицаРеквизитовУзла", ТаблицаРеквизитовСсылочногоТипа) Тогда
// Выполняем регистрацию выбранных объектов ссылочного типа на текущем узле без использования ПРО.
ВыполнитьРегистрациюОбъектовСсылочногоТипаПоСвойствамУзла(Источник, ТаблицаРеквизитовСсылочногоТипа);
// Обновляем повторно используемые значения механизма.
ОбменДаннымиСлужебный.СброситьКэшМеханизмаРегистрацииОбъектов();
КонецЕсли;
КонецПроцедуры
Процедура ВключитьИспользованиеПланаОбмена(Источник, Отказ) Экспорт
// Проверка значения свойства ОбменДанными.Загрузка отсутствует по причине того, что в расположенным ниже коде,
// реализована логика, которая должна выполняться в том числе при установке этого свойства равным Истина
// (на стороне кода, который выполняет попытку записи в данный план обмена).
Если Источник.ЭтоНовый() И ОбменДаннымиПовтИсп.ЭтоУзелРазделенногоОбменаДаннымиБСП(Источник.Ссылка) Тогда
// Кэш открытых сеансов для МРО стал неактуальным.
ОбменДаннымиСлужебный.СброситьКэшМеханизмаРегистрацииОбъектов();
КонецЕсли;
КонецПроцедуры
// Параметры:
// Источник - ПланОбменаОбъект - узел плана обмена.
// Отказ - Булево - Истина, в случае отказа от выполнения операции.
//
Процедура ОтключитьИспользованиеПланаОбмена(Источник, Отказ) Экспорт
// Проверка значения свойства ОбменДанными.Загрузка отсутствует по причине того, что в расположенным ниже коде,
// реализована логика, которая должна выполняться в том числе при установке этого свойства равным Истина
// (на стороне кода, который выполняет попытку удаления узла данного плана обмена).
Если ОбменДаннымиПовтИсп.ЭтоУзелРазделенногоОбменаДаннымиБСП(Источник.Ссылка) Тогда
// Кэш открытых сеансов для МРО стал неактуальным.
ОбменДаннымиСлужебный.СброситьКэшМеханизмаРегистрацииОбъектов();
КонецЕсли;
КонецПроцедуры
Процедура ПроверитьВозможностьИзмененияНастроекОбменаДанными(Источник, Отказ) Экспорт
Если Источник.ОбменДанными.Загрузка Тогда
Возврат;
КонецЕсли;
Если Не ОбменДаннымиПовтИсп.ЭтоУзелОбменаДаннымиБСП(Источник.Ссылка) Тогда
Возврат;
КонецЕсли;
ИсключаемыеСвойства = Новый Массив;
ИсключаемыеСвойства.Добавить("НомерОтправленного");
ИсключаемыеСвойства.Добавить("НомерПринятого");
ИсключаемыеСвойства.Добавить("ПометкаУдаления");
ИсключаемыеСвойства.Добавить("Код");
ИсключаемыеСвойства.Добавить("Наименование");
Если ОбщегоНазначения.РазделениеВключено() Тогда
ПолноеИмяМетаданных = Источник.Метаданные().ПолноеИмя();
МодульРаботаВМоделиСервиса = ОбщегоНазначения.ОбщийМодуль("РаботаВМоделиСервиса");
РазделительОсновныхДанных = МодульРаботаВМоделиСервиса.РазделительОсновныхДанных();
РазделительВспомогательныхДанных = МодульРаботаВМоделиСервиса.РазделительВспомогательныхДанных();
Если МодульРаботаВМоделиСервиса.ЭтоРазделенныйОбъектМетаданных(ПолноеИмяМетаданных, РазделительОсновныхДанных) Тогда
ИсключаемыеСвойства.Добавить(РазделительОсновныхДанных);
КонецЕсли;
Если МодульРаботаВМоделиСервиса.ЭтоРазделенныйОбъектМетаданных(ПолноеИмяМетаданных, РазделительВспомогательныхДанных) Тогда
ИсключаемыеСвойства.Добавить(РазделительВспомогательныхДанных);
КонецЕсли;
КонецЕсли;
Если Источник.ДополнительныеСвойства.Свойство("ОтложеннаяЗаписьУзла")
Или (Не Источник.ДополнительныеСвойства.Свойство("ПолучениеСообщенияОбмена")
И Не Источник.ЭтоНовый()
И Не Источник.ЭтотУзел
И ДанныеРазличаются(Источник, Источник.Ссылка.ПолучитьОбъект(), , СтрСоединить(ИсключаемыеСвойства, ","))
И ОбменДаннымиСлужебный.ИзмененияЗарегистрированы(Источник.Ссылка)) Тогда
СохранитьРазрешенныеКВыгрузкеОбъекты(Источник);
КонецЕсли;
Если ОбщегоНазначения.ПодсистемаСуществует("ТехнологияСервиса.БазоваяФункциональность") Тогда
МодульРаботаВМоделиСервиса = ОбщегоНазначения.ОбщийМодуль("РаботаВМоделиСервиса");
СеансЗапущенБезРазделителей = МодульРаботаВМоделиСервиса.СеансЗапущенБезРазделителей();
Иначе
СеансЗапущенБезРазделителей = Истина;
КонецЕсли;
// Код и наименование узла в сервисе менять нельзя.
Если ОбщегоНазначения.РазделениеВключено()
И НЕ СеансЗапущенБезРазделителей
И Не Источник.ЭтоНовый()
И ДанныеРазличаются(Источник, Источник.Ссылка.ПолучитьОбъект(), "Код, Наименование") Тогда
ВызватьИсключение НСтр("ru = 'Изменение наименования и кода синхронизации данных недопустимо.'");
КонецЕсли;
КонецПроцедуры
Процедура ОтключитьАвтоматическуюСинхронизациюДанныхПриЗаписи(Источник, Отказ, Замещение) Экспорт
Если Источник.ОбменДанными.Загрузка Тогда
Возврат;
КонецЕсли;
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.РаботаВМоделиСервиса.ОбменДаннымиВМоделиСервиса") Тогда
МодульАвтономнаяРабота = ОбщегоНазначения.ОбщийМодуль("АвтономнаяРабота");
МодульАвтономнаяРабота.ОтключитьАвтоматическуюСинхронизациюДанныхСПриложениемВИнтернете(Источник);
КонецЕсли;
КонецПроцедуры
// Параметры:
// УзелСсылка - ПланОбменаСсылка
// ПолноеИмяОбъектаМетаданных - Строка
//
// Возвращаемое значение:
// ТаблицаЗначений - выгрузка из таблицы изменений объекта:
// * Ссылка - ЛюбаяСсылка - ссылка на объект.
// * Узел - ПланОбменаСсылка - узел плана обмена.
// * Регистратор - ДокументСсылка - регистратор набора записей (опционально).
// * <ВедущиеИзмененияРегистров> - Произвольный
//
Функция ЗарегистрированныеДанныеОдногоТипа(УзелСсылка, ПолноеИмяОбъектаМетаданных)
Запрос = Новый Запрос(
"ВЫБРАТЬ
| *
|ИЗ
| #ТаблицаИзменения КАК ТаблицаИзменения
|ГДЕ
| ТаблицаИзменения.Узел = &Узел");
Запрос.УстановитьПараметр("Узел", УзелСсылка);
Запрос.Текст = СтрЗаменить(Запрос.Текст, "#ТаблицаИзменения", ПолноеИмяОбъектаМетаданных + ".Изменения");
Возврат Запрос.Выполнить().Выгрузить();
КонецФункции
// Возвращаемое значение:
// ТаблицаЗначений:
// * Ссылка - ЛюбаяСсылка - ссылка на зарегистрированный объект.
//
Функция ЗарегистрированныеДанныеОдногоСсылочногоТипа(УзелСсылка, ПолноеИмяОбъектаМетаданных)
Запрос = Новый Запрос(
"ВЫБРАТЬ
| ТаблицаОбъект.Ссылка КАК Ссылка
|ИЗ
| #ТаблицаИзменения КАК ТаблицаИзменения
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ #ТаблицаОбъект КАК ТаблицаОбъект
| ПО ТаблицаИзменения.Ссылка = ТаблицаОбъект.Ссылка
|ГДЕ
| ТаблицаИзменения.Узел = &Узел");
Запрос.УстановитьПараметр("Узел", УзелСсылка);
Запрос.Текст = СтрЗаменить(Запрос.Текст, "#ТаблицаИзменения", ПолноеИмяОбъектаМетаданных + ".Изменения");
Запрос.Текст = СтрЗаменить(Запрос.Текст, "#ТаблицаОбъект", ПолноеИмяОбъектаМетаданных);
Возврат Запрос.Выполнить().Выгрузить();
КонецФункции
Процедура СохранитьРазрешенныеКВыгрузкеОбъекты(УзелОбъект)
УстановитьПривилегированныйРежим(Истина);
ЗарегистрированныеДанные = Новый Соответствие;
СоставПланаОбмена = УзелОбъект.Метаданные().Состав;
Для Каждого ЭлементСостава Из СоставПланаОбмена Цикл
Если ЭлементСостава.Авторегистрация = АвтоРегистрацияИзменений.Разрешить Тогда
Продолжить;
КонецЕсли;
МетаданныеЭлемента = ЭлементСостава.Метаданные;
ПолноеИмяОбъектаМетаданных = МетаданныеЭлемента.ПолноеИмя();
Если ОбщегоНазначения.ЭтоОбъектСсылочногоТипа(МетаданныеЭлемента) Тогда
КоллекцияСсылок = Новый Массив;
НаборДанных = ЗарегистрированныеДанныеОдногоСсылочногоТипа(УзелОбъект.Ссылка, ПолноеИмяОбъектаМетаданных);
Для Каждого СтрокаДанные Из НаборДанных Цикл
СсылкаНаОбъект = СтрокаДанные.Ссылка;
Если ВыгрузкаОбъектаРазрешена(УзелОбъект.Ссылка, СсылкаНаОбъект.ПолучитьОбъект()) Тогда
КоллекцияСсылок.Добавить(СсылкаНаОбъект);
КонецЕсли;
КонецЦикла;
ЗарегистрированныеДанные[МетаданныеЭлемента] = КоллекцияСсылок;
ИначеЕсли ОбщегоНазначения.ЭтоКонстанта(МетаданныеЭлемента) Тогда
МенеджерЗначенияКонстанты = Константы[МетаданныеЭлемента.Имя].СоздатьМенеджерЗначения();
Если ВыгрузкаОбъектаРазрешена(УзелОбъект.Ссылка, МенеджерЗначенияКонстанты) Тогда
ЗарегистрированныеДанные[МетаданныеЭлемента] = МенеджерЗначенияКонстанты;
КонецЕсли;
Иначе // Регистр или последовательность.
ТаблицаОтборы = Новый ТаблицаЗначений;
МенеджерОбъекта = ОбщегоНазначения.МенеджерОбъектаПоПолномуИмени(ПолноеИмяОбъектаМетаданных);
НаборДанных = ЗарегистрированныеДанныеОдногоТипа(УзелОбъект.Ссылка, ПолноеИмяОбъектаМетаданных);
НаборЗаписей = МенеджерОбъекта.СоздатьНаборЗаписей(); // РегистрСведенийНаборЗаписей, и т.п.
Для Каждого ЭлементОтбора Из НаборЗаписей.Отбор Цикл
Если НаборДанных.Колонки.Найти(ЭлементОтбора.Имя) <> Неопределено Тогда
ТаблицаОтборы.Колонки.Добавить(ЭлементОтбора.Имя);
КонецЕсли;
КонецЦикла;
Для Каждого СтрокаДанные Из НаборДанных Цикл
НаборЗаписей = МенеджерОбъекта.СоздатьНаборЗаписей(); // РегистрСведенийНаборЗаписей, и т.п.
Для Каждого ЭлементОтбора Из ТаблицаОтборы.Колонки Цикл
ОбменДаннымиСлужебный.УстановитьЗначениеЭлементаОтбора(
НаборЗаписей.Отбор, ЭлементОтбора.Имя, СтрокаДанные[ЭлементОтбора.Имя]);
КонецЦикла;
НаборЗаписей.Прочитать();
Если ВыгрузкаОбъектаРазрешена(УзелОбъект.Ссылка, НаборЗаписей) Тогда
СтруктураОтбора = ТаблицаОтборы.Добавить();
ЗаполнитьЗначенияСвойств(СтруктураОтбора, СтрокаДанные);
КонецЕсли;
КонецЦикла;
ЗарегистрированныеДанные[МетаданныеЭлемента] = ТаблицаОтборы;
КонецЕсли;
КонецЦикла;
УзелОбъект.ДополнительныеСвойства.Вставить("ЗарегистрированныеКВыгрузкеОбъекты", ЗарегистрированныеДанные);
КонецПроцедуры
Функция ВыгрузкаОбъектаРазрешена(УзелОбмена, Объект)
Если ОбщегоНазначения.ЗначениеСсылочногоТипа(Объект) Тогда
Возврат ОбменДаннымиСервер.ВыгрузкаСсылкиРазрешена(УзелОбмена, Объект);
КонецЕсли;
Отправка = ОтправкаЭлементаДанных.Авто;
ПриОтправкеДанныхКорреспонденту(Объект, Отправка, , УзелОбмена);
Возврат Отправка = ОтправкаЭлементаДанных.Авто;
КонецФункции
Процедура ОтменитьОтправкуДанныхУзлаВРаспределеннойИнформационнойБазе(Источник, ЭлементДанных, Игнорировать) Экспорт
Если Не ОбменДаннымиПовтИсп.ЭтоУзелОбменаДаннымиБСП(Источник.Ссылка) Тогда
Возврат;
КонецЕсли;
Если Не ЭлементДанных.ЭтотУзел Тогда
Если ОбщегоНазначения.РазделениеВключено() Тогда
// При отправке данных узла в разделенном режиме необходимо обнулять значения разделителей.
// В противном случае при загрузке в неразделенный АРМ будет происходить попытка записи узла в неинициализированную
// область данных с указанным значением разделителя, что приведет к ошибке отсутствия в ней узла с признаком "ЭтотУзел".
МодульРаботаВМоделиСервиса = ОбщегоНазначения.ОбщийМодуль("РаботаВМоделиСервиса");
Если МодульРаботаВМоделиСервиса.ЭтоРазделенныйОбъектМетаданных(Источник.Метаданные().ПолноеИмя(),
МодульРаботаВМоделиСервиса.РазделительОсновныхДанных()) Тогда
ЭлементДанных[МодульРаботаВМоделиСервиса.РазделительОсновныхДанных()] = 0;
КонецЕсли;
Если МодульРаботаВМоделиСервиса.ЭтоРазделенныйОбъектМетаданных(Источник.Метаданные().ПолноеИмя(),
МодульРаботаВМоделиСервиса.РазделительВспомогательныхДанных()) Тогда
ЭлементДанных[МодульРаботаВМоделиСервиса.РазделительВспомогательныхДанных()] = 0;
КонецЕсли;
КонецЕсли;
Возврат;
КонецЕсли;
Игнорировать = Истина;
КонецПроцедуры
Процедура ЗарегистрироватьИзмененияОбщихДанныхУзлов(Источник, Отказ) Экспорт
Если Источник.ОбменДанными.Загрузка Тогда
Возврат;
КонецЕсли;
Если Источник.ЭтоНовый() Тогда
Возврат;
ИначеЕсли Источник.ДополнительныеСвойства.Свойство("ПолучениеСообщенияОбмена") Тогда
Возврат; // Запись узла при получении сообщения обмена (универсальный обмен данными).
ИначеЕсли Не ОбменДаннымиПовтИсп.ЭтоУзелРазделенногоОбменаДаннымиБСП(Источник.Ссылка) Тогда
Возврат;
ИначеЕсли Не ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных() Тогда
Возврат;
КонецЕсли;
ОбщиеДанныеУзлов = ОбменДаннымиПовтИсп.ОбщиеДанныеУзлов(Источник.Ссылка);
Если ПустаяСтрока(ОбщиеДанныеУзлов) Тогда
Возврат;
КонецЕсли;
Если Источник.ЭтотУзел Тогда
Возврат;
КонецЕсли;
Если ДанныеРазличаются(Источник, Источник.Ссылка.ПолучитьОбъект(), ОбщиеДанныеУзлов) Тогда
РегистрыСведений.ИзмененияОбщихДанныхУзлов.ЗарегистрироватьИзменения(Источник.Ссылка);
КонецЕсли;
КонецПроцедуры
Процедура ОчиститьСсылкиНаУзелИнформационнойБазы(Источник, Отказ) Экспорт
// Проверка значения свойства ОбменДанными.Загрузка отсутствует по причине того, что в расположенным ниже коде,
// реализована логика, которая должна выполняться в том числе при установке этого свойства равным Истина
// (на стороне кода, который выполняет попытку удаления узла данного плана обмена).
Если Не ОбменДаннымиПовтИсп.ЭтоУзелОбменаДаннымиБСП(Источник.Ссылка) Тогда
Возврат;
КонецЕсли;
Справочники.СценарииОбменовДанными.ОчиститьСсылкиНаУзелИнформационнойБазы(Источник.Ссылка);
Если ОбщегоНазначения.РазделениеВключено()
И ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных() Тогда
Если ОбщегоНазначения.ПодсистемаСуществует("ТехнологияСервиса.ОчередьЗаданий")
И Не Источник.ДополнительныеСвойства.Свойство("ЭтоГлавныйУзелАРМ") Тогда
МодульОчередьЗаданий = ОбщегоНазначения.ОбщийМодуль("ОчередьЗаданий");
МодульРаботаВМоделиСервиса = ОбщегоНазначения.ОбщийМодуль("РаботаВМоделиСервиса");
КлючЗадания = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
НСтр("ru = 'Обмен данными с внешней системой (%1)'"),
Источник.Код);
Отбор = Новый Структура;
Отбор.Вставить("ОбластьДанных", МодульРаботаВМоделиСервиса.ЗначениеРазделителяСеанса());
Отбор.Вставить("Ключ", КлючЗадания);
ТаблицаЗадания = МодульОчередьЗаданий.ПолучитьЗадания(Отбор);
Для Каждого СтрокаЗадания Из ТаблицаЗадания Цикл
МодульОчередьЗаданий.УдалитьЗадание(СтрокаЗадания.Идентификатор);
КонецЦикла;
КонецЕсли;
КонецЕсли;
УстановитьПривилегированныйРежим(Истина);
ОбщегоНазначения.УдалитьДанныеИзБезопасногоХранилища(Источник.Ссылка);
УстановитьПривилегированныйРежим(Ложь);
КонецПроцедуры
Процедура ПередУдалениемПланаОбмена(Источник, Отказ) Экспорт
Если Источник.ОбменДанными.Загрузка Тогда
Возврат;
КонецЕсли;
Если ОбменДаннымиПовтИсп.ЭтоУзелОбменаДаннымиБСП(Источник.Ссылка)
И НЕ Источник.ДополнительныеСвойства.Свойство("УдалениеНастройкиСинхронизации") Тогда
Отказ = Истина;
КонецЕсли;
КонецПроцедуры
#КонецОбласти
#Область МеханизмРегистрацииОбъектов
// Определяет список узлов получателей плана обмена ИмяПланаОбмена, для которых необходимо выполнить
// регистрацию объекта Объект для последующей его выгрузки.
//
// Сначала, с помощью механизма выборочной регистрации объектов (ВРО) определяется,
// на каких планах обмена должен быть зарегистрирован объект к выгрузке.
// Затем, с помощью механизма регистрации объектов (ПРО, правила регистрации) определяется,
// на каких узлах каждого плана обмена должен быть зарегистрирован объект.
//
// Параметры:
// ИмяПланаОбмена - Строка - имя плана обмена, для которого выполняется механизм регистрации.
// Объект - Произвольный - изменяемые данные: объект, набор записей, константа или сведения об удалении объекта.
// Отказ - Булево - признак возникновения ошибки во время регистрации объекта на узлах:
// если во время регистрации объекта возникнут ошибки, то этот флаг будет установлен в значение Истина.
// ДополнительныеПараметры - Структура - уточняющие сведения об изменяемых данных:
// * ЭтоРегистр - Булево - значение Истина означает, что обрабатывается регистр.
// Необязательный, значение по умолчанию Ложь.
// * ЭтоУдалениеОбъекта - Булево - значение Истина означает, что обрабатывается удаление объекта.
// Необязательный, значение по умолчанию Ложь.
// * ЭтоКонстанта - Булево - значение Истина означает, что обрабатывается константа.
// Необязательный, значение по умолчанию Ложь.
// * РежимЗаписи - см. в синтакс-помощнике РежимЗаписиДокумента - режим записи документа (только для документов).
// Необязательный, значение по умолчанию Неопределено.
// * Замещение - Булево - режим записи регистра (только для регистров).
// Необязательный, значение по умолчанию Неопределено.
//
Процедура ЗарегистрироватьИзменениеОбъекта(ИмяПланаОбмена, Объект, Отказ, ДополнительныеПараметры = Неопределено)
// Проверка значения свойства ОбменДанными.Загрузка отсутствует по причине того, что в расположенным ниже коде,
// реализована логика, регистрации изменений на узлах плана обмена, которая должна выполняться в том числе при
// установке этого свойства равным Истина (на стороне кода, который выполняет попытку изменения/удаления данных).
НеобязательныеПараметры = Новый Структура;
НеобязательныеПараметры.Вставить("ЭтоРегистр", Ложь);
НеобязательныеПараметры.Вставить("ЭтоУдалениеОбъекта", Ложь);
НеобязательныеПараметры.Вставить("ЭтоКонстанта", Ложь);
НеобязательныеПараметры.Вставить("РежимЗаписи", Неопределено);
НеобязательныеПараметры.Вставить("Замещение", Неопределено);
Если ДополнительныеПараметры <> Неопределено Тогда
ЗаполнитьЗначенияСвойств(НеобязательныеПараметры, ДополнительныеПараметры);
КонецЕсли;
ЭтоРегистр = НеобязательныеПараметры.ЭтоРегистр;
ЭтоУдалениеОбъекта = НеобязательныеПараметры.ЭтоУдалениеОбъекта;
ЭтоКонстанта = НеобязательныеПараметры.ЭтоКонстанта;
РежимЗаписи = НеобязательныеПараметры.РежимЗаписи;
Замещение = НеобязательныеПараметры.Замещение;
Попытка
УстановитьПривилегированныйРежим(Истина);
// Обновляем повторно используемые значения Механизма регистрации объектов.
ОбменДаннымиСлужебный.ПроверитьКэшМеханизмаРегистрацииОбъектов();
Если Объект.ДополнительныеСвойства.Свойство("РегистрироватьНаУзлахПлановОбменаПриОбновленииИБ") Тогда
// Параметр РегистрироватьНаУзлахПлановОбменаПриОбновленииИБ указывает на то, что выполняется обновление данных ИБ.
ОтключитьРегистрацию = Истина;
Если Объект.ДополнительныеСвойства.РегистрироватьНаУзлахПлановОбменаПриОбновленииИБ = Неопределено Тогда
// Принятие решения о необходимости регистрации данных для обмена выполняется автоматически,
// по сопутствующей информации.
Если Не (ЭтоРегистр Или ЭтоУдалениеОбъекта Или ЭтоКонстанта) И Объект.ЭтоНовый() Тогда
// Новые ссылочные объекты должны всегда регистрироваться к обмену.
ОтключитьРегистрацию = Ложь;
ИначеЕсли ЗначениеЗаполнено(ПараметрыСеанса.ПараметрыОбработчикаОбновления) Тогда
НазначениеПланаОбмена = ОбменДаннымиПовтИсп.НазначениеПланаОбмена(ИмяПланаОбмена);
Если НазначениеПланаОбмена = "РИБСФильтром" Тогда
// Регистрация может включаться только при использовании параллельного механизма обновления.
// Если механизм используется, то регистрация определяется признаком выполнения обработчика в периферийном узле РИБ.
ПараметрыОбработчикаОбновления = ПараметрыСеанса.ПараметрыОбработчикаОбновления;
Если ПараметрыОбработчикаОбновления.РежимВыполненияОтложенныхОбработчиков = "Параллельно" Тогда
ОтключитьРегистрацию = ПараметрыОбработчикаОбновления.ЗапускатьИВПодчиненномУзлеРИБСФильтрами;
КонецЕсли;
ИначеЕсли НазначениеПланаОбмена = "РИБ" Тогда
ОтключитьРегистрацию = Не ПараметрыСеанса.ПараметрыОбработчикаОбновления.ЗапускатьТолькоВГлавномУзле;
КонецЕсли;
КонецЕсли;
ИначеЕсли Объект.ДополнительныеСвойства.РегистрироватьНаУзлахПлановОбменаПриОбновленииИБ Тогда
// Разработчик принял решение, что эти данные должны быть зарегистрированы для обмена.
ОтключитьРегистрацию = Ложь;
КонецЕсли;
Если ОтключитьРегистрацию Тогда
Возврат;
КонецЕсли;
ИначеЕсли Объект.ДополнительныеСвойства.Свойство("ОтключитьМеханизмРегистрацииОбъектов") Тогда
// Регистрация объектов отключена принудительно.
Возврат;
КонецЕсли;
ОбъектМетаданных = Объект.Метаданные();
Если ОбщегоНазначения.РазделениеВключено() Тогда
Если Не РазделенныйПланОбмена(ИмяПланаОбмена) Тогда
ВызватьИсключение НСтр("ru = 'Регистрация изменений для неразделенных планов обмена не поддерживается.'");
КонецЕсли;
Если Не ОбменДаннымиПовтИсп.ПланОбменаИспользуетсяВМоделиСервиса(ИмяПланаОбмена) Тогда
Возврат;
КонецЕсли;
Если ОбщегоНазначения.ПодсистемаСуществует("ТехнологияСервиса.БазоваяФункциональность") Тогда
МодульРаботаВМоделиСервиса = ОбщегоНазначения.ОбщийМодуль("РаботаВМоделиСервиса");
ЭтоРазделенныеДанные = МодульРаботаВМоделиСервиса.ЭтоРазделенныйОбъектМетаданных(
ОбъектМетаданных.ПолноеИмя(), МодульРаботаВМоделиСервиса.РазделительОсновныхДанных());
Иначе
ЭтоРазделенныеДанные = Ложь;
КонецЕсли;
Если ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных() Тогда
Если ОбщегоНазначения.ПодсистемаСуществует("ТехнологияСервиса.БазоваяФункциональность") Тогда
МодульРаботаВМоделиСервиса = ОбщегоНазначения.ОбщийМодуль("РаботаВМоделиСервиса");
ЭтоСовместноРазделенныеДанные = МодульРаботаВМоделиСервиса.ЭтоРазделенныйОбъектМетаданных(
ОбъектМетаданных.ПолноеИмя(), МодульРаботаВМоделиСервиса.РазделительВспомогательныхДанных());
Иначе
ЭтоСовместноРазделенныеДанные = Ложь;
КонецЕсли;
Если Не ЭтоРазделенныеДанные И Не ЭтоСовместноРазделенныеДанные Тогда
ВызватьИсключение НСтр("ru = 'Регистрация изменений неразделенных данных в разделенном режиме.'");
КонецЕсли;
Иначе
Если ЭтоРазделенныеДанные Тогда
ВызватьИсключение НСтр("ru = 'Регистрация изменений разделенных данных в неразделенном режиме.'");
КонецЕсли;
// Для неразделенных данных в неразделенном режиме выполняем регистрацию изменений данных
// на всех узлах разделенных планов обмена.
// Использование механизма правил регистрации в этом режиме не поддерживается.
ЗарегистрироватьИзмененияНаВсехУзлахРазделенныхПлановОбмена(ИмяПланаОбмена, Объект);
Возврат;
КонецЕсли;
КонецЕсли;
// Определяем необходимость регистрации объекта на узле отправителе.
Если Объект.ДополнительныеСвойства.Свойство("РегистрироватьОбъектНаУзлеОтправителе") Тогда
Объект.ОбменДанными.Отправитель = Неопределено;
КонецЕсли;
Если Не ОбменДаннымиСлужебный.ОбменДаннымиВключен(ИмяПланаОбмена, Объект.ОбменДанными.Отправитель) Тогда
Возврат;
КонецЕсли;
// При физическом удалении объекта ВРО не выполняем.
ЗарегистрироватьОбъектКВыгрузке = ЭтоРегистр Или ЭтоУдалениеОбъекта Или ЭтоКонстанта;
ОбъектМодифицирован = Объект.ДополнительныеСвойства.Свойство("ОтложеннаяЗапись")
Или Объект.ДополнительныеСвойства.Свойство("ОтложенноеПроведение")
Или ОбъектМодифицированДляПланаОбмена(
Объект, ОбъектМетаданных, ИмяПланаОбмена, РежимЗаписи, ЗарегистрироватьОбъектКВыгрузке);
Если Не ОбъектМодифицирован Тогда
Если ОбменДаннымиПовтИсп.АвтоРегистрацияРазрешена(ИмяПланаОбмена, ОбъектМетаданных.ПолноеИмя()) Тогда
// Если объект не модифицирован и он регистрируется автоматически,
// то удаляем все узлы по авторегистрации для текущего плана обмена.
СократитьПолучателей(Объект, ВсеУзлыПланаОбмена(ИмяПланаОбмена));
КонецЕсли;
// Объект не модифицирован относительно текущего плана обмена
// регистрацию на узлах этого плана обмена не выполняем.
Возврат;
КонецЕсли;
Если Не ОбменДаннымиПовтИсп.АвтоРегистрацияРазрешена(ИмяПланаОбмена, ОбъектМетаданных.ПолноеИмя()) Тогда
МассивУзловРезультат = Новый Массив;
ДополнительныеПараметры = Новый Структура;
ДополнительныеПараметры.Вставить("ОбъектМетаданных", ОбъектМетаданных);
ДополнительныеПараметры.Вставить("ЭтоРегистр", ЭтоРегистр);
ДополнительныеПараметры.Вставить("ЭтоУдалениеОбъекта", ЭтоУдалениеОбъекта);
ДополнительныеПараметры.Вставить("Замещение", Замещение);
ДополнительныеПараметры.Вставить("РежимЗаписи", РежимЗаписи);
ПроверятьСсылку = ?(ЭтоРегистр ИЛИ ЭтоКонстанта, Ложь, Не Объект.ЭтоНовый() И Не ЭтоУдалениеОбъекта);
ДополнительныеПараметры.Вставить("ПроверятьСсылку", ПроверятьСсылку);
ВыполнитьПравилаРегистрацииОбъектовДляПланаОбмена(МассивУзловРезультат, Объект, ИмяПланаОбмена, ДополнительныеПараметры);
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.РаботаВМоделиСервиса.ОбменДаннымиВМоделиСервиса") Тогда
МодульОбменДаннымиВМоделиСервиса = ОбщегоНазначения.ОбщийМодуль("ОбменДаннымиВМоделиСервиса");
МодульОбменДаннымиВМоделиСервиса.ПослеОпределенияПолучателей(Объект, МассивУзловРезультат, ИмяПланаОбмена);
КонецЕсли;
ДополнитьПолучателей(Объект, МассивУзловРезультат);
КонецЕсли;
Исключение
ОписаниеОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
НСтр("ru = 'Не удалось зарегистрировать изменения на узлах плана обмена %1 по причине: %2'"),
ИмяПланаОбмена,
ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
ЗаписьЖурналаРегистрации(НСтр("ru = 'Обмен данными.Правила регистрации объектов'", ОбщегоНазначения.КодОсновногоЯзыка()),
УровеньЖурналаРегистрации.Ошибка, Метаданные.ПланыОбмена[ИмяПланаОбмена], , ОписаниеОшибки);
ВызватьИсключение ОписаниеОшибки;
КонецПопытки;
КонецПроцедуры
Процедура ЗарегистрироватьИзмененияНаВсехУзлахРазделенныхПлановОбмена(ИмяПланаОбмена, Объект)
ШаблонТекста = "ПланОбмена.%1";
ИмяПланаОбменаСтрокой = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ШаблонТекста, ИмяПланаОбмена);
ТекстЗапроса =
"ВЫБРАТЬ
| ПланОбмена.Ссылка КАК Получатель
|ИЗ
| &ИмяПланаОбмена КАК ПланОбмена
|ГДЕ
| ПланОбмена.РегистрироватьИзменения
| И НЕ ПланОбмена.ПометкаУдаления";
Запрос = Новый Запрос;
Запрос.Текст = СтрЗаменить(ТекстЗапроса, "&ИмяПланаОбмена", ИмяПланаОбменаСтрокой);
Получатели = Запрос.Выполнить().Выгрузить().ВыгрузитьКолонку("Получатель");
Для Каждого Получатель Из Получатели Цикл
Объект.ОбменДанными.Получатели.Добавить(Получатель);
КонецЦикла;
КонецПроцедуры
#КонецОбласти
#Область МеханизмВыборочнойРегистрацииОбъектов
Функция ОбъектМодифицированДляПланаОбмена(Источник, ОбъектМетаданных, ИмяПланаОбмена, РежимЗаписи, ЗарегистрироватьОбъектКВыгрузке)
Попытка
ОбъектМодифицирован = ОбъектМодифицированДляПланаОбменаПопыткаИсключение(Источник, ОбъектМетаданных, ИмяПланаОбмена, РежимЗаписи, ЗарегистрироватьОбъектКВыгрузке);
Исключение
ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
НСтр("ru = 'Ошибка определения модифицированности объекта: %1'"),
ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
КонецПопытки;
Возврат ОбъектМодифицирован;
КонецФункции
Функция ОбъектМодифицированДляПланаОбменаПопыткаИсключение(Источник, ОбъектМетаданных, ИмяПланаОбмена, РежимЗаписи, ЗарегистрироватьОбъектКВыгрузке)
Если ЗарегистрироватьОбъектКВыгрузке Или Источник.ЭтоНовый() Или Источник.ОбменДанными.Загрузка Тогда
// Регистрируем изменения всегда
// - для наборов записей регистров,
// - при физическом удалении объектов,
// - для новых объектов,
// - для объектов записанных по обмену данными.
Возврат Истина;
ИначеЕсли РежимЗаписи <> Неопределено И ИзмененоПроведениеДокумента(Источник, РежимЗаписи) Тогда
// Если изменен признак документа "Проведен", то считаем документ измененным.
Возврат Истина;
КонецЕсли;
ИмяОбъекта = ОбъектМетаданных.ПолноеИмя();
ТаблицаРеквизитовРегистрации = ОбменДаннымиПовтИсп.РеквизитыОбъектаДляРегистрации(ИмяОбъекта, ИмяПланаОбмена);
Если ТаблицаРеквизитовРегистрации.Количество() = 0 Тогда
// Если правила ВРО не заданы, то считаем, что фильтра ВРО нет.
// Объект модифицирован всегда.
Возврат Истина;
КонецЕсли;
Для Каждого СтрокаТаблицыРеквизитовРегистрации Из ТаблицаРеквизитовРегистрации Цикл
ЕстьИзмененияВерсийОбъектов = ОпределитьИзмененияВерсийОбъекта(Источник, СтрокаТаблицыРеквизитовРегистрации);
Если ЕстьИзмененияВерсийОбъектов Тогда
Возврат Истина;
КонецЕсли;
КонецЦикла;
// Если дошли до конца, то объект не изменился по реквизитам регистрации. Регистрация на узлах не нужна.
Возврат Ложь;
КонецФункции
Функция ОбъектМодифицированПоРеквизитам(Источник, ТаблицаРеквизитовСсылочногоТипа)
Для Каждого СтрокаТаблицы Из ТаблицаРеквизитовСсылочногоТипа Цикл
ЕстьИзмененияВерсийОбъектов = ОпределитьИзмененияВерсийОбъекта(Источник, СтрокаТаблицы);
Если ЕстьИзмененияВерсийОбъектов Тогда
Возврат Истина;
КонецЕсли;
КонецЦикла;
Возврат Ложь;
КонецФункции
Функция ОпределитьИзмененияВерсийОбъекта(Объект, СтрокаТаблицыРеквизитовРегистрации)
Если ПустаяСтрока(СтрокаТаблицыРеквизитовРегистрации.ИмяТабличнойЧасти) Тогда // реквизиты Шапки объекта
ТаблицаРеквизитовРегистрацииВерсияОбъектаДоИзменения = РеквизитыРегистрацииШапкиДоИзменения(Объект, СтрокаТаблицыРеквизитовРегистрации);
ТаблицаРеквизитовРегистрацииВерсияОбъектаПослеИзменения = РеквизитыРегистрацииШапкиПослеИзменения(Объект, СтрокаТаблицыРеквизитовРегистрации);
Иначе // реквизиты ТЧ объекта
// Проверка, что это ТЧ объекта, а не таблица регистра.
Если Объект.Метаданные().ТабличныеЧасти.Найти(СтрокаТаблицыРеквизитовРегистрации.ИмяТабличнойЧасти) = Неопределено Тогда
Возврат Ложь;
КонецЕсли;
ТаблицаРеквизитовРегистрацииВерсияОбъектаДоИзменения = РеквизитыРегистрацииТабличнойЧастиДоИзменения(Объект, СтрокаТаблицыРеквизитовРегистрации);
ТаблицаРеквизитовРегистрацииВерсияОбъектаПослеИзменения = РеквизитыРегистрацииТабличнойЧастиПослеИзменения(Объект, СтрокаТаблицыРеквизитовРегистрации);
КонецЕсли;
Возврат Не ТаблицыРеквизитовРегистрацииОдинаковые(ТаблицаРеквизитовРегистрацииВерсияОбъектаДоИзменения, ТаблицаРеквизитовРегистрацииВерсияОбъектаПослеИзменения, СтрокаТаблицыРеквизитовРегистрации);
КонецФункции
Функция РеквизитыРегистрацииШапкиДоИзменения(Объект, СтрокаТаблицыРеквизитовРегистрации)
ШаблонТекстаЗапроса =
"ВЫБРАТЬ
| &РеквизитыРегистрации
|ИЗ
| &ИмяТаблицыМетаданных КАК ТекущийОбъект
|ГДЕ
| ТекущийОбъект.Ссылка = &Ссылка";
ТекстЗапроса = СтрЗаменить(ШаблонТекстаЗапроса, "&РеквизитыРегистрации", СтрокаТаблицыРеквизитовРегистрации.РеквизитыРегистрации);
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&ИмяТаблицыМетаданных", СтрокаТаблицыРеквизитовРегистрации.ИмяОбъекта);
Запрос = Новый Запрос(ТекстЗапроса);
Запрос.УстановитьПараметр("Ссылка", Объект.Ссылка);
Возврат Запрос.Выполнить().Выгрузить();
КонецФункции
Функция РеквизитыРегистрацииТабличнойЧастиДоИзменения(Объект, СтрокаТаблицыРеквизитовРегистрации)
ШаблонТекстаЗапроса =
"ВЫБРАТЬ
| &РеквизитыРегистрации
|ИЗ
| &ИмяТаблицыМетаданных КАК ТекущийОбъектИмяТабличнойЧасти
|ГДЕ
| ТекущийОбъектИмяТабличнойЧасти.Ссылка = &Ссылка";
СтрокаЗамены = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку("%1.%2", СтрокаТаблицыРеквизитовРегистрации.ИмяОбъекта, СтрокаТаблицыРеквизитовРегистрации.ИмяТабличнойЧасти);
ТекстЗапроса = СтрЗаменить(ШаблонТекстаЗапроса, "&РеквизитыРегистрации", СтрокаТаблицыРеквизитовРегистрации.РеквизитыРегистрации);
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&ИмяТаблицыМетаданных", СтрокаЗамены);
Запрос = Новый Запрос(ТекстЗапроса);
Запрос.УстановитьПараметр("Ссылка", Объект.Ссылка);
Возврат Запрос.Выполнить().Выгрузить();
КонецФункции
Функция РеквизитыРегистрацииШапкиПослеИзменения(Объект, СтрокаТаблицыРеквизитовРегистрации)
СтруктураРеквизитовРегистрации = СтрокаТаблицыРеквизитовРегистрации.СтруктураРеквизитовРегистрации;
ТаблицаРеквизитовРегистрации = Новый ТаблицаЗначений;
Для Каждого РеквизитРегистрации Из СтруктураРеквизитовРегистрации Цикл
ТаблицаРеквизитовРегистрации.Колонки.Добавить(РеквизитРегистрации.Ключ);
КонецЦикла;
СтрокаТаблицы = ТаблицаРеквизитовРегистрации.Добавить();
Для Каждого РеквизитРегистрации Из СтруктураРеквизитовРегистрации Цикл
СтрокаТаблицы[РеквизитРегистрации.Ключ] = Объект[РеквизитРегистрации.Ключ];
КонецЦикла;
Возврат ТаблицаРеквизитовРегистрации;
КонецФункции
Функция РеквизитыРегистрацииТабличнойЧастиПослеИзменения(Объект, СтрокаТаблицыРеквизитовРегистрации)
ТаблицаРеквизитовРегистрации = Объект[СтрокаТаблицыРеквизитовРегистрации.ИмяТабличнойЧасти].Выгрузить(, СтрокаТаблицыРеквизитовРегистрации.РеквизитыРегистрации);
Возврат ТаблицаРеквизитовРегистрации;
КонецФункции
Функция ТаблицыРеквизитовРегистрацииОдинаковые(Таблица1, Таблица2, СтрокаТаблицыРеквизитовРегистрации)
ДобавитьКолонкуСоЗначениемВТаблицу(Таблица1, +1);
ДобавитьКолонкуСоЗначениемВТаблицу(Таблица2, -1);
ТаблицаРезультат = Таблица1.Скопировать();
ОбщегоНазначенияКлиентСервер.ДополнитьТаблицу(Таблица2, ТаблицаРезультат);
ТаблицаРезультат.Свернуть(СтрокаТаблицыРеквизитовРегистрации.РеквизитыРегистрации, "ИтераторТаблицыРеквизитовРегистрации");
КоличествоОдинаковыхСтрок = ТаблицаРезультат.НайтиСтроки(Новый Структура ("ИтераторТаблицыРеквизитовРегистрации", 0)).Количество();
КоличествоСтрокТаблицы = ТаблицаРезультат.Количество();
Возврат КоличествоОдинаковыхСтрок = КоличествоСтрокТаблицы;
КонецФункции
Функция ИзмененоПроведениеДокумента(Источник, РежимЗаписи)
Возврат (Источник.Проведен И РежимЗаписи = РежимЗаписиДокумента.ОтменаПроведения)
ИЛИ (НЕ Источник.Проведен И РежимЗаписи = РежимЗаписиДокумента.Проведение);
КонецФункции
Процедура ДобавитьКолонкуСоЗначениемВТаблицу(Таблица, ЗначениеИтератора)
Таблица.Колонки.Добавить("ИтераторТаблицыРеквизитовРегистрации");
Таблица.ЗаполнитьЗначения(ЗначениеИтератора, "ИтераторТаблицыРеквизитовРегистрации");
КонецПроцедуры
#КонецОбласти
#Область ПравилаРегистрацииОбъектов
// Процедура-обертка, выполняет код основной процедуры в режиме попытки
// (см. ВыполнитьПравилаРегистрацииОбъектовДляПланаОбменаПопыткаИсключение).
//
// Параметры:
// МассивУзловРезультат - Массив - массив узлов получателей плана обмена ИмяПланаОбмена,
// для которых необходимо выполнить регистрацию.
// Объект - Произвольный - изменяемые данные: объект, набор записей, константа или сведения об удалении объекта.
// ИмяПланаОбмена - Строка - имя плана обмена, для которого выполняется механизм регистрации.
// ДополнительныеПараметры - Структура - уточняющие сведения об изменяемых данных:
// * ОбъектМетаданных - ОбъектМетаданных - объект метаданных, которому соответствуют изменяемые данные. Обязательный.
// * ЭтоРегистр - Булево - значение Истина означает, что обрабатывается регистр.
// Необязательный, значение по умолчанию Ложь.
// * ЭтоУдалениеОбъекта - Булево - значение Истина означает, что обрабатывается удаление объекта.
// Необязательный, значение по умолчанию Ложь.
// * РежимЗаписи - см. в синтакс-помощнике РежимЗаписиДокумента - режим записи документа (только для документов).
// Необязательный, значение по умолчанию Неопределено.
// * Замещение - Булево - режим записи регистра (только для регистров).
// Необязательный, значение по умолчанию Неопределено.
// * ПроверятьСсылку - Булево - признак необходимости учитывать версию данных на момент до их изменения.
// Необязательный, значение по умолчанию Ложь.
// * Выгрузка - Булево - параметр определяет контекст выполнения правила регистрации.
// Истина - правило регистрации выполняется в контексте выгрузки объекта.
// Ложь - правило регистрации выполняется в контексте перед записью объекта.
// Необязательный, значение по умолчанию Ложь.
//
Процедура ВыполнитьПравилаРегистрацииОбъектовДляПланаОбмена(МассивУзловРезультат, Объект, ИмяПланаОбмена, ДополнительныеПараметры)
ОбъектМетаданных = ДополнительныеПараметры.ОбъектМетаданных;
НеобязательныеПараметры = Новый Структура;
НеобязательныеПараметры.Вставить("ЭтоРегистр", Ложь);
НеобязательныеПараметры.Вставить("ЭтоУдалениеОбъекта", Ложь);
НеобязательныеПараметры.Вставить("РежимЗаписи", Неопределено);
НеобязательныеПараметры.Вставить("Замещение", Ложь);
НеобязательныеПараметры.Вставить("ПроверятьСсылку", Ложь);
НеобязательныеПараметры.Вставить("Выгрузка", Ложь);
ЗаполнитьЗначенияСвойств(НеобязательныеПараметры, ДополнительныеПараметры);
ДополнительныеПараметры = НеобязательныеПараметры;
ДополнительныеПараметры.Вставить("ОбъектМетаданных", ОбъектМетаданных);
Попытка
ВыполнитьПравилаРегистрацииОбъектовДляПланаОбменаПопыткаИсключение(МассивУзловРезультат, Объект, ИмяПланаОбмена, ДополнительныеПараметры);
Исключение
ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
НСтр("ru = 'Ошибка выполнения правил регистрации объектов для плана обмена %1.
|Описание ошибки:
|%2'"),
ИмяПланаОбмена,
ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
КонецПопытки;
КонецПроцедуры
// Определяет список узлов получателей плана обмена ИмяПланаОбмена, для которых необходимо выполнить
// регистрацию объекта Объект для последующей его выгрузки.
//
// Параметры:
// МассивУзловРезультат - Массив - массив узлов получателей плана обмена ИмяПланаОбмена,
// для которых необходимо выполнить регистрацию.
// Объект - Произвольный - изменяемые данные: объект, набор записей, константа или сведения об удалении объекта.
// ИмяПланаОбмена - Строка - имя плана обмена, для которого выполняется механизм регистрации.
// ДополнительныеПараметры - Структура - уточняющие сведения об изменяемых данных:
// * ОбъектМетаданных - ОбъектМетаданных - объект метаданных, которому соответствуют изменяемые данные. Обязательный.
// * ЭтоРегистр - Булево - значение Истина означает, что обрабатывается регистр. Обязательный.
// * ЭтоУдалениеОбъекта - Булево - значение Истина означает, что обрабатывается удаление объекта. Обязательный.
// * РежимЗаписи - см. в синтакс-помощнике РежимЗаписиДокумента - режим записи документа (только для документов).
// Обязательный.
// * Замещение - Булево - режим записи регистра (только для регистров). Обязательный.
// * ПроверятьСсылку - Булево - признак необходимости учитывать версию данных на момент до их изменения.
// Обязательный.
// * Выгрузка - Булево - параметр определяет контекст выполнения правила регистрации.
// Истина - правило регистрации выполняется в контексте выгрузки объекта.
// Ложь - правило регистрации выполняется в контексте перед записью объекта. Обязательный.
//
Процедура ВыполнитьПравилаРегистрацииОбъектовДляПланаОбменаПопыткаИсключение(МассивУзловРезультат, Объект, ИмяПланаОбмена, ДополнительныеПараметры)
ОбъектМетаданных = ДополнительныеПараметры.ОбъектМетаданных;
ЭтоРегистр = ДополнительныеПараметры.ЭтоРегистр;
Замещение = ДополнительныеПараметры.Замещение;
Выгрузка = ДополнительныеПараметры.Выгрузка;
ПравилаРегистрацииОбъекта = Новый Массив;
ИмяПрофиляБезопасности = ОбменДаннымиПовтИсп.ИмяПрофиляБезопасности(ИмяПланаОбмена);
Если ИмяПрофиляБезопасности <> Неопределено Тогда
УстановитьБезопасныйРежим(ИмяПрофиляБезопасности);
КонецЕсли;
Правила = ПравилаРегистрацииОбъекта(ИмяПланаОбмена, ОбъектМетаданных.ПолноеИмя());
Для Каждого Правило Из Правила Цикл
ПравилаРегистрацииОбъекта.Добавить(ПравилоРегистрацииСтруктурой(Правило, Правила.Колонки));
КонецЦикла;
Если ПравилаРегистрацииОбъекта.Количество() = 0 Тогда // Правила регистрации не заданы.
// Если для объекта не созданы ПРО и отключена авторегистрация,
// то регистрируем объект на всех узлах плана обмена кроме предопределенного.
Получатели = ВсеУзлыПланаОбмена(ИмяПланаОбмена);
ОбщегоНазначенияКлиентСервер.ДополнитьМассив(МассивУзловРезультат, Получатели, Истина);
Иначе // Последовательно выполняем правила регистрации.
Если ЭтоРегистр Тогда // для регистра
Для Каждого ПРО Из ПравилаРегистрацииОбъекта Цикл
// ОПРЕДЕЛЯЕМ ПОЛУЧАТЕЛЕЙ С РЕЖИМОМ ВЫГРУЗКИ "ПО УСЛОВИЮ"
ОпределитьПолучателейПоУсловиюДляНабораЗаписей(МассивУзловРезультат, ПРО, Объект, ОбъектМетаданных, ИмяПланаОбмена, Замещение, Выгрузка);
Если ЗначениеЗаполнено(ПРО.ИмяРеквизитаФлага) Тогда
// ОПРЕДЕЛЯЕМ ПОЛУЧАТЕЛЕЙ С РЕЖИМОМ ВЫГРУЗКИ "ВСЕГДА"
УстановитьПривилегированныйРежим(Истина);
Получатели = УзлыДляРегистрацииПоУсловиюВыгружатьВсегда(ИмяПланаОбмена, ПРО.ИмяРеквизитаФлага);
УстановитьПривилегированныйРежим(Ложь);
ОбщегоНазначенияКлиентСервер.ДополнитьМассив(МассивУзловРезультат, Получатели, Истина);
// ОПРЕДЕЛЯЕМ ПОЛУЧАТЕЛЕЙ С РЕЖИМОМ ВЫГРУЗКИ "ПРИ НЕОБХОДИМОСТИ"
// для наборов записей выполнение регистрации "при необходимости" не имеет физического смысла.
КонецЕсли;
КонецЦикла;
Иначе // для ссылочного типа
Для Каждого ПРО Из ПравилаРегистрацииОбъекта Цикл
// ОПРЕДЕЛЯЕМ ПОЛУЧАТЕЛЕЙ С РЕЖИМОМ ВЫГРУЗКИ "ПО УСЛОВИЮ"
ОпределитьПолучателейПоУсловию(МассивУзловРезультат, ПРО, Объект, ИмяПланаОбмена, ДополнительныеПараметры);
Если ЗначениеЗаполнено(ПРО.ИмяРеквизитаФлага) Тогда
// ОПРЕДЕЛЯЕМ ПОЛУЧАТЕЛЕЙ С РЕЖИМОМ ВЫГРУЗКИ "ВСЕГДА"
УстановитьПривилегированныйРежим(Истина);
Получатели = УзлыДляРегистрацииПоУсловиюВыгружатьВсегда(ИмяПланаОбмена, ПРО.ИмяРеквизитаФлага);
УстановитьПривилегированныйРежим(Ложь);
ОбщегоНазначенияКлиентСервер.ДополнитьМассив(МассивУзловРезультат, Получатели, Истина);
// ОПРЕДЕЛЯЕМ ПОЛУЧАТЕЛЕЙ С РЕЖИМОМ ВЫГРУЗКИ "ПРИ НЕОБХОДИМОСТИ"
Если Не Объект.ЭтоНовый() Тогда
УстановитьПривилегированныйРежим(Истина);
Получатели = УзлыДляРегистрацииПоУсловиюВыгружатьПриНеобходимости(Объект.Ссылка, ИмяПланаОбмена, ПРО.ИмяРеквизитаФлага);
УстановитьПривилегированныйРежим(Ложь);
ОбщегоНазначенияКлиентСервер.ДополнитьМассив(МассивУзловРезультат, Получатели, Истина);
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
// Получает массив узлов плана обмена, для которых установлен признак "Выгружать всегда".
//
// Параметры:
// ИмяПланаОбмена - Строка - имя плана обмена, как объекта метаданных, по которому определяются узлы.
// ИмяРеквизитаФлага - Строка - имя реквизита плана обмена, по которому устанавливается фильтр на выборку узлов.
//
// Возвращаемое значение:
// Массив - массив узлов плана обмена, для которых установлен признак "Выгружать всегда".
//
Функция УзлыДляРегистрацииПоУсловиюВыгружатьВсегда(Знач ИмяПланаОбмена, Знач ИмяРеквизитаФлага)
ШаблонТекста = "ПланОбмена.%1";
ИмяПланаОбменаСтрокой = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ШаблонТекста, ИмяПланаОбмена);
ШаблонТекстаПоле = "ШапкаПланаОбмена.%1";
ИмяРеквизитаФлагаСтрокой = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ШаблонТекстаПоле, ИмяРеквизитаФлага);
ТекстЗапроса = "ВЫБРАТЬ
| ШапкаПланаОбмена.Ссылка КАК Узел
|ИЗ
| &ИмяПланаОбмена КАК ШапкаПланаОбмена
|ГДЕ
| НЕ ШапкаПланаОбмена.ЭтотУзел
| И &ИмяРеквизитаФлага = ЗНАЧЕНИЕ(Перечисление.РежимыВыгрузкиОбъектовОбмена.ВыгружатьВсегда)
| И НЕ ШапкаПланаОбмена.ПометкаУдаления";
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&ИмяПланаОбмена", ИмяПланаОбменаСтрокой);
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&ИмяРеквизитаФлага", ИмяРеквизитаФлагаСтрокой);
Запрос = Новый Запрос;
Запрос.Текст = ТекстЗапроса;
Возврат Запрос.Выполнить().Выгрузить().ВыгрузитьКолонку("Узел");
КонецФункции
// Получает массив узлов плана обмена, для которых установлен признак "Выгружать при необходимости".
//
// Параметры:
// Ссылка - ссылка на объект ИБ, для которого необходимо получить массив узлов, в которые объект ранее выгружался.
// ИмяПланаОбмена - Строка - имя плана обмена, как объекта метаданных, по которому определяются узлы.
// ИмяРеквизитаФлага - Строка - имя реквизита плана обмена, по которому устанавливается фильтр на выборку узлов.
//
// Возвращаемое значение:
// Массив - массив узлов плана обмена, для которых установлен признак "Выгружать при необходимости".
//
Функция УзлыДляРегистрацииПоУсловиюВыгружатьПриНеобходимости(Ссылка, Знач ИмяПланаОбмена, Знач ИмяРеквизитаФлага)
МассивУзлов = Новый Массив;
Если ОбменДаннымиСервер.ЭтоПланОбменаXDTO(ИмяПланаОбмена) Тогда
МассивУзлов = ОбменДаннымиXDTOСервер.МассивУзловДляРегистрацииВыгружатьПриНеобходимости(
Ссылка, ИмяПланаОбмена, ИмяРеквизитаФлага);
Иначе
ШаблонТекстаТаблица = "ПланОбмена.%1";
ИмяПланаОбменаСтрокой = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ШаблонТекстаТаблица, ИмяПланаОбмена);
ШаблонТекстаПоле = "ШапкаПланаОбмена.%1";
ИмяРеквизитаФлагаСтрокой = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ШаблонТекстаПоле, ИмяРеквизитаФлага);
ТекстЗапроса = "ВЫБРАТЬ РАЗЛИЧНЫЕ
| ШапкаПланаОбмена.Ссылка КАК Узел
|ИЗ
| &ИмяПланаОбмена КАК ШапкаПланаОбмена
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.СоответствияОбъектовИнформационныхБаз КАК СоответствияОбъектовИнформационныхБаз
| ПО ШапкаПланаОбмена.Ссылка = СоответствияОбъектовИнформационныхБаз.УзелИнформационнойБазы
| И СоответствияОбъектовИнформационныхБаз.УникальныйИдентификаторИсточника = &Объект
|ГДЕ
| НЕ ШапкаПланаОбмена.ЭтотУзел
| И &ИмяРеквизитаФлага = ЗНАЧЕНИЕ(Перечисление.РежимыВыгрузкиОбъектовОбмена.ВыгружатьПриНеобходимости)
| И НЕ ШапкаПланаОбмена.ПометкаУдаления
| И СоответствияОбъектовИнформационныхБаз.УникальныйИдентификаторИсточника = &Объект";
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&ИмяПланаОбмена", ИмяПланаОбменаСтрокой);
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&ИмяРеквизитаФлага", ИмяРеквизитаФлагаСтрокой);
Запрос = Новый Запрос;
Запрос.Текст = ТекстЗапроса;
Запрос.УстановитьПараметр("Объект", Ссылка);
МассивУзлов = Запрос.Выполнить().Выгрузить().ВыгрузитьКолонку("Узел");
КонецЕсли;
Возврат МассивУзлов;
КонецФункции
Процедура ВыполнитьПравилоРегистрацииОбъектаДляНабораЗаписей(МассивУзловРезультат,
ПРО,
Объект,
ОбъектМетаданных,
ИмяПланаОбмена,
Замещение,
Выгрузка)
// Определяем массив узлов-получателей по текущему набору записей.
ОпределитьМассивПолучателейПоНаборуЗаписей(МассивУзловРезультат, Объект, ПРО, ОбъектМетаданных, ИмяПланаОбмена, Ложь, Выгрузка);
Если Замещение И Не Выгрузка Тогда
СтарыйНаборЗаписей = НаборЗаписей(Объект);
// Определяем массив узлов-получателей по старому набору записей.
ОпределитьМассивПолучателейПоНаборуЗаписей(МассивУзловРезультат, СтарыйНаборЗаписей, ПРО, ОбъектМетаданных, ИмяПланаОбмена, Истина, Ложь);
КонецЕсли;
КонецПроцедуры
// Определяет список узлов получателей плана обмена ИмяПланаОбмена, для которых необходимо выполнить
// регистрацию объекта Объект в соответствии с ПРО (универсальную часть) для последующей его выгрузки.
//
// Параметры:
// МассивУзловРезультат - Массив - массив узлов получателей плана обмена ИмяПланаОбмена,
// для которых необходимо выполнить регистрацию.
// ПРО - СтрокаТаблицыЗначений - содержит сведения о правиле регистрации объектов, для которого выполняется процедура.
// Объект - Произвольный - изменяемые данные: объект, набор записей, константа или сведения об удалении объекта.
// ИмяПланаОбмена - Строка - имя плана обмена, для которого выполняется механизм регистрации.
// ДополнительныеПараметры - Структура - уточняющие сведения об изменяемых данных:
// * ЭтоУдалениеОбъекта - Булево - значение Истина означает, что обрабатывается удаление объекта. Обязательный.
// * РежимЗаписи - см. в синтакс-помощнике РежимЗаписиДокумента - режим записи документа (только для документов).
// Обязательный.
// * ПроверятьСсылку - Булево - признак необходимости учитывать версию данных на момент до их изменения.
// Обязательный.
// * Выгрузка - Булево - параметр определяет контекст выполнения правила регистрации.
// Истина - правило регистрации выполняется в контексте выгрузки объекта.
// Ложь - правило регистрации выполняется в контексте перед записью объекта. Обязательный.
//
Процедура ВыполнитьПравилоРегистрацииОбъектаДляСсылочногоТипа(МассивУзловРезультат,
ПРО,
Объект,
ИмяПланаОбмена,
ДополнительныеПараметры)
ЭтоУдалениеОбъекта = ДополнительныеПараметры.ЭтоУдалениеОбъекта;
РежимЗаписи = ДополнительныеПараметры.РежимЗаписи;
ПроверятьСсылку = ДополнительныеПараметры.ПроверятьСсылку;
Выгрузка = ДополнительныеПараметры.Выгрузка;
// ПРОБ - Правила регистрации по свойствам Объекта.
// ПРОП - Правила регистрации по свойствам Плана обмена.
// ПРО = ПРОБ <И> ПРОП
// ПРОБ
Если Не ПРО.ПравилоПоСвойствамОбъектаПустое
И Не ОбъектПрошелФильтрПравилРегистрацииПоСвойствам(ПРО, Объект, ПроверятьСсылку, РежимЗаписи) Тогда
Возврат;
КонецЕсли;
// ПРОП
// определяем узлы для регистрации объекта.
ОпределитьМассивУзловДляОбъекта(МассивУзловРезультат, Объект, ИмяПланаОбмена, ПРО, ЭтоУдалениеОбъекта, ПроверятьСсылку, Выгрузка);
КонецПроцедуры
// Определяет список узлов получателей плана обмена ИмяПланаОбмена, для которых необходимо выполнить
// регистрацию объекта Объект в соответствии с ПРО для последующей его выгрузки.
//
// Параметры:
// МассивУзловРезультат - Массив - массив узлов получателей плана обмена ИмяПланаОбмена,
// для которых необходимо выполнить регистрацию.
// ПРО - СтрокаТаблицыЗначений - содержит сведения о правиле регистрации объектов, для которого выполняется процедура.
// Объект - Произвольный - изменяемые данные: объект, набор записей, константа или сведения об удалении объекта.
// ИмяПланаОбмена - Строка - имя плана обмена, для которого выполняется механизм регистрации.
// ДополнительныеПараметры - Структура - уточняющие сведения об изменяемых данных:
// * ОбъектМетаданных - ОбъектМетаданных - объект метаданных, которому соответствуют изменяемые данные. Обязательный.
// * ЭтоУдалениеОбъекта - Булево - значение Истина означает, что обрабатывается удаление объекта. Обязательный.
// * РежимЗаписи - см. в синтакс-помощнике РежимЗаписиДокумента - режим записи документа (только для документов).
// Обязательный.
// * ПроверятьСсылку - Булево - признак необходимости учитывать версию данных на момент до их изменения.
// Обязательный.
// * Выгрузка - Булево - параметр определяет контекст выполнения правила регистрации.
// Истина - правило регистрации выполняется в контексте выгрузки объекта.
// Ложь - правило регистрации выполняется в контексте перед записью объекта. Обязательный.
//
Процедура ОпределитьПолучателейПоУсловию(МассивУзловРезультат, ПРО, Объект, ИмяПланаОбмена, ДополнительныеПараметры)
ОбъектМетаданных = ДополнительныеПараметры.ОбъектМетаданных;
Выгрузка = ДополнительныеПараметры.Выгрузка;
// {Обработчик: Перед обработкой} Начало.
Отказ = Ложь;
ВыполнитьОбработчикПРОПередОбработкой(ПРО, Отказ, Объект, ОбъектМетаданных, Выгрузка);
Если Отказ Тогда
Возврат;
КонецЕсли;
// {Обработчик: Перед обработкой} Окончание.
Получатели = Новый Массив;
ВыполнитьПравилоРегистрацииОбъектаДляСсылочногоТипа(Получатели, ПРО, Объект, ИмяПланаОбмена, ДополнительныеПараметры);
// {Обработчик: После обработки} Начало.
Отказ = Ложь;
ВыполнитьОбработчикПРОПослеОбработки(ПРО, Отказ, Объект, ОбъектМетаданных, Получатели, Выгрузка);
Если Отказ Тогда
Возврат;
КонецЕсли;
// {Обработчик: После обработки} Окончание.
ОбщегоНазначенияКлиентСервер.ДополнитьМассив(МассивУзловРезультат, Получатели, Истина);
КонецПроцедуры
Процедура ОпределитьПолучателейПоУсловиюДляНабораЗаписей(МассивУзловРезультат,
ПРО,
Объект,
ОбъектМетаданных,
ИмяПланаОбмена,
Замещение,
Выгрузка)
// {Обработчик: Перед обработкой} Начало.
Отказ = Ложь;
ВыполнитьОбработчикПРОПередОбработкой(ПРО, Отказ, Объект, ОбъектМетаданных, Выгрузка);
Если Отказ Тогда
Возврат;
КонецЕсли;
// {Обработчик: Перед обработкой} Окончание.
Получатели = Новый Массив;
ВыполнитьПравилоРегистрацииОбъектаДляНабораЗаписей(Получатели, ПРО, Объект, ОбъектМетаданных, ИмяПланаОбмена, Замещение, Выгрузка);
// {Обработчик: После обработки} Начало.
Отказ = Ложь;
ВыполнитьОбработчикПРОПослеОбработки(ПРО, Отказ, Объект, ОбъектМетаданных, Получатели, Выгрузка);
Если Отказ Тогда
Возврат;
КонецЕсли;
// {Обработчик: После обработки} Окончание.
ОбщегоНазначенияКлиентСервер.ДополнитьМассив(МассивУзловРезультат, Получатели, Истина);
КонецПроцедуры
Процедура ОпределитьМассивУзловДляОбъекта(МассивУзловРезультат,
Источник,
ИмяПланаОбмена,
ПРО,
ЭтоУдалениеОбъекта,
ПроверятьСсылку,
Выгрузка)
// Получаем структуру значений свойств для объекта.
ЗначенияСвойствОбъекта = ЗначенияСвойствДляОбъекта(Источник, ПРО);
// Определяем массив узлов для регистрации объекта.
МассивУзлов = ОпределитьМассивУзловПоЗначениямСвойств(ЗначенияСвойствОбъекта, ПРО, ИмяПланаОбмена, Источник, Выгрузка);
// Добавляем узлы для регистрации.
ОбщегоНазначенияКлиентСервер.ДополнитьМассив(МассивУзловРезультат, МассивУзлов, Истина);
Если ПроверятьСсылку Тогда
// Получаем структуру значений свойств для ссылки.
УстановитьПривилегированныйРежим(Истина);
ЗначенияСвойствСсылки = ЗначенияСвойствДляСсылки(Источник.Ссылка, ПРО.СвойстваОбъекта, ПРО.СвойстваОбъектаСтрокой, ПРО.ОбъектМетаданныхИмя);
УстановитьПривилегированныйРежим(Ложь);
// Определяем массив узлов для регистрации ссылки.
МассивУзлов = ОпределитьМассивУзловПоЗначениямСвойствДополнительный(ЗначенияСвойствСсылки, ПРО, ИмяПланаОбмена, Источник);
// Добавляем узлы для регистрации.
ОбщегоНазначенияКлиентСервер.ДополнитьМассив(МассивУзловРезультат, МассивУзлов, Истина);
КонецЕсли;
КонецПроцедуры
Процедура ОпределитьМассивПолучателейПоНаборуЗаписей(МассивУзловРезультат,
НаборЗаписей,
ПРО,
ОбъектМетаданных,
ИмяПланаОбмена,
ЭтоВерсияОбъектаДоИзменения,
Выгрузка)
// Получаем значение регистратора из отбора для набора записей.
Регистратор = Неопределено;
ЭлементОтбора = НаборЗаписей.Отбор.Найти("Регистратор");
ЕстьРегистратор = ЭлементОтбора <> Неопределено;
Если ЕстьРегистратор Тогда
Регистратор = ЭлементОтбора.Значение;
КонецЕсли;
ПРО_СтрокиНабора = СкопироватьСтруктуру(ПРО);
Для Каждого СтрокаНабора Из НаборЗаписей Цикл
Если ЕстьРегистратор И СтрокаНабора["Регистратор"] = Неопределено Тогда
Если Регистратор <> Неопределено Тогда
СтрокаНабора["Регистратор"] = Регистратор;
КонецЕсли;
КонецЕсли;
// ПРОБ
Если Не ОбъектПрошелФильтрПравилРегистрацииПоСвойствам(ПРО_СтрокиНабора, СтрокаНабора, Ложь) Тогда
Продолжить;
КонецЕсли;
// ПРОП
// Получаем структуру значений свойств для объекта.
ЗначенияСвойствОбъекта = ЗначенияСвойствДляОбъекта(СтрокаНабора, ПРО_СтрокиНабора);
Если ЭтоВерсияОбъектаДоИзменения Тогда
// Определяем массив узлов для регистрации объекта.
МассивУзлов = ОпределитьМассивУзловПоЗначениямСвойствДополнительный(ЗначенияСвойствОбъекта,
ПРО_СтрокиНабора, ИмяПланаОбмена, СтрокаНабора, НаборЗаписей.ДополнительныеСвойства);
Иначе
// Определяем массив узлов для регистрации объекта.
МассивУзлов = ОпределитьМассивУзловПоЗначениямСвойств(ЗначенияСвойствОбъекта, ПРО_СтрокиНабора,
ИмяПланаОбмена, СтрокаНабора, Выгрузка, НаборЗаписей.ДополнительныеСвойства);
КонецЕсли;
// Добавляем узлы для регистрации.
ОбщегоНазначенияКлиентСервер.ДополнитьМассив(МассивУзловРезультат, МассивУзлов, Истина);
КонецЦикла;
КонецПроцедуры
// Возвращает структуру со значениями свойств объекта, полученных запросом из ИБ.
// Ключ структуры - имя свойства; Значение - значение свойства объекта.
//
// Параметры:
// Ссылка - ссылка на объект ИБ, значения свойств которого требуется получить.
//
// Возвращаемое значение:
// Структура - структура со значениями свойств объекта.
//
Функция ЗначенияСвойствДляСсылки(Ссылка, СвойстваОбъекта, Знач СвойстваОбъектаСтрокой, Знач ОбъектМетаданныхИмя)
ЗначенияСвойств = СкопироватьСтруктуру(СвойстваОбъекта);
Если ЗначенияСвойств.Количество() = 0 Тогда
Возврат ЗначенияСвойств; // Возвращаем пустую структуру.
КонецЕсли;
ТекстЗапроса =
"ВЫБРАТЬ
| &СвойстваОбъектаСтрокой
|ИЗ
| &ОбъектМетаданныхИмя КАК Таблица
|ГДЕ
| Таблица.Ссылка = &Ссылка";
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&СвойстваОбъектаСтрокой", СвойстваОбъектаСтрокой);
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&ОбъектМетаданныхИмя", ОбъектМетаданныхИмя);
Запрос = Новый Запрос;
Запрос.Текст = ТекстЗапроса;
Запрос.УстановитьПараметр("Ссылка", Ссылка);
Попытка
Выборка = Запрос.Выполнить().Выбрать();
Исключение
СтрокаСообщения = НСтр("ru = 'Ошибка при получении свойств ссылки. Ошибка выполнения запроса: [ОписаниеОшибки]'");
СтрокаСообщения = СтрЗаменить(СтрокаСообщения, "[ОписаниеОшибки]", ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
ВызватьИсключение СтрокаСообщения;
КонецПопытки;
Если Выборка.Следующий() Тогда
Для Каждого Элемент Из ЗначенияСвойств Цикл
ЗначенияСвойств[Элемент.Ключ] = Выборка[Элемент.Ключ];
КонецЦикла;
КонецЕсли;
Возврат ЗначенияСвойств;
КонецФункции
Функция ОпределитьМассивУзловПоЗначениямСвойств(ЗначенияСвойств, ПРО, Знач ИмяПланаОбмена, Объект, Знач Выгрузка, ДополнительныеСвойства = Неопределено)
ИспользоватьКэш = Истина;
ТекстЗапроса = ПРО.ТекстЗапроса;
// {Обработчик: При обработке} Начало.
Отказ = Ложь;
ДополнительныеПараметры = Новый Структура;
ДополнительныеПараметры.Вставить("ТекстЗапроса", ТекстЗапроса);
ДополнительныеПараметры.Вставить("ПараметрыЗапроса", ЗначенияСвойств);
ДополнительныеПараметры.Вставить("ИспользоватьКэш", ИспользоватьКэш);
ДополнительныеПараметры.Вставить("Выгрузка", Выгрузка);
ДополнительныеПараметры.Вставить("ДополнительныеСвойства", ДополнительныеСвойства);
ВыполнитьОбработчикПРОПриОбработке(Отказ, ПРО, Объект, ДополнительныеПараметры);
ТекстЗапроса = ДополнительныеПараметры.ТекстЗапроса;
ЗначенияСвойств = ДополнительныеПараметры.ПараметрыЗапроса;
ИспользоватьКэш = ДополнительныеПараметры.ИспользоватьКэш;
Если Отказ Тогда
Возврат Новый Массив;
КонецЕсли;
// {Обработчик: При обработке} Окончание.
Если ИспользоватьКэш Тогда
Возврат ОбменДаннымиПовтИсп.МассивУзловПоЗначениямСвойств(ЗначенияСвойств, ТекстЗапроса, ИмяПланаОбмена, ПРО.ИмяРеквизитаФлага, Выгрузка);
Иначе
УстановитьПривилегированныйРежим(Истина);
Возврат МассивУзловПоЗначениямСвойств(ЗначенияСвойств, ТекстЗапроса, ИмяПланаОбмена, ПРО.ИмяРеквизитаФлага, Выгрузка);
КонецЕсли;
КонецФункции
Функция ОпределитьМассивУзловПоЗначениямСвойствДополнительный(ЗначенияСвойств, ПРО, Знач ИмяПланаОбмена, Объект, ДополнительныеСвойства = Неопределено)
ИспользоватьКэш = Истина;
ТекстЗапроса = ПРО.ТекстЗапроса;
// {Обработчик: При обработке (дополнительный)} Начало.
Отказ = Ложь;
ВыполнитьОбработчикПРОПриОбработкеДополнительный(Отказ, ПРО, Объект, ТекстЗапроса, ЗначенияСвойств, ИспользоватьКэш, ДополнительныеСвойства);
Если Отказ Тогда
Возврат Новый Массив;
КонецЕсли;
// {Обработчик: При обработке (дополнительный)} Окончание.
Если ИспользоватьКэш Тогда
Возврат ОбменДаннымиПовтИсп.МассивУзловПоЗначениямСвойств(ЗначенияСвойств, ТекстЗапроса, ИмяПланаОбмена, ПРО.ИмяРеквизитаФлага);
Иначе
УстановитьПривилегированныйРежим(Истина);
Возврат МассивУзловПоЗначениямСвойств(ЗначенияСвойств, ТекстЗапроса, ИмяПланаОбмена, ПРО.ИмяРеквизитаФлага);
КонецЕсли;
КонецФункции
// Возвращает массив узлов плана обмена по заданным параметрам запроса и тексту запроса к таблице плана обмена.
//
//
Функция МассивУзловПоЗначениямСвойств(ЗначенияСвойств, Знач ТекстЗапроса, Знач ИмяПланаОбмена, Знач ИмяРеквизитаФлага, Знач Выгрузка = Ложь) Экспорт
// Возвращаемое значение функции.
МассивУзловРезультат = Новый Массив;
// Подготавливаем запрос для получения узлов планов обмена.
Запрос = Новый Запрос;
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "[ОбязательныеУсловия]",
"И ПланОбменаОсновнаяТаблица.Ссылка <> &" + ИмяПланаОбмена + "ЭтотУзел
|И НЕ ПланОбменаОсновнаяТаблица.ПометкаУдаления
|[УсловиеОтбораПоРеквизитуФлагу]
|");
//
Если ПустаяСтрока(ИмяРеквизитаФлага) Тогда
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "[УсловиеОтбораПоРеквизитуФлагу]", "");
Иначе
Если Выгрузка Тогда
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "[УсловиеОтбораПоРеквизитуФлагу]",
"И (ПланОбменаОсновнаяТаблица.[ИмяРеквизитаФлага] = ЗНАЧЕНИЕ(Перечисление.РежимыВыгрузкиОбъектовОбмена.ВыгружатьПоУсловию)
|ИЛИ ПланОбменаОсновнаяТаблица.[ИмяРеквизитаФлага] = ЗНАЧЕНИЕ(Перечисление.РежимыВыгрузкиОбъектовОбмена.ВыгружатьВручную)
|ИЛИ ПланОбменаОсновнаяТаблица.[ИмяРеквизитаФлага] = ЗНАЧЕНИЕ(Перечисление.РежимыВыгрузкиОбъектовОбмена.ПустаяСсылка))");
Иначе
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "[УсловиеОтбораПоРеквизитуФлагу]",
"И (ПланОбменаОсновнаяТаблица.[ИмяРеквизитаФлага] = ЗНАЧЕНИЕ(Перечисление.РежимыВыгрузкиОбъектовОбмена.ВыгружатьПоУсловию)
|ИЛИ ПланОбменаОсновнаяТаблица.[ИмяРеквизитаФлага] = ЗНАЧЕНИЕ(Перечисление.РежимыВыгрузкиОбъектовОбмена.ПустаяСсылка))");
КонецЕсли;
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "[ИмяРеквизитаФлага]", ИмяРеквизитаФлага);
КонецЕсли;
// текст запроса
Запрос.Текст = ТекстЗапроса;
Запрос.УстановитьПараметр(ИмяПланаОбмена + "ЭтотУзел", ОбменДаннымиПовтИсп.ПолучитьЭтотУзелПланаОбмена(ИмяПланаОбмена));
// Задаем значения параметров запроса из свойств объекта.
Для Каждого Элемент Из ЗначенияСвойств Цикл
Запрос.УстановитьПараметр("СвойствоОбъекта_" + Элемент.Ключ, Элемент.Значение);
КонецЦикла;
Попытка
МассивУзловРезультат = Запрос.Выполнить().Выгрузить().ВыгрузитьКолонку("Ссылка");
Исключение
СтрокаСообщения = НСтр("ru = 'Ошибка при получении списка узлов получателей. Ошибка выполнения запроса: [ОписаниеОшибки]'");
СтрокаСообщения = СтрЗаменить(СтрокаСообщения, "[ОписаниеОшибки]", ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
ВызватьИсключение СтрокаСообщения;
КонецПопытки;
Возврат МассивУзловРезультат;
КонецФункции
Функция ЗначенияСвойствДляОбъекта(Объект, ПРО)
ЗначенияСвойств = Новый Структура;
Для Каждого Элемент Из ПРО.СвойстваОбъекта Цикл
ЗначенияСвойств.Вставить(Элемент.Ключ, ЗначениеСвойстваОбъекта(Объект, Элемент.Значение));
КонецЦикла;
Возврат ЗначенияСвойств;
КонецФункции
Функция ЗначениеСвойстваОбъекта(Объект, СтрокаСвойствОбъекта)
Значение = Объект;
МассивПодстрок = СтрРазделить(СтрокаСвойствОбъекта, ".");
// Значение получаем с учетом возможного разыменования свойства.
Для Каждого ИмяСвойства Из МассивПодстрок Цикл
Значение = Значение[ИмяСвойства];
Если Значение = Неопределено Тогда
Возврат Неопределено;
КонецЕсли;
КонецЦикла;
Возврат Значение;
КонецФункции
// Возвращаемое значение:
// ТаблицаЗначений - таблица правил регистрации для текущего плана обмена.
//
Функция ПравилаРегистрацииОбъектовПланаОбмена(Знач ИмяПланаОбмена) Экспорт
Возврат ОбменДаннымиПовтИсп.ПравилаРегистрацииОбъектовПланаОбмена(ИмяПланаОбмена);
КонецФункции
Функция ПравилаРегистрацииОбъекта(Знач ИмяПланаОбмена, Знач ПолноеИмяОбъекта) Экспорт
Возврат ОбменДаннымиПовтИсп.ПравилаРегистрацииОбъекта(ИмяПланаОбмена, ПолноеИмяОбъекта);
КонецФункции
Функция ПравилоРегистрацииСтруктурой(Правило, Колонки)
Результат = Новый Структура;
Для Каждого Колонка Из Колонки Цикл
Ключ = Колонка.Имя;
Значение = Правило[Ключ];
Если ТипЗнч(Значение) = Тип("ТаблицаЗначений") Тогда
Результат.Вставить(Ключ, Значение.Скопировать());
ИначеЕсли ТипЗнч(Значение) = Тип("ДеревоЗначений") Тогда
Результат.Вставить(Ключ, Значение.Скопировать());
ИначеЕсли ТипЗнч(Значение) = Тип("Структура") Тогда
Результат.Вставить(Ключ, СкопироватьСтруктуру(Значение));
Иначе
Результат.Вставить(Ключ, Значение);
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
Функция РазделенныйПланОбмена(Знач ИмяПланаОбмена)
Если ОбщегоНазначения.ПодсистемаСуществует("ТехнологияСервиса.БазоваяФункциональность") Тогда
МодульРаботаВМоделиСервиса = ОбщегоНазначения.ОбщийМодуль("РаботаВМоделиСервиса");
ЭтоРазделенныеДанные = МодульРаботаВМоделиСервиса.ЭтоРазделенныйОбъектМетаданных(
"ПланОбмена." + ИмяПланаОбмена, МодульРаботаВМоделиСервиса.РазделительОсновныхДанных());
Иначе
ЭтоРазделенныеДанные = Ложь;
КонецЕсли;
Возврат ЭтоРазделенныеДанные;
КонецФункции
// Создает набор записей для регистра.
//
// Параметры:
// ОбъектМетаданных регистра - для получения набора записей.
//
// Возвращаемое значение:
// НаборЗаписей - в случае если для объекта метаданных не предусмотрено набора записей
// вызывается исключение.
//
Функция НаборЗаписейПоТипу(ОбъектМетаданных)
Если ОбщегоНазначения.ЭтоРегистрСведений(ОбъектМетаданных) Тогда
Результат = РегистрыСведений[ОбъектМетаданных.Имя].СоздатьНаборЗаписей();
ИначеЕсли ОбщегоНазначения.ЭтоРегистрНакопления(ОбъектМетаданных) Тогда
Результат = РегистрыНакопления[ОбъектМетаданных.Имя].СоздатьНаборЗаписей();
ИначеЕсли ОбщегоНазначения.ЭтоРегистрБухгалтерии(ОбъектМетаданных) Тогда
Результат = РегистрыБухгалтерии[ОбъектМетаданных.Имя].СоздатьНаборЗаписей();
ИначеЕсли ОбщегоНазначения.ЭтоРегистрРасчета(ОбъектМетаданных) Тогда
Результат = РегистрыРасчета[ОбъектМетаданных.Имя].СоздатьНаборЗаписей();
ИначеЕсли ОбщегоНазначения.ЭтоПоследовательность(ОбъектМетаданных) Тогда
Результат = Последовательности[ОбъектМетаданных.Имя].СоздатьНаборЗаписей();
ИначеЕсли ОбщегоНазначения.ЭтоРегистрРасчета(ОбъектМетаданных.Родитель())
И Метаданные.РегистрыРасчета[ОбъектМетаданных.Родитель().Имя].Перерасчеты.Содержит(ОбъектМетаданных) Тогда
Результат = РегистрыРасчета[ОбъектМетаданных.Родитель().Имя].Перерасчеты[ОбъектМетаданных.Имя].СоздатьНаборЗаписей();
Иначе
СтрокаСообщения = НСтр("ru = 'Для объекта метаданных %1 не предусмотрено набора записей.'");
СтрокаСообщения = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(СтрокаСообщения, ОбъектМетаданных.ПолноеИмя());
ВызватьИсключение СтрокаСообщения;
КонецЕсли;
Возврат Результат;
КонецФункции
#КонецОбласти
#Область ПравилаРегистрацииПоСвойствамОбъектов
Процедура ЗаполнитьЗначенияСвойствИзОбъекта(ДеревоЗначений, Объект)
Для Каждого СтрокаДерева Из ДеревоЗначений.Строки Цикл
Если СтрокаДерева.ЭтоГруппа Тогда
ЗаполнитьЗначенияСвойствИзОбъекта(СтрокаДерева, Объект);
Иначе
СтрокаДерева.ЗначениеСвойства = ЗначениеСвойстваОбъекта(Объект, СтрокаДерева.СвойствоОбъекта);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
// Параметры:
// Объект - Произвольный
// ДеревоЗначенийПриемник - ДеревоЗначений
// ДеревоЗначенийИсточник - ДеревоЗначений
//
Процедура СоздатьДопустимыйОтборПоСвойствам(Объект, ДеревоЗначенийПриемник, ДеревоЗначенийИсточник)
Для Каждого СтрокаДереваИсточника Из ДеревоЗначенийИсточник.Строки Цикл
Если СтрокаДереваИсточника.ЭтоГруппа Тогда
СтрокаДереваПриемника = ДеревоЗначенийПриемник.Строки.Добавить();
ЗаполнитьЗначенияСвойств(СтрокаДереваПриемника, СтрокаДереваИсточника);
СоздатьДопустимыйОтборПоСвойствам(Объект, СтрокаДереваПриемника, СтрокаДереваИсточника);
Иначе
Если ЦепочкаСвойствДействительна(Объект, СтрокаДереваИсточника.СвойствоОбъекта) Тогда
СтрокаДереваПриемника = ДеревоЗначенийПриемник.Строки.Добавить();
ЗаполнитьЗначенияСвойств(СтрокаДереваПриемника, СтрокаДереваИсточника);
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
// Предназначения для получения значений констант, которые вычисляются по произвольным выражениям.
// Значения вычисляются в привилегированном режиме.
//
Процедура ПолучитьЗначенияАлгоритмовКонстант(ПРО, ДеревоЗначений)
Для Каждого СтрокаДерева Из ДеревоЗначений.Строки Цикл
Если СтрокаДерева.ЭтоГруппа Тогда
ПолучитьЗначенияАлгоритмовКонстант(ПРО, СтрокаДерева);
Иначе
Если СтрокаДерева.ВидЭлементаОтбора = ОбменДаннымиСервер.ЭлементОтбораСвойствоАлгоритмЗначения() Тогда
Значение = Неопределено;
Попытка
#Если ВнешнееСоединение ИЛИ ТолстыйКлиентОбычноеПриложение Тогда
ВыполнитьОбработчикВПривилегированномРежиме(Значение, СтрокаДерева.ЗначениеКонстанты);
#Иначе
УстановитьПривилегированныйРежим(Истина);
Выполнить(СтрокаДерева.ЗначениеКонстанты);
УстановитьПривилегированныйРежим(Ложь);
#КонецЕсли
Исключение
СтрокаСообщения = НСтр("ru = 'Ошибка алгоритма вычисления значения константы:
|План обмена: [ИмяПланаОбмена]
|Объект метаданных: [ОбъектМетаданныхИмя]
|Описание ошибки: [Описание]
|Алгоритм:
|// {Начало алгоритма}
|[ЗначениеКонстанты]
|// {Окончание алгоритма}'");
СтрокаСообщения = СтрЗаменить(СтрокаСообщения, "[ИмяПланаОбмена]", ПРО.ИмяПланаОбмена);
СтрокаСообщения = СтрЗаменить(СтрокаСообщения, "[ОбъектМетаданныхИмя]", ПРО.ОбъектМетаданныхИмя);
СтрокаСообщения = СтрЗаменить(СтрокаСообщения, "[Описание]", ИнформацияОбОшибке().Описание);
СтрокаСообщения = СтрЗаменить(СтрокаСообщения, "[ЗначениеКонстанты]", Строка(СтрокаДерева.ЗначениеКонстанты));
ВызватьИсключение СтрокаСообщения;
КонецПопытки;
СтрокаДерева.ЗначениеКонстанты = Значение;
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Функция ЦепочкаСвойствДействительна(Объект, Знач СтрокаСвойствОбъекта)
Значение = Объект;
МассивПодстрок = СтрРазделить(СтрокаСвойствОбъекта, ".");
// Значение получаем с учетом возможного разыменования свойства.
Для Каждого ИмяСвойства Из МассивПодстрок Цикл
Попытка
Значение = Значение[ИмяСвойства];
Исключение
Возврат Ложь;
КонецПопытки;
КонецЦикла;
Возврат Истина;
КонецФункции
// Выполняем ПРОБ для ссылки и для объекта.
// Результат учитываем по условию "ИЛИ".
// Если объект прошел фильтр ПРОБ по значения из ссылки,
// то ПРОБ для значений объекта уже не выполняем.
//
Функция ОбъектПрошелФильтрПравилРегистрацииПоСвойствам(ПРО, Объект, ПроверятьСсылку, РежимЗаписи = Неопределено)
НачальноеЗначениеСвойстваПроведен = Неопределено;
ПолучитьЗначенияАлгоритмовКонстант(ПРО, ПРО.ОтборПоСвойствамОбъекта);
Если РежимЗаписи <> Неопределено Тогда
НачальноеЗначениеСвойстваПроведен = Объект.Проведен;
Если РежимЗаписи = РежимЗаписиДокумента.ОтменаПроведения Тогда
Объект.Проведен = Ложь;
ИначеЕсли РежимЗаписи = РежимЗаписиДокумента.Проведение Тогда
Объект.Проведен = Истина;
КонецЕсли;
КонецЕсли;
// ПРОБ по значению свойств Объекта.
Если ОбъектПроходитФильтрПРОБ(ПРО, Объект) Тогда
Если НачальноеЗначениеСвойстваПроведен <> Неопределено Тогда
Объект.Проведен = НачальноеЗначениеСвойстваПроведен;
КонецЕсли;
Возврат Истина;
КонецЕсли;
Если НачальноеЗначениеСвойстваПроведен <> Неопределено Тогда
Объект.Проведен = НачальноеЗначениеСвойстваПроведен;
КонецЕсли;
Если ПроверятьСсылку Тогда
// ПРОБ по значению свойств Ссылки.
Если ОбъектПроходитФильтрПРОБ(ПРО, Объект.Ссылка) Тогда
Возврат Истина;
КонецЕсли;
КонецЕсли;
Возврат Ложь;
КонецФункции
Функция ОбъектПроходитФильтрПРОБ(ПРО, Объект)
ПРО.ОтборПоСвойствам = Обработки.ЗагрузкаПравилРегистрацииОбъектов.ИнициализацияТаблицыОтборПоСвойствамОбъекта();
СоздатьДопустимыйОтборПоСвойствам(Объект, ПРО.ОтборПоСвойствам, ПРО.ОтборПоСвойствамОбъекта);
ЗаполнитьЗначенияСвойствИзОбъекта(ПРО.ОтборПоСвойствам, Объект);
Возврат УсловиеИстинноДляВеткиДереваЗначений(ПРО.ОтборПоСвойствам);
КонецФункции
// По умолчанию считаем, что элементы отбора корневой группы сравниваются по условию "И".
// Поэтому параметр ЭтоОператорИ по умолчанию принимает значение Истина.
//
Функция УсловиеИстинноДляВеткиДереваЗначений(ДеревоЗначений, Знач ЭтоОператорИ = Истина)
// инициализация
Если ЭтоОператорИ Тогда // И
Результат = Истина;
Иначе // ИЛИ
Результат = Ложь;
КонецЕсли;
Для Каждого СтрокаДерева Из ДеревоЗначений.Строки Цикл
Если СтрокаДерева.ЭтоГруппа Тогда
РезультатЭлемента = УсловиеИстинноДляВеткиДереваЗначений(СтрокаДерева, СтрокаДерева.ЭтоОператорИ);
Иначе
РезультатЭлемента = УсловиеИстинноДляЭлемента(СтрокаДерева, ЭтоОператорИ);
КонецЕсли;
Если ЭтоОператорИ Тогда // И
Результат = Результат И РезультатЭлемента;
Если Не Результат Тогда
Возврат Ложь;
КонецЕсли;
Иначе // ИЛИ
Результат = Результат ИЛИ РезультатЭлемента;
Если Результат Тогда
Возврат Истина;
КонецЕсли;
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
Функция УсловиеИстинноДляЭлемента(СтрокаДерева, ЭтоОператорИ)
ВидСравненияПравила = СтрокаДерева.ВидСравнения;
Попытка
Если ВидСравненияПравила = "Равно" Тогда Возврат СтрокаДерева.ЗначениеСвойства = СтрокаДерева.ЗначениеКонстанты;
ИначеЕсли ВидСравненияПравила = "НеРавно" Тогда Возврат СтрокаДерева.ЗначениеСвойства <> СтрокаДерева.ЗначениеКонстанты;
ИначеЕсли ВидСравненияПравила = "Больше" Тогда Возврат СтрокаДерева.ЗначениеСвойства > СтрокаДерева.ЗначениеКонстанты;
ИначеЕсли ВидСравненияПравила = "БольшеИлиРавно" Тогда Возврат СтрокаДерева.ЗначениеСвойства >= СтрокаДерева.ЗначениеКонстанты;
ИначеЕсли ВидСравненияПравила = "Меньше" Тогда Возврат СтрокаДерева.ЗначениеСвойства < СтрокаДерева.ЗначениеКонстанты;
ИначеЕсли ВидСравненияПравила = "МеньшеИлиРавно" Тогда Возврат СтрокаДерева.ЗначениеСвойства <= СтрокаДерева.ЗначениеКонстанты;
КонецЕсли;
Исключение
Возврат Ложь;
КонецПопытки;
Возврат Ложь;
КонецФункции
#КонецОбласти
#Область СобытияПравилРегистрацииОбъектов
Процедура ВыполнитьОбработчикПРОПередОбработкой(ПРО, Отказ, Объект, ОбъектМетаданных, Знач Выгрузка)
Если ПРО.ЕстьОбработчикПередОбработкой Тогда
Попытка
Выполнить(ПРО.ПередОбработкой);
Исключение
ВызватьИсключение ПодробноеПредставлениеОшибкиВыполненияОбработчика(
"ПередОбработкой",
ПРО.ИмяПланаОбмена,
ПРО.ОбъектМетаданныхИмя,
ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
КонецПопытки;
КонецЕсли;
КонецПроцедуры
Процедура ВыполнитьОбработчикПРОПриОбработке(Отказ, ПРО, Объект, ДополнительныеПараметры)
ТекстЗапроса = ДополнительныеПараметры.ТекстЗапроса;
ПараметрыЗапроса = ДополнительныеПараметры.ПараметрыЗапроса;
ИспользоватьКэш = ДополнительныеПараметры.ИспользоватьКэш;
Выгрузка = ДополнительныеПараметры.Выгрузка;
ДополнительныеСвойства = ДополнительныеПараметры.ДополнительныеСвойства;
Если ПРО.ЕстьОбработчикПриОбработке Тогда
Попытка
Выполнить(ПРО.ПриОбработке);
Исключение
ВызватьИсключение ПодробноеПредставлениеОшибкиВыполненияОбработчика(
"ПриОбработке",
ПРО.ИмяПланаОбмена,
ПРО.ОбъектМетаданныхИмя,
ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
КонецПопытки;
КонецЕсли;
ДополнительныеПараметры.ТекстЗапроса = ТекстЗапроса;
ДополнительныеПараметры.ПараметрыЗапроса = ПараметрыЗапроса;
ДополнительныеПараметры.ИспользоватьКэш = ИспользоватьКэш;
КонецПроцедуры
Процедура ВыполнитьОбработчикПРОПриОбработкеДополнительный(Отказ, ПРО, Объект, ТекстЗапроса, ПараметрыЗапроса, ИспользоватьКэш, ДополнительныеСвойства = Неопределено)
Если ПРО.ЕстьОбработчикПриОбработкеДополнительный Тогда
Попытка
Выполнить(ПРО.ПриОбработкеДополнительный);
Исключение
ВызватьИсключение ПодробноеПредставлениеОшибкиВыполненияОбработчика(
"ПриОбработкеДополнительный",
ПРО.ИмяПланаОбмена,
ПРО.ОбъектМетаданныхИмя,
ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
КонецПопытки;
КонецЕсли;
КонецПроцедуры
Процедура ВыполнитьОбработчикПРОПослеОбработки(ПРО, Отказ, Объект, ОбъектМетаданных, Получатели, Знач Выгрузка)
Если ПРО.ЕстьОбработчикПослеОбработки Тогда
Попытка
Выполнить(ПРО.ПослеОбработки);
Исключение
ВызватьИсключение ПодробноеПредставлениеОшибкиВыполненияОбработчика(
"ПослеОбработки",
ПРО.ИмяПланаОбмена,
ПРО.ОбъектМетаданныхИмя,
ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
КонецПопытки;
КонецЕсли;
КонецПроцедуры
#КонецОбласти
#Область ВспомогательныеПроцедурыИФункции
Функция ПодробноеПредставлениеОшибкиВыполненияОбработчика(ИмяОбработчика, ИмяПланаОбмена, ИмяОбъектаМетаданных, ПредставлениеОшибки)
Возврат СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
НСтр("ru = 'Ошибка при выполнении обработчика: ""%1"";
|План обмена: %2;
|Объект метаданных: %3;
|Описание ошибки: %4.'"),
ИмяОбработчика,
ИмяПланаОбмена,
ИмяОбъектаМетаданных,
ПредставлениеОшибки);
КонецФункции
Процедура ПриОтправкеДанных(ЭлементДанных, ОтправкаЭлемента, Знач Получатель, Знач СозданиеНачальногоОбраза, Знач Анализ)
Если ТипЗнч(ЭлементДанных) = Тип("УдалениеОбъекта") Тогда
Возврат;
КонецЕсли;
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.ЗащитаПерсональныхДанных") Тогда
МодульЗащитаПерсональныхДанных = ОбщегоНазначения.ОбщийМодуль("ЗащитаПерсональныхДанных");
МодульЗащитаПерсональныхДанных.ПриОтправкеДанных(ЭлементДанных, ОтправкаЭлемента, Получатель, СозданиеНачальногоОбраза);
КонецЕсли;
// Проверяем актуальность кэша механизма регистрации объектов.
ОбменДаннымиСлужебный.ПроверитьКэшМеханизмаРегистрацииОбъектов();
РежимВыгрузкиОбъекта = ОбменДаннымиПовтИсп.РежимВыгрузкиОбъекта(ЭлементДанных.Метаданные().ПолноеИмя(), Получатель);
Если РежимВыгрузкиОбъекта = Перечисления.РежимыВыгрузкиОбъектовОбмена.ВыгружатьВсегда Тогда
// Выгружаем элемент данных
ИначеЕсли РежимВыгрузкиОбъекта = Перечисления.РежимыВыгрузкиОбъектовОбмена.ВыгружатьПоУсловию
ИЛИ РежимВыгрузкиОбъекта = Перечисления.РежимыВыгрузкиОбъектовОбмена.ВыгружатьПриНеобходимости Тогда
Если Не ДанныеСоответствуютФильтруПравилРегистрации(ЭлементДанных, Получатель) Тогда
Если СозданиеНачальногоОбраза Тогда
ОтправкаЭлемента = ОтправкаЭлементаДанных.Игнорировать;
Иначе
ОтправкаЭлемента = ОтправкаЭлементаДанных.Удалить;
КонецЕсли;
КонецЕсли;
ИначеЕсли РежимВыгрузкиОбъекта = Перечисления.РежимыВыгрузкиОбъектовОбмена.ВыгружатьВручную Тогда
Если ДанныеСоответствуютФильтруПравилРегистрации(ЭлементДанных, Получатель) Тогда
Если Не Анализ Тогда
// Удаляем регистрацию изменений данных, выгруженных вручную.
ПланыОбмена.УдалитьРегистрациюИзменений(Получатель, ЭлементДанных);
КонецЕсли;
Иначе
ОтправкаЭлемента = ОтправкаЭлементаДанных.Игнорировать;
КонецЕсли;
ИначеЕсли РежимВыгрузкиОбъекта = Перечисления.РежимыВыгрузкиОбъектовОбмена.НеВыгружать Тогда
ОтправкаЭлемента = ОтправкаЭлементаДанных.Игнорировать;
КонецЕсли;
Если ОтправкаЭлемента = ОтправкаЭлементаДанных.Игнорировать
И Не (ОбменДаннымиПовтИсп.ЭтоУзелРаспределеннойИнформационнойБазы(Получатель) И СозданиеНачальногоОбраза)
И Не Анализ Тогда
// При отказе в выгрузке объекта необходимо удалить регистрацию изменений.
ПланыОбмена.УдалитьРегистрациюИзменений(Получатель, ЭлементДанных);
КонецЕсли;
КонецПроцедуры
Функция ДанныеСоответствуютФильтруПравилРегистрации(ЭлементДанных, Знач Получатель)
Результат = Истина;
ИмяПланаОбмена = ОбменДаннымиПовтИсп.ПолучитьИмяПланаОбмена(Получатель);
ОбъектМетаданных = ЭлементДанных.Метаданные();
Если ОбщегоНазначения.ЭтоСправочник(ОбъектМетаданных)
ИЛИ ОбщегоНазначения.ЭтоДокумент(ОбъектМетаданных)
ИЛИ ОбщегоНазначения.ЭтоПланВидовХарактеристик(ОбъектМетаданных)
ИЛИ ОбщегоНазначения.ЭтоПланСчетов(ОбъектМетаданных)
ИЛИ ОбщегоНазначения.ЭтоПланВидовРасчета(ОбъектМетаданных)
ИЛИ ОбщегоНазначения.ЭтоБизнесПроцесс(ОбъектМетаданных)
ИЛИ ОбщегоНазначения.ЭтоЗадача(ОбъектМетаданных) Тогда
// Определяем массив узлов для регистрации объекта.
МассивУзловДляРегистрацииОбъекта = Новый Массив;
ДополнительныеПараметры = Новый Структура;
ДополнительныеПараметры.Вставить("ОбъектМетаданных", ОбъектМетаданных);
ДополнительныеПараметры.Вставить("Выгрузка", Истина);
ВыполнитьПравилаРегистрацииОбъектовДляПланаОбмена(МассивУзловДляРегистрацииОбъекта,
ЭлементДанных,
ИмяПланаОбмена,
ДополнительныеПараметры);
//
// Если в массиве нет текущего узла, то посылаем удаление объекта.
Если МассивУзловДляРегистрацииОбъекта.Найти(Получатель) = Неопределено Тогда
Результат = Ложь;
КонецЕсли;
ИначеЕсли ОбщегоНазначения.ЭтоРегистр(ОбъектМетаданных) Тогда
ИсключаяСвойства = ?(ОбщегоНазначения.ЭтоРегистрНакопления(ОбъектМетаданных), "ВидДвижения", "");
ДанныеДляПроверки = НаборЗаписейПоТипу(ОбъектМетаданных);
Для Каждого ЭлементОтбораИсточник Из ЭлементДанных.Отбор Цикл
ЭлементОтбораПриемник = ДанныеДляПроверки.Отбор.Найти(ЭлементОтбораИсточник.Имя);
ЗаполнитьЗначенияСвойств(ЭлементОтбораПриемник, ЭлементОтбораИсточник);
КонецЦикла;
ДанныеДляПроверки.Добавить();
ОбратныйИндекс = ЭлементДанных.Количество() - 1;
Пока ОбратныйИндекс >= 0 Цикл
ЗаполнитьЗначенияСвойств(ДанныеДляПроверки[0], ЭлементДанных[ОбратныйИндекс],, ИсключаяСвойства);
// Определяем массив узлов для регистрации объекта.
МассивУзловДляРегистрацииОбъекта = Новый Массив;
ДополнительныеПараметры = Новый Структура;
ДополнительныеПараметры.Вставить("ОбъектМетаданных", ОбъектМетаданных);
ДополнительныеПараметры.Вставить("ЭтоРегистр", Истина);
ДополнительныеПараметры.Вставить("Выгрузка", Истина);
ВыполнитьПравилаРегистрацииОбъектовДляПланаОбмена(МассивУзловДляРегистрацииОбъекта,
ДанныеДляПроверки,
ИмяПланаОбмена,
ДополнительныеПараметры);
// Если в массиве нет текущего узла, то удаляем строку из набора.
Если МассивУзловДляРегистрацииОбъекта.Найти(Получатель) = Неопределено Тогда
ЭлементДанных.Удалить(ОбратныйИндекс);
КонецЕсли;
ОбратныйИндекс = ОбратныйИндекс - 1;
КонецЦикла;
Если ЭлементДанных.Количество() = 0 Тогда
Результат = Ложь;
КонецЕсли;
КонецЕсли;
Возврат Результат;
КонецФункции
// Заполняет значения реквизитов и табличных частей однотипных объектов информационной базы.
//
// Параметры:
// Источник - объект информационной базы (СправочникОбъект, ДокументОбъект, ПланВидовХарактеристикОбъект и пр.)
// который является источником данных для заполнения.
//
// Приемник - объект информационной базы (СправочникОбъект, ДокументОбъект,
// ПланВидовХарактеристикОбъект и пр.) который будет заполнен данными источника.
//
// СписокСвойств - Строка - список свойств объекта и табличных частей, разделенных запятыми.
// Если параметр задан, то заполнение свойств объекта будет
// выполняться согласно заданным свойствам, при этом параметр.
// ИсключаяСвойства будет проигнорирован.
//
// ИсключаяСвойства - Строка - список свойств объекта и табличных частей, разделенных запятыми.
// Если параметр задан, то заполнение свойств объекта будет выполняться
// для всех свойств и табличных частей, исключая заданные свойства.
//
Процедура ЗаполнитьЗначенияСвойствОбъекта(Приемник, Источник, Знач СписокСвойств = Неопределено, Знач ИсключаяСвойства = Неопределено) Экспорт
Если СписокСвойств <> Неопределено Тогда
СписокСвойств = СтрЗаменить(СписокСвойств, " ", "");
СписокСвойств = СтрРазделить(СписокСвойств, ",");
ОбъектМетаданных = Приемник.Метаданные();
ТабличныеЧасти = ТабличныеЧастиОбъекта(ОбъектМетаданных);
СписокСвойствШапки = Новый Массив;
ИспользуемыеТабличныеЧасти = Новый Массив;
Для Каждого Свойство Из СписокСвойств Цикл
Если ТабличныеЧасти.Найти(Свойство) <> Неопределено Тогда
ИспользуемыеТабличныеЧасти.Добавить(Свойство);
Иначе
СписокСвойствШапки.Добавить(Свойство);
КонецЕсли;
КонецЦикла;
СписокСвойствШапки = СтрСоединить(СписокСвойствШапки, ",");
ЗаполнитьЗначенияСвойств(Приемник, Источник, СписокСвойствШапки);
Для Каждого ТабличнаяЧасть Из ИспользуемыеТабличныеЧасти Цикл
Приемник[ТабличнаяЧасть].Загрузить(Источник[ТабличнаяЧасть].Выгрузить());
КонецЦикла;
ИначеЕсли ИсключаяСвойства <> Неопределено Тогда
ЗаполнитьЗначенияСвойств(Приемник, Источник,, ИсключаяСвойства);
ОбъектМетаданных = Приемник.Метаданные();
ТабличныеЧасти = ТабличныеЧастиОбъекта(ОбъектМетаданных);
Для Каждого ТабличнаяЧасть Из ТабличныеЧасти Цикл
Если СтрНайти(ИсключаяСвойства, ТабличнаяЧасть) <> 0 Тогда
Продолжить;
КонецЕсли;
Приемник[ТабличнаяЧасть].Загрузить(Источник[ТабличнаяЧасть].Выгрузить());
КонецЦикла;
Иначе
ЗаполнитьЗначенияСвойств(Приемник, Источник);
ОбъектМетаданных = Приемник.Метаданные();
ТабличныеЧасти = ТабличныеЧастиОбъекта(ОбъектМетаданных);
Для Каждого ТабличнаяЧасть Из ТабличныеЧасти Цикл
Приемник[ТабличнаяЧасть].Загрузить(Источник[ТабличнаяЧасть].Выгрузить());
КонецЦикла;
КонецЕсли;
КонецПроцедуры
// Параметры:
// Объект - СправочникОбъект
// - ДокументОбъект
// - Произвольный - объект ссылочного типа.
// ТаблицаРеквизитовСсылочногоТипа - ТаблицаЗначений
//
Процедура ВыполнитьРегистрациюОбъектовСсылочногоТипаПоСвойствамУзла(Объект, ТаблицаРеквизитовСсылочногоТипа)
УзелИнформационнойБазы = Объект.Ссылка;
ИмяПланаОбмена = ОбменДаннымиПовтИсп.ПолучитьИмяПланаОбмена(УзелИнформационнойБазы);
Для Каждого СтрокаТаблицы Из ТаблицаРеквизитовСсылочногоТипа Цикл
Если ПустаяСтрока(СтрокаТаблицы.ИмяТабличнойЧасти) Тогда // реквизиты шапки
Для Каждого Элемент Из СтрокаТаблицы.СтруктураРеквизитовРегистрации Цикл
Ссылка = Объект[Элемент.Ключ];
Если Не Ссылка.Пустая()
И СоставПланаОбменаСодержитТип(ИмяПланаОбмена, ТипЗнч(Ссылка)) Тогда
ПланыОбмена.ЗарегистрироватьИзменения(УзелИнформационнойБазы, Ссылка);
КонецЕсли;
КонецЦикла;
Иначе // реквизиты табличной части
ТабличнаяЧасть = Объект[СтрокаТаблицы.ИмяТабличнойЧасти];
Для Каждого СтрокаТабличнойЧасти Из ТабличнаяЧасть Цикл
Для Каждого Элемент Из СтрокаТаблицы.СтруктураРеквизитовРегистрации Цикл
Ссылка = СтрокаТабличнойЧасти[Элемент.Ключ];
Если Не Ссылка.Пустая()
И СоставПланаОбменаСодержитТип(ИмяПланаОбмена, ТипЗнч(Ссылка)) Тогда
ПланыОбмена.ЗарегистрироватьИзменения(УзелИнформационнойБазы, Ссылка);
КонецЕсли;
КонецЦикла;
КонецЦикла;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Функция РеквизитыОбъектаСсылочногоТипа(Объект, ИмяПланаОбмена)
// Выполняем инициализацию таблицы.
Результат = ОбменДаннымиСервер.ИнициализацияТаблицыПравилВыборочнойРегистрацииОбъектов();
ОбъектМетаданных = Объект.Метаданные();
ОбъектМетаданныхПолноеИмя = ОбъектМетаданных.ПолноеИмя();
// Получаем реквизиты шапки
Реквизиты = РеквизитыСсылочногоТипа(ОбъектМетаданных.Реквизиты, ИмяПланаОбмена);
Если Реквизиты.Количество() > 0 Тогда
СтрокаТаблицы = Результат.Добавить();
СтрокаТаблицы.ИмяОбъекта = ОбъектМетаданныхПолноеИмя;
СтрокаТаблицы.ИмяТабличнойЧасти = "";
СтрокаТаблицы.РеквизитыРегистрации = КлючиСтруктурыВСтроку(Реквизиты);
СтрокаТаблицы.СтруктураРеквизитовРегистрации = СкопироватьСтруктуру(Реквизиты);
КонецЕсли;
// Получаем реквизиты табличных частей.
Для Каждого ТабличнаяЧасть Из ОбъектМетаданных.ТабличныеЧасти Цикл
Реквизиты = РеквизитыСсылочногоТипа(ТабличнаяЧасть.Реквизиты, ИмяПланаОбмена);
Если Реквизиты.Количество() > 0 Тогда
СтрокаТаблицы = Результат.Добавить();
СтрокаТаблицы.ИмяОбъекта = ОбъектМетаданныхПолноеИмя;
СтрокаТаблицы.ИмяТабличнойЧасти = ТабличнаяЧасть.Имя;
СтрокаТаблицы.РеквизитыРегистрации = КлючиСтруктурыВСтроку(Реквизиты);
СтрокаТаблицы.СтруктураРеквизитовРегистрации = СкопироватьСтруктуру(Реквизиты);
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
Функция РеквизитыСсылочногоТипа(Реквизиты, ИмяПланаОбмена)
// Возвращаемое значение функции.
Результат = Новый Структура;
Для Каждого Реквизит Из Реквизиты Цикл
МассивТипов = Реквизит.Тип.Типы();
ЭтоСсылка = Ложь;
Для Каждого Тип Из МассивТипов Цикл
Если ОбщегоНазначения.ЭтоСсылка(Тип)
И СоставПланаОбменаСодержитТип(ИмяПланаОбмена, Тип) Тогда
ЭтоСсылка = Истина;
Прервать;
КонецЕсли;
КонецЦикла;
Если ЭтоСсылка Тогда
Результат.Вставить(Реквизит.Имя);
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
Функция СоставПланаОбменаСодержитТип(ИмяПланаОбмена, Тип)
Возврат Метаданные.ПланыОбмена[ИмяПланаОбмена].Состав.Содержит(Метаданные.НайтиПоТипу(Тип));
КонецФункции
// Создает новый экземпляр объекта Структура, заполняет объект данными указанной структуры.
//
// Параметры:
// СтруктураИсточник - Структура - структура, копию которой необходимо получить.
//
// Возвращаемое значение:
// Структура - копия переданной структуры.
//
Функция СкопироватьСтруктуру(СтруктураИсточник) Экспорт
СтруктураРезультат = Новый Структура;
Для Каждого Элемент Из СтруктураИсточник Цикл
Если ТипЗнч(Элемент.Значение) = Тип("ТаблицаЗначений") Тогда
СтруктураРезультат.Вставить(Элемент.Ключ, Элемент.Значение.Скопировать());
ИначеЕсли ТипЗнч(Элемент.Значение) = Тип("ДеревоЗначений") Тогда
СтруктураРезультат.Вставить(Элемент.Ключ, Элемент.Значение.Скопировать());
ИначеЕсли ТипЗнч(Элемент.Значение) = Тип("Структура") Тогда
СтруктураРезультат.Вставить(Элемент.Ключ, СкопироватьСтруктуру(Элемент.Значение));
ИначеЕсли ТипЗнч(Элемент.Значение) = Тип("СписокЗначений") Тогда
СтруктураРезультат.Вставить(Элемент.Ключ, Элемент.Значение.Скопировать());
Иначе
СтруктураРезультат.Вставить(Элемент.Ключ, Элемент.Значение);
КонецЕсли;
КонецЦикла;
Возврат СтруктураРезультат;
КонецФункции
// Получает строку, содержащую ключи структуры, разделенные символом разделителя.
//
// Параметры:
// Структура - Структура - структура, ключи которой преобразуются в строку.
// Разделитель - Строка - разделитель, который вставляется в строку между ключами структуры.
//
// Возвращаемое значение:
// Строка - строка, содержащая ключи структуры разделенные разделителем.
//
Функция КлючиСтруктурыВСтроку(Структура, Разделитель = ",") Экспорт
Результат = "";
Для Каждого Элемент Из Структура Цикл
СимволРазделителя = ?(ПустаяСтрока(Результат), "", Разделитель);
Результат = Результат + СимволРазделителя + Элемент.Ключ;
КонецЦикла;
Возврат Результат;
КонецФункции
// Выполняет сравнение версий двух однотипных объектов.
//
// Параметры:
// Данные1 - СправочникОбъект
// - ДокументОбъект
// - ПланВидовХарактеристикОбъект
// - ПланВидовРасчетаОбъект
// - ПланСчетовОбъект
// - ПланОбменаОбъект
// - БизнесПроцессОбъект
// - ЗадачаОбъект - первая версия данных для сравнения.
// Данные2 - СправочникОбъект
// - ДокументОбъект
// - ПланВидовХарактеристикОбъект
// - ПланВидовРасчетаОбъект
// - ПланСчетовОбъект
// - ПланОбменаОбъект
// - БизнесПроцессОбъект
// - ЗадачаОбъект - вторая версия данных для сравнения.
// СписокСвойств - Строка - список свойств объекта и табличных частей, разделенных запятыми.
// Если параметр задан, то заполнение свойств объекта будет
// выполняться согласно заданным свойствам, при этом параметр
// "ИсключаяСвойства" будет проигнорирован.
// ИсключаяСвойства - Строка - список свойств объекта и табличных частей, разделенных запятыми.
// Если параметр задан, то заполнение свойств объекта будет выполняться
// для всех свойств и табличных частей, исключая заданные свойства.
//
// Возвращаемое значение:
// Булево - Истина - если версии данных различаются, иначе Ложь.
//
Функция ДанныеРазличаются(Данные1, Данные2, СписокСвойств = Неопределено, ИсключаяСвойства = Неопределено) Экспорт
Если ТипЗнч(Данные1) <> ТипЗнч(Данные2) Тогда
Возврат Истина;
КонецЕсли;
ОбъектМетаданных = Данные1.Метаданные(); // ОбъектМетаданных
Если ОбщегоНазначения.ЭтоСправочник(ОбъектМетаданных) Тогда
Если Данные1.ЭтоГруппа Тогда
Объект1 = Справочники[ОбъектМетаданных.Имя].СоздатьГруппу();
Иначе
Объект1 = Справочники[ОбъектМетаданных.Имя].СоздатьЭлемент();
КонецЕсли;
Если Данные2.ЭтоГруппа Тогда
Объект2 = Справочники[ОбъектМетаданных.Имя].СоздатьГруппу();
Иначе
Объект2 = Справочники[ОбъектМетаданных.Имя].СоздатьЭлемент();
КонецЕсли;
ИначеЕсли ОбщегоНазначения.ЭтоДокумент(ОбъектМетаданных) Тогда
Объект1 = Документы[ОбъектМетаданных.Имя].СоздатьДокумент();
Объект2 = Документы[ОбъектМетаданных.Имя].СоздатьДокумент();
ИначеЕсли ОбщегоНазначения.ЭтоПланВидовХарактеристик(ОбъектМетаданных) Тогда
Если Данные1.ЭтоГруппа Тогда
Объект1 = ПланыВидовХарактеристик[ОбъектМетаданных.Имя].СоздатьГруппу();
Иначе
Объект1 = ПланыВидовХарактеристик[ОбъектМетаданных.Имя].СоздатьЭлемент();
КонецЕсли;
Если Данные2.ЭтоГруппа Тогда
Объект2 = ПланыВидовХарактеристик[ОбъектМетаданных.Имя].СоздатьГруппу();
Иначе
Объект2 = ПланыВидовХарактеристик[ОбъектМетаданных.Имя].СоздатьЭлемент();
КонецЕсли;
ИначеЕсли ОбщегоНазначения.ЭтоПланВидовРасчета(ОбъектМетаданных) Тогда
Объект1 = ПланыВидовРасчета[ОбъектМетаданных.Имя].СоздатьВидРасчета();
Объект2 = ПланыВидовРасчета[ОбъектМетаданных.Имя].СоздатьВидРасчета();
ИначеЕсли ОбщегоНазначения.ЭтоПланСчетов(ОбъектМетаданных) Тогда
Объект1 = ПланыСчетов[ОбъектМетаданных.Имя].СоздатьСчет();
Объект2 = ПланыСчетов[ОбъектМетаданных.Имя].СоздатьСчет();
ИначеЕсли ОбщегоНазначения.ЭтоПланОбмена(ОбъектМетаданных) Тогда
Объект1 = ПланыОбмена[ОбъектМетаданных.Имя].СоздатьУзел();
Объект2 = ПланыОбмена[ОбъектМетаданных.Имя].СоздатьУзел();
ИначеЕсли ОбщегоНазначения.ЭтоБизнесПроцесс(ОбъектМетаданных) Тогда
Объект1 = БизнесПроцессы[ОбъектМетаданных.Имя].СоздатьБизнесПроцесс();
Объект2 = БизнесПроцессы[ОбъектМетаданных.Имя].СоздатьБизнесПроцесс();
ИначеЕсли ОбщегоНазначения.ЭтоЗадача(ОбъектМетаданных) Тогда
Объект1 = Задачи[ОбъектМетаданных.Имя].СоздатьЗадачу();
Объект2 = Задачи[ОбъектМетаданных.Имя].СоздатьЗадачу();
Иначе
ВызватьИсключение НСтр("ru = 'Задано недопустимое значение параметра [1] метода ОбщегоНазначения.ЗначенияСвойствИзменены.'");
КонецЕсли;
ЗаполнитьЗначенияСвойствОбъекта(Объект1, Данные1, СписокСвойств, ИсключаяСвойства);
ЗаполнитьЗначенияСвойствОбъекта(Объект2, Данные2, СписокСвойств, ИсключаяСвойства);
Возврат ДанныеИнформационнойБазыСтрокой(Объект1) <> ДанныеИнформационнойБазыСтрокой(Объект2);
КонецФункции
Функция ДанныеИнформационнойБазыСтрокой(Данные)
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.УстановитьСтроку();
ЗаписатьXML(ЗаписьXML, Данные, НазначениеТипаXML.Явное);
Возврат ЗаписьXML.Закрыть();
КонецФункции
// Возвращает массив табличных частей объекта.
//
// Параметры:
// ОбъектМетаданных - ОбъектМетаданных - ссылочный объект метаданных:
// * ТабличныеЧасти - КоллекцияОбъектовМетаданных из ОбъектМетаданныхТабличнаяЧасть
//
// Возвращаемое значение:
// Массив из Строка - коллекция табличных частей объекта.
//
Функция ТабличныеЧастиОбъекта(ОбъектМетаданных) Экспорт
Результат = Новый Массив;
Для Каждого ТабличнаяЧасть Из ОбъектМетаданных.ТабличныеЧасти Цикл
Результат.Добавить(ТабличнаяЧасть.Имя);
КонецЦикла;
Возврат Результат;
КонецФункции
// Параметры:
// УзелПланаОбмена - ПланОбменаОбъект - узел плана обмена.
// Настройки - Структура - структура со значениями настроек.
//
Процедура УстановитьЗначенияНаУзле(УзелПланаОбмена, Настройки)
// УзелПланаОбмена - недоступный тип параметра для модулей с повторным использованием значений,
// поэтому используется УзелПланаОбмена.Ссылка.
ИмяПланаОбмена = ОбменДаннымиПовтИсп.ПолучитьИмяПланаОбмена(УзелПланаОбмена.Ссылка);
Для Каждого Элемент Из Настройки Цикл
Ключ = Элемент.Ключ;
Значение = Элемент.Значение;
Если УзелПланаОбмена.Метаданные().Реквизиты.Найти(Ключ) = Неопределено
И УзелПланаОбмена.Метаданные().ТабличныеЧасти.Найти(Ключ) = Неопределено Тогда
Продолжить;
КонецЕсли;
Если ТипЗнч(Значение) = Тип("Массив") Тогда
ДанныеРеквизита = СсылочныйТипИзПервогоРеквизитаТабличнойЧастиПланаОбмена(ИмяПланаОбмена, Ключ);
Если ДанныеРеквизита = Неопределено Тогда
Продолжить;
КонецЕсли;
ТаблицаУзла = УзелПланаОбмена[Ключ];
ТаблицаУзла.Очистить();
Для Каждого СтрокаТаблицы Из Значение Цикл
Если СтрокаТаблицы.Использовать Тогда
МенеджерОбъекта = ОбщегоНазначения.МенеджерОбъектаПоСсылке(ДанныеРеквизита.Тип.ПривестиЗначение());
ЗначениеРеквизита = МенеджерОбъекта.ПолучитьСсылку(Новый УникальныйИдентификатор(СтрокаТаблицы.УникальныйИдентификаторСсылки));
ТаблицаУзла.Добавить()[ДанныеРеквизита.Имя] = ЗначениеРеквизита;
КонецЕсли;
КонецЦикла;
ИначеЕсли ТипЗнч(Значение) = Тип("Структура") Тогда
ЗаполнитьТаблицуУзлаПланаОбмена(УзелПланаОбмена, Значение, Ключ);
Иначе // примитивные типы
УзелПланаОбмена[Ключ] = Значение;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Процедура ЗаполнитьТаблицуУзлаПланаОбмена(Узел, СтруктураТабличнойЧасти, ИмяТаблицы)
ТаблицаУзла = Узел[ИмяТаблицы];
ТаблицаУзла.Очистить();
Для Каждого Элемент Из СтруктураТабличнойЧасти Цикл
Пока ТаблицаУзла.Количество() < Элемент.Значение.Количество() Цикл
ТаблицаУзла.Добавить();
КонецЦикла;
ТаблицаУзла.ЗагрузитьКолонку(Элемент.Значение, Элемент.Ключ);
КонецЦикла;
КонецПроцедуры
Функция СсылочныйТипИзПервогоРеквизитаТабличнойЧастиПланаОбмена(Знач ИмяПланаОбмена, Знач ИмяТабличнойЧасти)
ТабличнаяЧасть = Метаданные.ПланыОбмена[ИмяПланаОбмена].ТабличныеЧасти[ИмяТабличнойЧасти];
Для Каждого Реквизит Из ТабличнаяЧасть.Реквизиты Цикл
Тип = Реквизит.Тип.Типы()[0];
Если ОбщегоНазначения.ЭтоСсылка(Тип) Тогда
Возврат Новый Структура("Имя, Тип", Реквизит.Имя, Реквизит.Тип);
КонецЕсли;
КонецЦикла;
Возврат Неопределено;
КонецФункции
Процедура ПроверитьУстранениеПроблемыДокументаОбработкаПроведения(Источник, Отказ, РежимПроведения) Экспорт
// Проверка значения свойства ОбменДанными.Загрузка отсутствует по причине того, что в расположенным ниже коде,
// реализована логика, которая должна выполняться в том числе при установке этого свойства равным Истина
// (на стороне кода, который выполняет попытку записи документа, а также при загрузке документа).
РегистрыСведений.РезультатыОбменаДанными.ЗарегистрироватьУстранениеПроблемы(Источник, Перечисления.ТипыПроблемОбменаДанными.НепроведенныйДокумент);
КонецПроцедуры
Процедура ПроверитьУстранениеПроблемыОбъектаПриЗаписи(Источник, Отказ) Экспорт
// Проверка значения свойства ОбменДанными.Загрузка отсутствует по причине того, что в расположенным ниже коде,
// реализована логика, которая должна выполняться в том числе при установке этого свойства равным Истина
// (на стороне кода, который выполняет попытку записи объекта, а также при загрузке объекта).
РегистрыСведений.РезультатыОбменаДанными.ЗарегистрироватьУстранениеПроблемы(Источник, Перечисления.ТипыПроблемОбменаДанными.НезаполненныеРеквизиты);
КонецПроцедуры
// Получает текущее значение набора записей в информационной базе.
//
// Параметры:
// Данные - набор записей регистров.
//
// Возвращаемое значение:
// НаборЗаписей - содержащий текущее значение в информационной базе.
//
Функция НаборЗаписей(Знач Данные)
ОбъектМетаданных = Данные.Метаданные();
НаборЗаписей = НаборЗаписейПоТипу(ОбъектМетаданных);
Для Каждого ЗначениеОтбора Из Данные.Отбор Цикл
Если ЗначениеОтбора.Использование = Ложь Тогда
Продолжить;
КонецЕсли;
СтрокаОтбора = НаборЗаписей.Отбор.Найти(ЗначениеОтбора.Имя);
СтрокаОтбора.Значение = ЗначениеОтбора.Значение;
СтрокаОтбора.Использование = Истина;
КонецЦикла;
НаборЗаписей.Прочитать();
Возврат НаборЗаписей;
КонецФункции
// Проверяет режим запуска, устанавливает привилегированный режим и выполняет обработчик.
//
Процедура ВыполнитьОбработчикВПривилегированномРежиме(Значение, Знач СтрокаОбработчика)
Если ТекущийРежимЗапуска() = РежимЗапускаКлиентскогоПриложения.УправляемоеПриложение Тогда
ВызватьИсключение НСтр("ru = 'Метод не поддерживается в режиме управляемого приложения.'");
КонецЕсли;
Если ОбщегоНазначения.РазделениеВключено() Тогда
ВызватьИсключение НСтр("ru = 'Метод не поддерживается при работе в модели сервиса.'");
КонецЕсли;
УстановитьПривилегированныйРежим(Истина);
Выполнить(СтрокаОбработчика);
КонецПроцедуры
#КонецОбласти
#Область РаботаСКоллизиямиИзмененияДанныхПриОбмене
// Проверяет наличие коллизий при загрузке
// и выдает информацию есть ли коллизия при обмене.
//
// Параметры:
// ЭлементДанных - Произвольный - произвольные данные.
// ПолучениеЭлемента - ПолучениеЭлементаДанных
// Отправитель - ПланОбменаОбъект
// ЭтоПолучениеОтГлавного - Булево
//
Процедура ПроверитьКоллизиюИзмененийДанных(ЭлементДанных, ПолучениеЭлемента, Знач Отправитель, Знач ЭтоПолучениеОтГлавного)
Если ТипЗнч(ЭлементДанных) = Тип("УдалениеОбъекта") Тогда
Возврат;
ИначеЕсли ЭлементДанных.ДополнительныеСвойства.Свойство("ОбменДанными") И ЭлементДанных.ДополнительныеСвойства.ОбменДанными.АнализДанных Тогда
Возврат;
КонецЕсли;
Отправитель = Отправитель.Ссылка;
МетаданныеОбъекта = ЭлементДанных.Метаданные();
ЭтоСсылочныйТип = ОбщегоНазначения.ЭтоОбъектСсылочногоТипа(МетаданныеОбъекта);
ИмяПланаОбмена = ОбменДаннымиПовтИсп.ПолучитьИмяПланаОбмена(Отправитель);
Если Не ОбменДаннымиПовтИсп.ЭтоПланОбменаРаспределеннойИнформационнойБазы(ИмяПланаОбмена)
И Не ОбменДаннымиПовтИсп.ПланОбменаСодержитОбъект(ИмяПланаОбмена, МетаданныеОбъекта.ПолноеИмя()) Тогда
Возврат;
КонецЕсли;
ЕстьКоллизия = ПланыОбмена.ИзменениеЗарегистрировано(Отправитель, ЭлементДанных);
// Выполняем дополнительную проверку на изменение объекта
// если объект до коллизии и после коллизии не изменен,
// то считаем, что коллизии нет.
Если ЕстьКоллизия Тогда
Если ЭтоСсылочныйТип И Не ЭлементДанных.Ссылка.Пустая() Тогда
ОбъектВБазе = ЭлементДанных.Ссылка.ПолучитьОбъект();
СсылкаСуществует = (ОбъектВБазе <> Неопределено);
Иначе
СсылкаСуществует = Ложь;
ОбъектВБазе = Неопределено;
КонецЕсли;
СтрокаОбъектаДоИзменения = ДанныеОбъектаСтрокойДоИзменения(ЭлементДанных, МетаданныеОбъекта, ЭтоСсылочныйТип, СсылкаСуществует, ОбъектВБазе);
СтрокаОбъектаПослеИзменения = ДанныеОбъектаСтрокойПослеИзменения(ЭлементДанных, МетаданныеОбъекта);
// Если значения совпадают, то коллизии нет.
Если СтрокаОбъектаДоИзменения = СтрокаОбъектаПослеИзменения Тогда
ЕстьКоллизия = Ложь;
КонецЕсли;
КонецЕсли;
Если ЕстьКоллизия Тогда
ОбменДаннымиПереопределяемый.ПриКоллизииИзмененийДанных(ЭлементДанных, ПолучениеЭлемента, Отправитель, ЭтоПолучениеОтГлавного);
Если ПолучениеЭлемента = ПолучениеЭлементаДанных.Авто Тогда
ПолучениеЭлемента = ?(ЭтоПолучениеОтГлавного, ПолучениеЭлементаДанных.Принять, ПолучениеЭлементаДанных.Игнорировать);
КонецЕсли;
ЗаписатьОбъект = (ПолучениеЭлемента = ПолучениеЭлементаДанных.Принять);
ЗарегистрироватьПредупреждениеОКоллизииВЖурналеРегистрации(ЭлементДанных, МетаданныеОбъекта, ЗаписатьОбъект, ЭтоСсылочныйТип);
Если Не ЭтоСсылочныйТип Тогда
Возврат;
КонецЕсли;
Если ОбменДаннымиПовтИсп.ИспользуетсяВерсионирование(Отправитель) Тогда
Если СсылкаСуществует Тогда
Если ЗаписатьОбъект Тогда
ПредупреждениеСинхронизации = НСтр("ru = 'Предыдущая версия (автоматическое разрешение конфликта).'");
Иначе
ПредупреждениеСинхронизации = НСтр("ru = 'Текущая версия (автоматическое разрешение конфликта).'");
КонецЕсли;
СведенияОВерсииОбъекта = Новый Структура("ПредупреждениеСинхронизации, ТипВерсииОбъекта", ПредупреждениеСинхронизации, "НепринятыеДанныеПоКоллизии");
ПриСозданииВерсииОбъекта(ОбъектВБазе, СведенияОВерсииОбъекта, СсылкаСуществует, Отправитель);
КонецЕсли;
СведенияОВерсииОбъекта = Новый Структура;
Если ЗаписатьОбъект Тогда
СведенияОВерсииОбъекта.Вставить("АвторВерсии", Отправитель);
СведенияОВерсииОбъекта.Вставить("ТипВерсииОбъекта", "ПринятыеДанныеПоКоллизии");
СведенияОВерсииОбъекта.Вставить("ПредупреждениеСинхронизации", НСтр("ru = 'Текущая версия (автоматическое разрешение конфликта).'"));
Иначе
СведенияОВерсииОбъекта.Вставить("АвторВерсии", Отправитель);
СведенияОВерсииОбъекта.Вставить("ТипВерсииОбъекта", "НепринятыеДанныеПоКоллизии");
СведенияОВерсииОбъекта.Вставить("ПредупреждениеСинхронизации", НСтр("ru = 'Отклоненная версия (автоматическое разрешение конфликта).'"));
КонецЕсли;
Если ОбменДаннымиПовтИсп.ЭтоУзелРаспределеннойИнформационнойБазы(Отправитель) Тогда
ПриСозданииВерсииОбъекта(ЭлементДанных, СведенияОВерсииОбъекта, СсылкаСуществует, Отправитель);
Иначе
ЭлементДанных.ДополнительныеСвойства.Вставить("СведенияОВерсииОбъекта", СведенияОВерсииОбъекта);
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
// Выполняет проверку на наличие запрета загрузки по дате.
//
// Параметры:
// ЭлементДанных - СправочникОбъект
// - ДокументОбъект
// - РегистрСведенийНаборЗаписей -
// Данные, которые были зачитаны из сообщения обмена, но еще не были записаны в ИБ.
// ПолучениеЭлемента - ПолучениеЭлементаДанных
// Отправитель - ПланОбменаОбъект
//
Процедура ПроверитьНаличиеЗапретаЗагрузкиПоДате(ЭлементДанных, ПолучениеЭлемента, Знач Отправитель)
Если ОбменДаннымиПовтИсп.ЭтоУзелРаспределеннойИнформационнойБазы(Отправитель.Ссылка) Тогда
Возврат;
КонецЕсли;
ЭтоУдалениеОбъекта = (ТипЗнч(ЭлементДанных) = Тип("УдалениеОбъекта"));
Если Не ЭтоУдалениеОбъекта
И ОбщегоНазначения.ЭтоКонстанта(ЭлементДанных.Метаданные()) Тогда
Возврат;
КонецЕсли;
Если Не ЭтоУдалениеОбъекта
И ЭлементДанных.ДополнительныеСвойства.Свойство("УдалятьСозданныеПоКлючевымСвойствам") Тогда
Возврат;
КонецЕсли;
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.ДатыЗапретаИзменения") Тогда
МодульДатыЗапретаИзменения = ОбщегоНазначения.ОбщийМодуль("ДатыЗапретаИзменения");
Отказ = Ложь;
ОписаниеОшибки = "";
МодульДатыЗапретаИзменения.ПроверитьДатыЗапретаЗагрузкиДанных(ЭлементДанных,
Отправитель.Ссылка, Отказ, ОписаниеОшибки);
Если Отказ Тогда
ЗарегистрироватьЗапретЗагрузкиДанныхПоДате(
?(ЭтоУдалениеОбъекта, ЭлементДанных.Ссылка.ПолучитьОбъект(), ЭлементДанных), Отправитель, ОписаниеОшибки);
ПолучениеЭлемента = ПолучениеЭлементаДанных.Игнорировать;
КонецЕсли;
КонецЕсли;
Если Не ЭтоУдалениеОбъекта Тогда
ЭлементДанных.ДополнительныеСвойства.Вставить("ПропуститьПроверкуЗапретаИзменения");
КонецЕсли;
КонецПроцедуры
// Регистрирует запрет на загрузку данных по причине установленной даты запрета загрузки данных
// в журнале регистрации. Для ссылочных типов при наличии подсистемы ВерсионированиеОбъектов
// регистрирует его так же в мониторе проблем обмена.
// Для проверки наличия запрета загрузки по дате см. процедуру
// общего модуля ДатыЗапретаИзменения.ПроверитьДатыЗапретаЗагрузкиДанных.
//
// Параметры:
// Объект - объект ссылочного типа для которого выполняется регистрация запрета.
// УзелОбмена - ПланОбменаСсылка - узел информационной базы из которой получен объект.
// СообщениеОбОшибке - Строка - подробное описание причины отказа от загрузки.
//
Процедура ЗарегистрироватьЗапретЗагрузкиДанныхПоДате(ЭлементДанных, Отправитель, СообщениеОбОшибке)
ЗаписьЖурналаРегистрации(ОбменДаннымиСервер.СобытиеЖурналаРегистрацииОбменДанными(),
УровеньЖурналаРегистрации.Предупреждение, , ЭлементДанных, СообщениеОбОшибке);
Если ОбменДаннымиПовтИсп.ИспользуетсяВерсионирование(Отправитель.Ссылка) И ОбщегоНазначения.ЭтоОбъектСсылочногоТипа(ЭлементДанных.Метаданные()) Тогда
СсылкаНаОбъект = ЭлементДанных.Ссылка;
СсылкаСуществует = ОбщегоНазначения.СсылкаСуществует(СсылкаНаОбъект);
ТипВерсииОбъекта = "";
Если СсылкаСуществует Тогда
ОбъектВБазе = СсылкаНаОбъект.ПолучитьОбъект();
ПредупреждениеСинхронизации = НСтр("ru = 'Версия создана при синхронизации данных.'");
СведенияОВерсииОбъекта = Новый Структура("ПредупреждениеСинхронизации", ПредупреждениеСинхронизации);
ПриСозданииВерсииОбъекта(ОбъектВБазе, СведенияОВерсииОбъекта, СсылкаСуществует, Отправитель);
СтрокаСообщенияОбОшибке = СообщениеОбОшибке;
ТипВерсииОбъекта = "НепринятыйПоДатеЗапретаОбъектСуществуетВБазе";
Иначе
СтрокаСообщенияОбОшибке = НСтр("ru = '%1 запрещено загружать в запрещенный период.%2%2%3'");
СтрокаСообщенияОбОшибке = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(СтрокаСообщенияОбОшибке, Строка(ЭлементДанных), Символы.ПС, СообщениеОбОшибке);
ТипВерсииОбъекта = "НепринятыйПоДатеЗапретаОбъектНеСуществуетВБазе";
КонецЕсли;
НепринятыеПоДатеЗапрета = Новый Соответствие;
Если Не Отправитель.ДополнительныеСвойства.Свойство("НепринятыеПоДатеЗапрета") Тогда
Отправитель.ДополнительныеСвойства.Вставить("НепринятыеПоДатеЗапрета", НепринятыеПоДатеЗапрета);
Иначе
НепринятыеПоДатеЗапрета = Отправитель.ДополнительныеСвойства.НепринятыеПоДатеЗапрета;
КонецЕсли;
НепринятыеПоДатеЗапрета.Вставить(СсылкаНаОбъект, ТипВерсииОбъекта);
СведенияОВерсииОбъекта = Новый Структура;
СведенияОВерсииОбъекта.Вставить("АвторВерсии", ОбщегоНазначения.МенеджерОбъектаПоСсылке(Отправитель.Ссылка).НайтиПоКоду(Отправитель.Код));
СведенияОВерсииОбъекта.Вставить("ТипВерсииОбъекта", ТипВерсииОбъекта);
СведенияОВерсииОбъекта.Вставить("Комментарий", "");
СведенияОВерсииОбъекта.Вставить("ПредупреждениеСинхронизации", СтрокаСообщенияОбОшибке);
Если ОбщегоНазначения.ЭтоДокумент(ЭлементДанных.Метаданные())
И ТипВерсииОбъекта = "НепринятыйПоДатеЗапретаОбъектНеСуществуетВБазе" Тогда
СвойствоПроведен = Новый Структура("Проведен", Ложь);
ЗаполнитьЗначенияСвойств(ЭлементДанных, СвойствоПроведен);
КонецЕсли;
ПриСозданииВерсииОбъекта(ЭлементДанных, СведенияОВерсииОбъекта, СсылкаСуществует, Отправитель);
КонецЕсли;
КонецПроцедуры
// Параметры:
// Объект - СправочникОбъект, ДокументОбъект, и т.п - элемент данных.
// МетаданныеОбъекта - ОбъектМетаданных - метаданные элемента данных.
// ЗаписатьОбъект - Булево - Истина, если было выполнено замещение объекта этой ИБ полученным объектом.
// ЭтоСсылочныйТип - Булево - Истина, если объект ссылочного типа.
//
Процедура ЗарегистрироватьПредупреждениеОКоллизииВЖурналеРегистрации(Объект, МетаданныеОбъекта, ЗаписатьОбъект, ЭтоСсылочныйТип)
Если ЗаписатьОбъект Тогда
ТекстПредупрежденияЖР = НСтр("ru = 'Возник конфликт изменений объектов.
|Объект этой информационной базы был заменен версией объекта из второй информационной базы.'");
Иначе
ТекстПредупрежденияЖР = НСтр("ru = 'Возник конфликт изменений объектов.
|Объект из второй информационной базы не принят. Объект этой информационной базы не изменен.'");
КонецЕсли;
Данные = ?(ЭтоСсылочныйТип, Объект.Ссылка, Неопределено);
ЗаписьЖурналаРегистрации(ОбменДаннымиСервер.СобытиеЖурналаРегистрацииОбменДанными(),
УровеньЖурналаРегистрации.Предупреждение, МетаданныеОбъекта, Данные, ТекстПредупрежденияЖР);
КонецПроцедуры
// Параметры:
// Объект - Произвольный
// МетаданныеОбъекта - ОбъектМетаданных
// ЭтоСсылочныйТип - Булево
// СсылкаСуществует - Булево
// ОбъектВБазе - ЛюбаяСсылка
// - Неопределено
//
Функция ДанныеОбъектаСтрокойДоИзменения(Объект, МетаданныеОбъекта, ЭтоСсылочныйТип, СсылкаСуществует, ОбъектВБазе)
// Возвращаемое значение функции.
СтрокаОбъекта = "";
Если ЭтоСсылочныйТип Тогда
Если СсылкаСуществует Тогда
// Получаем представление объекта из ИБ по ссылке.
СтрокаОбъекта = ОбщегоНазначения.ЗначениеВСтрокуXML(ОбъектВБазе);
Иначе
СтрокаОбъекта = НСтр("ru = 'Объект удален'");
КонецЕсли;
ИначеЕсли ОбщегоНазначения.ЭтоКонстанта(МетаданныеОбъекта) Тогда
// Получаем значение константы из ИБ.
СтрокаОбъекта = XMLСтрока(Константы[МетаданныеОбъекта.Имя].Получить());
Иначе // Набор записей
СтарыйНаборЗаписей = НаборЗаписей(Объект);
СтрокаОбъекта = ОбщегоНазначения.ЗначениеВСтрокуXML(СтарыйНаборЗаписей);
КонецЕсли;
Возврат СтрокаОбъекта;
КонецФункции
Функция ДанныеОбъектаСтрокойПослеИзменения(Объект, МетаданныеОбъекта)
// Возвращаемое значение функции.
СтрокаОбъекта = "";
Если ОбщегоНазначения.ЭтоКонстанта(МетаданныеОбъекта) Тогда
СтрокаОбъекта = XMLСтрока(Объект.Значение);
Иначе
СтрокаОбъекта = ОбщегоНазначения.ЗначениеВСтрокуXML(Объект);
КонецЕсли;
Возврат СтрокаОбъекта;
КонецФункции
#КонецОбласти
#КонецОбласти