Загрузка данных
///////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2026, ООО 1С-Софт
// Все права защищены. Эта программа и сопроводительные материалы предоставляются
// в соответствии с условиями лицензии Attribution 4.0 International (CC BY 4.0)
// Текст лицензии доступен по ссылке:
// https://creativecommons.org/licenses/by/4.0/legalcode
///////////////////////////////////////////////////////////////////////////////////////////////////////
#Если Сервер Или ТолстыйКлиентОбычноеПриложение Или ВнешнееСоединение Тогда
#Область ОписаниеПеременных
Перем ДоступностьОбъектовПоОпциям Экспорт;
#КонецОбласти
#Область ПрограммныйИнтерфейс
// Возвращает дерево значений, заполненное данными для выбора узла обмена. В дереве 2 уровня:
// план обмена -> узлы обмена. Служебные узлы выброшены.
//
// Параметры:
// ОбъектДанных - ЛюбаяСсылка
// - Структура - ссылка или структура со значениями измерений набор записей. Для этих
// данных которых анализируются узлы обмена. Если не указано, то для всех.
// ИмяТаблицы - Строка - если ОбъектДанных - структура, то имя таблицы для набора записей.
//
// Возвращаемое значение:
// ДеревоЗначений:
// * Наименование - Строка - представление плана обмена или узла обмена.
// * ИндексКартинки - Число - 1 = план обмена, 2 = узел , 3 = помеченный для удаления узел.
// * ИндексКартинкиАвторегистрация - Число - если не указан параметр ОбъектДанных, то Неопределено.
// Иначе: 0 = нет, 1 = запрещена, 2 = разрешена, Неопределено для
// плана обмена.
// * ПланОбменаИмя - Строка - имя плана обмена узла.
// * Ссылка - ПланОбменаСсылка - ссылка узла, Неопределено для плана обмена.
// * Код - Число
// - Строка - код узла, Неопределено для плана обмена.
// * НомерОтправленного - Число - данные узла.
// * НомерПринятого - Число - данные узла.
// * НомерСообщения - Число
// - Null - если указан объект, то номер сообщения для него, иначе NULL.
// * НеВыгружалось - Булево
// - Null - если указан объект, то флаг выгрузки, иначе NULL.
// * Пометка - Булево - если указан объект, то 0 = нет регистрации, 1 - есть, иначе
// всегда 0.
// * ИсходнаяПометка - Булево - аналогично колонке "Пометка".
// * ИдентификаторСтроки - Число - индекс добавленной строки (обход дерева сверху вниз слева
// направо).
//
Функция СформироватьДеревоУзлов(ОбъектДанных = Неопределено, ИмяТаблицы = Неопределено) Экспорт
Дерево = Новый ДеревоЗначений; // см. СформироватьДеревоУзлов
Колонки = Дерево.Колонки;
Строки = Дерево.Строки;
Колонки.Добавить("Наименование");
Колонки.Добавить("ИндексКартинки");
Колонки.Добавить("ИндексКартинкиАвторегистрация");
Колонки.Добавить("ПланОбменаИмя");
Колонки.Добавить("Ссылка");
Колонки.Добавить("Код");
Колонки.Добавить("НомерОтправленного");
Колонки.Добавить("НомерПринятого");
Колонки.Добавить("НомерСообщения");
Колонки.Добавить("НеВыгружалось");
Колонки.Добавить("Пометка");
Колонки.Добавить("ИсходнаяПометка");
Колонки.Добавить("ИдентификаторСтроки");
ТекстПодзапроса = "";
Запрос = Новый Запрос;
Если ОбъектДанных = Неопределено Тогда
МетаОбъект = Неопределено;
ТекстЗапроса =
"ВЫБРАТЬ
| ПРЕДСТАВЛЕНИЕССЫЛКИ(ПланОбмена.Ссылка) КАК Наименование,
| ВЫБОР
| КОГДА ПланОбмена.ПометкаУдаления
| ТОГДА 2
| ИНАЧЕ 1
| КОНЕЦ КАК ИндексКартинки,
| ""&ТекстовоеПредставлениеПланаОбмена"" КАК ПланОбменаИмя,
| ПланОбмена.Код КАК Код,
| ПланОбмена.Ссылка КАК Ссылка,
| ПланОбмена.НомерОтправленного КАК НомерОтправленного,
| ПланОбмена.НомерПринятого КАК НомерПринятого,
| NULL КАК НомерСообщения,
| NULL КАК НеВыгружалось,
| 0 КАК КоличествоИзмененийНаУзле
|ИЗ
| &ИмяТаблицыПланаОбмена КАК ПланОбмена
|ГДЕ
| НЕ ПланОбмена.ЭтотУзел";
Иначе
Если ТипЗнч(ОбъектДанных) = Тип("Структура") Тогда
Для Каждого КлючЗначение Из ОбъектДанных Цикл
ТекИмя = КлючЗначение.Ключ;
ТекстПодзапроса = ТекстПодзапроса + "
|И ТаблицаИзменений." + ТекИмя + " = &" + ТекИмя;
Запрос.УстановитьПараметр(ТекИмя, ОбъектДанных[ТекИмя]);
КонецЦикла;
ТекИмяТаблицы = ИмяТаблицы;
МетаОбъект = МетаданныеПоПолномуИмени(ИмяТаблицы);
ИначеЕсли ТипЗнч(ОбъектДанных) = Тип("Строка") Тогда
ТекИмяТаблицы = ОбъектДанных;
МетаОбъект = МетаданныеПоПолномуИмени(ОбъектДанных);
Иначе
ТекстПодзапроса = "
|И ТаблицаИзменений.Ссылка = &ОбъектРегистрации";
Запрос.УстановитьПараметр("ОбъектРегистрации", ОбъектДанных);
МетаОбъект = ОбъектДанных.Метаданные();
ТекИмяТаблицы = МетаОбъект.ПолноеИмя();
КонецЕсли;
ТекстЗапроса =
"ВЫБРАТЬ
| ПРЕДСТАВЛЕНИЕССЫЛКИ(ПланОбмена.Ссылка) КАК Наименование,
| ВЫБОР
| КОГДА ПланОбмена.ПометкаУдаления
| ТОГДА 2
| ИНАЧЕ 1
| КОНЕЦ КАК ИндексКартинки,
| ""&ТекстовоеПредставлениеПланаОбмена"" КАК ПланОбменаИмя,
| ПланОбмена.Код КАК Код,
| ПланОбмена.Ссылка КАК Ссылка,
| ПланОбмена.НомерОтправленного КАК НомерОтправленного,
| ПланОбмена.НомерПринятого КАК НомерПринятого,
| ТаблицаИзменений.НомерСообщения КАК НомерСообщения,
| ВЫБОР
| КОГДА ТаблицаИзменений.НомерСообщения ЕСТЬ NULL
| ТОГДА ИСТИНА
| ИНАЧЕ ЛОЖЬ
| КОНЕЦ КАК НеВыгружалось,
| КОЛИЧЕСТВО(ТаблицаИзменений.Узел) КАК КоличествоИзмененийНаУзле
|ИЗ
| &ИмяТаблицыПланаОбмена КАК ПланОбмена
| ЛЕВОЕ СОЕДИНЕНИЕ Справочник.СценарииОбменовДанными.Изменения КАК ТаблицаИзменений
| ПО ПланОбмена.Ссылка = ТаблицаИзменений.Узел
| И &УсловияОбъединенияТаблиц
|ГДЕ
| НЕ ПланОбмена.ЭтотУзел
|
|СГРУППИРОВАТЬ ПО
| ПланОбмена.Ссылка,
| ТаблицаИзменений.НомерСообщения,
| ВЫБОР
| КОГДА ПланОбмена.ПометкаУдаления
| ТОГДА 2
| ИНАЧЕ 1
| КОНЕЦ,
| ПланОбмена.Код,
| ПланОбмена.НомерОтправленного,
| ПланОбмена.НомерПринятого,
| ВЫБОР
| КОГДА ТаблицаИзменений.НомерСообщения ЕСТЬ NULL
| ТОГДА ИСТИНА
| ИНАЧЕ ЛОЖЬ
| КОНЕЦ";
КонецЕсли;
ТекНомерСтроки = 0;
Для Каждого Мета Из Метаданные.ПланыОбмена Цикл
Если Не ПравоДоступа("Чтение", Мета) Тогда
Продолжить;
КонецЕсли;
ИмяПлана = Мета.Имя;
Авторегистрация = Неопределено;
Если МетаОбъект <> Неопределено Тогда
ЭлементСостава = Мета.Состав.Найти(МетаОбъект);
Если ЭлементСостава = Неопределено Тогда
// Не входит в текущий план обмена.
Продолжить;
КонецЕсли;
Авторегистрация = ?(ЭлементСостава.Авторегистрация = АвтоРегистрацияИзменений.Запретить, 1, 2);
КонецЕсли;
ИмяПлана = Мета.Имя;
Запрос.Текст = СтрЗаменить(ТекстЗапроса, "&ТекстовоеПредставлениеПланаОбмена", ИмяПлана);
Запрос.Текст = СтрЗаменить(Запрос.Текст, "&ИмяТаблицыПланаОбмена", ПодставитьПараметрыВСтроку("ПланОбмена.%1", ИмяПлана));
Запрос.Текст = СтрЗаменить(Запрос.Текст, "Справочник.СценарииОбменовДанными", ТекИмяТаблицы);
Запрос.Текст = СтрЗаменить(Запрос.Текст, "И &УсловияОбъединенияТаблиц", ТекстПодзапроса);
Результат = Запрос.Выполнить();
Если Не Результат.Пустой() Тогда
СтрокаПлана = Строки.Добавить();
СтрокаПлана.Наименование = Мета.Представление();
СтрокаПлана.ИндексКартинки = 0;
СтрокаПлана.ПланОбменаИмя = ИмяПлана;
СтрокаПлана.ИдентификаторСтроки = ТекНомерСтроки;
ТекНомерСтроки = ТекНомерСтроки + 1;
// Сортировка по представлению, в запросе нельзя.
ВременнаяТаблица = Результат.Выгрузить();
ВременнаяТаблица.Сортировать("Наименование");
Для Каждого СтрокаУзла Из ВременнаяТаблица Цикл;
НоваяСтрока = СтрокаПлана.Строки.Добавить();
ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаУзла);
НоваяСтрока.ИсходнаяПометка = ?(СтрокаУзла.КоличествоИзмененийНаУзле > 0, 1, 0);
НоваяСтрока.Пометка = НоваяСтрока.ИсходнаяПометка;
НоваяСтрока.ИндексКартинкиАвторегистрация = Авторегистрация;
НоваяСтрока.ИдентификаторСтроки = ТекНомерСтроки;
ТекНомерСтроки = ТекНомерСтроки + 1;
КонецЦикла;
КонецЕсли;
КонецЦикла;
Возврат Дерево;
КонецФункции
// Возвращает структуру, описывающую метаданные для плана обмена.
// Объекты, не входящие в состав плана обмена, исключаются.
//
// Параметры:
// ИмяПланаОбмена - Строка - имя метаданных плана обмена, для которого строится дерево конфигурации.
// - ПланОбменаСсылка - дерево конфигурации строится для его плана обмена.
// - Неопределено - строится дерево всей конфигурации.
//
// Возвращаемое значение:
// Структура - описание метаданных. Поля:
// * СтруктураИмен - Структура - Ключ - группа метаданных (константы, справочники и т.п.),
// значение - массив полных имен.
// * СтруктураПредставлений - Структура - Ключ - группа метаданных (константы, справочники и т.п.),
// значение - массив полных имен.
// * СтруктураАвторегистрации - Структура - Ключ - группа метаданных (константы, справочники и т.п.),
// значение - массив флагов авторегистрации на узле.
// * Дерево - см. ДеревоОбъектовМетаданных
//
Функция СформироватьСтруктуруМетаданных(ИмяПланаОбмена = Неопределено) Экспорт
Дерево = ДеревоОбъектовМетаданных();
// Корень
СтрокаКорень = Дерево.Строки.Добавить();
СтрокаКорень.Наименование = Метаданные.Представление();
СтрокаКорень.ИндексКартинки = 0;
СтрокаКорень.ИдентификаторСтроки = 0;
// Параметры
ТекПараметры = Новый Структура;
ТекПараметры.Вставить("СтруктураИмен", Новый Структура);
ТекПараметры.Вставить("СтруктураПредставлений", Новый Структура);
ТекПараметры.Вставить("СтруктураАвторегистрации", Новый Структура);
ТекПараметры.Вставить("Строки", СтрокаКорень.Строки);
Если ИмяПланаОбмена = Неопределено Тогда
ПланОбмена = Неопределено;
ИначеЕсли ТипЗнч(ИмяПланаОбмена) = Тип("Строка") Тогда
ПланОбмена = Метаданные.ПланыОбмена[ИмяПланаОбмена];
Иначе
ПланОбмена = ИмяПланаОбмена.Метаданные();
КонецЕсли;
ТекПараметры.Вставить("ПланОбмена", ПланОбмена);
// Для планов обмена РИБ из доступных к регистрации должны быть исключены
// объекты метаданных, не входящие в соответствующие подписки МРО
// (т.е. объекты, которые выгружаются только в составе начального образа).
Если ПланОбмена <> Неопределено
И ПланОбмена.РаспределеннаяИнформационнаяБаза
И КонфигурацияПоддерживаетБСП Тогда
СоставПодписокМРО = Новый Массив;
ПрефиксИмениПодписки = ПланОбмена.Имя + "Регистрация";
Для Каждого Подписка Из Метаданные.ПодпискиНаСобытия Цикл
Если Не СтрНачинаетсяС(Подписка.Имя, ПрефиксИмениПодписки) Тогда
Продолжить;
КонецЕсли;
Для Каждого ТипИсточника Из Подписка.Источник.Типы() Цикл
МетаданныеИсточника = Метаданные.НайтиПоТипу(ТипИсточника);
Если СоставПодписокМРО.Найти(МетаданныеИсточника) = Неопределено Тогда
СоставПодписокМРО.Добавить(МетаданныеИсточника);
КонецЕсли;
КонецЦикла;
КонецЦикла;
ТекПараметры.Вставить("СоставПодписокМРО", СоставПодписокМРО);
КонецЕсли;
Результат = Новый Структура();
Результат.Вставить("Дерево", Дерево);
Результат.Вставить("СтруктураИмен", ТекПараметры.СтруктураИмен);
Результат.Вставить("СтруктураПредставлений", ТекПараметры.СтруктураПредставлений);
Результат.Вставить("СтруктураАвторегистрации", ТекПараметры.СтруктураАвторегистрации);
ТекНомерСтроки = 1;
СформироватьУровеньМетаданных(ТекНомерСтроки, ТекПараметры, 1, 2, Ложь, "Константы", НСтр("ru = 'Константы'"));
СформироватьУровеньМетаданных(ТекНомерСтроки, ТекПараметры, 3, 4, Истина, "Справочники", НСтр("ru = 'Справочники'"));
СформироватьУровеньМетаданных(ТекНомерСтроки, ТекПараметры, 5, 6, Истина, "Последовательности", НСтр("ru = 'Последовательности'"));
СформироватьУровеньМетаданных(ТекНомерСтроки, ТекПараметры, 7, 8, Истина, "Документы", НСтр("ru = 'Документы'"));
СформироватьУровеньМетаданных(ТекНомерСтроки, ТекПараметры, 9, 10, Истина, "ПланыВидовХарактеристик", НСтр("ru = 'Планы видов характеристик'"));
СформироватьУровеньМетаданных(ТекНомерСтроки, ТекПараметры, 11, 12, Истина, "ПланыСчетов", НСтр("ru = 'Планы счетов'"));
СформироватьУровеньМетаданных(ТекНомерСтроки, ТекПараметры, 13, 14, Истина, "ПланыВидовРасчета", НСтр("ru = 'Планы видов расчета'"));
СформироватьУровеньМетаданных(ТекНомерСтроки, ТекПараметры, 15, 16, Истина, "РегистрыСведений", НСтр("ru = 'Регистры сведений'"));
СформироватьУровеньМетаданных(ТекНомерСтроки, ТекПараметры, 17, 18, Истина, "РегистрыНакопления", НСтр("ru = 'Регистры накопления'"));
СформироватьУровеньМетаданных(ТекНомерСтроки, ТекПараметры, 19, 20, Истина, "РегистрыБухгалтерии", НСтр("ru = 'Регистры бухгалтерии'"));
СформироватьУровеньМетаданных(ТекНомерСтроки, ТекПараметры, 21, 22, Истина, "РегистрыРасчета", НСтр("ru = 'Регистры расчета'"));
СформироватьУровеньМетаданных(ТекНомерСтроки, ТекПараметры, 23, 24, Истина, "БизнесПроцессы", НСтр("ru = 'Бизнес-процессы'"));
СформироватьУровеньМетаданных(ТекНомерСтроки, ТекПараметры, 25, 26, Истина, "Задачи", НСтр("ru = 'Задачи'"));
Возврат Результат;
КонецФункции
// Вычисляет количества изменений для объектов метаданных для узлов обмена.
//
// Параметры:
// СписокТаблиц - Структура
// - Массив из Структура - имена. Может быть коллекцией "ключ/значение",
// где "значение" - массивы имен.
// СписокУзлов - ПланОбменаСсылка
// - Массив из ПланОбменаСсылка - узлы.
//
// Возвращаемое значение:
// ТаблицаЗначений:
// * МетаПолноеИмя - Строка - полное имя метаданных, для которых рассчитываем количество.
// * УзелОбмена - ПланОбменаСсылка - ссылка на узел обмена, для которого рассчитываем количество.
// * КоличествоИзменений - Число - содержит общее количество изменений.
// * КоличествоВыгруженных - Число - содержит количество выгруженных изменений.
// * КоличествоНеВыгруженных - Число - содержит количество не выгруженных изменений.
//
Функция ПолучитьКоличествоИзменений(СписокТаблиц, СписокУзлов) Экспорт
Результат = Новый ТаблицаЗначений;
Колонки = Результат.Колонки;
Колонки.Добавить("МетаПолноеИмя");
Колонки.Добавить("УзелОбмена");
Колонки.Добавить("КоличествоИзменений");
Колонки.Добавить("КоличествоВыгруженных");
Колонки.Добавить("КоличествоНеВыгруженных");
Результат.Индексы.Добавить("МетаПолноеИмя");
Результат.Индексы.Добавить("УзелОбмена");
Запрос = Новый Запрос;
Запрос.УстановитьПараметр("СписокУзлов", СписокУзлов);
// На входе или массив или структура/соответствие со многими массивами.
Если СписокТаблиц = Неопределено Тогда
Возврат Результат;
ИначеЕсли ТипЗнч(СписокТаблиц) = Тип("Массив") Тогда
Источник = Новый Структура("_", СписокТаблиц);
Иначе
Источник = СписокТаблиц;
КонецЕсли;
ШаблонТекстаЗапроса =
"ВЫБРАТЬ
| ""&ПредставлениеТаблицыМетаданных"" КАК МетаПолноеИмя,
| ИмяТаблицыМетаданных.Узел КАК УзелОбмена,
| КОЛИЧЕСТВО(*) КАК КоличествоИзменений,
| КОЛИЧЕСТВО(ИмяТаблицыМетаданных.НомерСообщения) КАК КоличествоВыгруженных,
| КОЛИЧЕСТВО(*) - КОЛИЧЕСТВО(ИмяТаблицыМетаданных.НомерСообщения) КАК КоличествоНеВыгруженных
|ИЗ
| Справочник.СценарииОбменовДанными.Изменения КАК ИмяТаблицыМетаданных
|ГДЕ
| ИмяТаблицыМетаданных.Узел В (&СписокУзлов)
|СГРУППИРОВАТЬ ПО
| ИмяТаблицыМетаданных.Узел";
// Пачками по 200 таблиц в запросе.
Текст = "";
Номер = 0;
Для Каждого КлючЗначение Из Источник Цикл
Если ТипЗнч(КлючЗначение.Значение) <> Тип("Массив") Тогда
Продолжить;
КонецЕсли;
Для Каждого Элемент Из КлючЗначение.Значение Цикл
Если ПустаяСтрока(Элемент) Тогда
Продолжить;
КонецЕсли;
Если Не ПравоДоступа("Чтение", Метаданные.НайтиПоПолномуИмени(Элемент)) Тогда
Продолжить;
КонецЕсли;
ТекстПодзапроса = СтрЗаменить(ШаблонТекстаЗапроса, "&ПредставлениеТаблицыМетаданных", СокрЛП(Элемент));
ТекстПодзапроса = СтрЗаменить(ТекстПодзапроса, "Справочник.СценарииОбменовДанными", СокрЛП(Элемент));
Если ПустаяСтрока(Текст) Тогда
Текст = ТекстПодзапроса;
Иначе
Текст = Текст + Символы.ПС + "ОБЪЕДИНИТЬ ВСЕ" + Символы.ПС + ТекстПодзапроса;
КонецЕсли;
Номер = Номер + 1;
Если Номер = 200 Тогда
Запрос.Текст = Текст;
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
ЗаполнитьЗначенияСвойств(Результат.Добавить(), Выборка);
КонецЦикла;
Текст = "";
Номер = 0;
КонецЕсли;
КонецЦикла;
КонецЦикла;
// Дочитываем хвосты
Если Текст <> "" Тогда
Запрос.Текст = Текст;
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
ЗаполнитьЗначенияСвойств(Результат.Добавить(), Выборка);
КонецЦикла;
КонецЕсли;
Возврат Результат;
КонецФункции
// Возвращает объект метаданных по его полному имени. Пустая строка обозначает конфигурацию.
//
// Параметры:
// ИмяМетаданных - Строка - имя объекта метаданных, например "Справочник.Валюты" или "Константы".
//
// Возвращаемое значение:
// ОбъектМетаданных - результат поиска.
//
Функция МетаданныеПоПолномуИмени(ИмяМетаданных) Экспорт
Если ПустаяСтрока(ИмяМетаданных) Тогда
// Вся конфигурация
Возврат Метаданные;
КонецЕсли;
Значение = Метаданные.НайтиПоПолномуИмени(ИмяМетаданных);
Если Значение = Неопределено Тогда
Значение = Метаданные[ИмяМетаданных];
КонецЕсли;
Возврат Значение;
КонецФункции
// Возвращает флаг регистрации объекта на узле.
//
// Параметры:
// Узел - ПланОбменаСсылка - узел плана обмена для которого получаем информацию,
// ОбъектРегистрации - Строка
// - ЛюбаяСсылка
// - Структура - объект, для которого получаем информацию.
// Структура хранит значения изменений набора записей.
// ИмяТаблицы - Строка - если ОбъектРегистрации - структура, то содержит имя таблицы для набора измерений.
//
// Возвращаемое значение:
// Булево - результат регистрации.
//
Функция ОбъектЗарегистрированНаУзле(Узел, ОбъектРегистрации, ИмяТаблицы = Неопределено) Экспорт
ТипПараметра = ТипЗнч(ОбъектРегистрации);
Если ТипПараметра = Тип("Строка") Тогда
// Константа как метаданные
Описание = ХарактеристикиПоМетаданным(ОбъектРегистрации);
ТекущийОбъект = Описание.Менеджер.СоздатьМенеджерЗначения();
ИначеЕсли ТипПараметра = Тип("Структура") Тогда
// Набор измерений, ИмяТаблицы - чего.
Описание = ХарактеристикиПоМетаданным(ИмяТаблицы);
ТекущийОбъект = Описание.Менеджер.СоздатьНаборЗаписей();
Для Каждого КлючЗначение Из ОбъектРегистрации Цикл
УстановитьЗначениеЭлементаОтбора(ТекущийОбъект.Отбор, КлючЗначение.Ключ, КлючЗначение.Значение);
КонецЦикла;
Иначе
ТекущийОбъект = ОбъектРегистрации;
КонецЕсли;
Возврат ПланыОбмена.ИзменениеЗарегистрировано(Узел, ТекущийОбъект);
КонецФункции
#Область ДляВызоваИзДругихПодсистем
// СтандартныеПодсистемы.ДополнительныеОтчетыИОбработки
// Возвращает сведения о внешней обработке.
//
// Возвращаемое значение:
// см. ДополнительныеОтчетыИОбработки.СведенияОВнешнейОбработке
//
Функция СведенияОВнешнейОбработке() Экспорт
Инфо = Новый Структура;
Инфо.Вставить("Вид", "СозданиеСвязанныхОбъектов");
Инфо.Вставить("Команды", Новый ТаблицаЗначений);
Инфо.Вставить("БезопасныйРежим", Истина);
Инфо.Вставить("Назначение", Новый Массив);
Инфо.Вставить("Наименование", НСтр("ru = 'Регистрация изменений для обмена данными'"));
Инфо.Вставить("Версия", "1.0");
Инфо.Вставить("ВерсияБСП", "1.2.1.4");
Инфо.Вставить("Информация", НСтр("ru = 'Обработка для управления регистрацией объектов на узлах обмена до формирования выгрузки. При работе в составе конфигурации с БСП версии 2.1.2.0 и старше производит контроль ограничений миграции данных для узлов обмена.'"));
Инфо.Назначение.Добавить("ПланыОбмена.*");
Инфо.Назначение.Добавить("Константы.*");
Инфо.Назначение.Добавить("Справочники.*");
Инфо.Назначение.Добавить("Документы.*");
Инфо.Назначение.Добавить("Последовательности.*");
Инфо.Назначение.Добавить("ПланыВидовХарактеристик.*");
Инфо.Назначение.Добавить("ПланыСчетов.*");
Инфо.Назначение.Добавить("ПланыВидовРасчета.*");
Инфо.Назначение.Добавить("РегистрыСведений.*");
Инфо.Назначение.Добавить("РегистрыНакопления.*");
Инфо.Назначение.Добавить("РегистрыБухгалтерии.*");
Инфо.Назначение.Добавить("РегистрыРасчета.*");
Инфо.Назначение.Добавить("БизнесПроцессы.*");
Инфо.Назначение.Добавить("Задачи.*");
Колонки = Инфо.Команды.Колонки;
ТипСтрока = Новый ОписаниеТипов("Строка");
Колонки.Добавить("Представление", ТипСтрока);
Колонки.Добавить("Идентификатор", ТипСтрока);
Колонки.Добавить("Использование", ТипСтрока);
Колонки.Добавить("Модификатор", ТипСтрока);
Колонки.Добавить("ПоказыватьОповещение", Новый ОписаниеТипов("Булево"));
// Единственная команда, что делать - определяем по типу переданного.
Команда = Инфо.Команды.Добавить();
Команда.Представление = НСтр("ru = 'Редактирование регистрации изменений объекта'");
Команда.Идентификатор = "ОткрытьФормуРедактированияРегистрации";
Команда.Использование = "ВызовКлиентскогоМетода";
Возврат Инфо;
КонецФункции
// Конец СтандартныеПодсистемы.ДополнительныеОтчетыИОбработки
#КонецОбласти
#КонецОбласти
#Область СлужебныеПроцедурыИФункции
// Запускает изменение регистрации в соответствии с переданными параметрами.
// Параметры:
// ПараметрыЗадания - Структура - параметры для изменения регистрации:
// * Команда - Булево - Истина, если надо добавлять, Ложь, если удалять.
// * БезУчетаАвторегистрации - Булево - Истина, если не надо анализировать флаг авторегистрации.
// * Узел - ПланОбменаСсылка - ссылка на узел плана обмена.
// * Данные - ЛюбаяСсылка
// - Строка
// - Структура - данные или массив таких данных.
// * ИмяТаблицы - Строка - если Данные является структурой, то содержит имя таблицы.
// АдресХранилища - Произвольный - адрес временного хранилища для сохранения результата при запуске в фоновом задании.
//
// Возвращаемое значение:
// Структура:
// * Всего - Число - общее число объектов.
// * Успешно - Число - числом успешно обработанных объектов.
// * Команда - значение входящего параметра Команда для упрощения обработки результатов.
//
Функция ВыполнитьИзменениеРегистрации(ПараметрыЗадания, АдресХранилища = Неопределено) Экспорт
ИмяТаблицы = Неопределено;
ПараметрыЗадания.Свойство("ИмяТаблицы", ИмяТаблицы);
КонфигурацияПоддерживаетБСП = ПараметрыЗадания.КонфигурацияПоддерживаетБСП;
ДоступнаРегистрацияСредствамиБСП = ПараметрыЗадания.ДоступнаРегистрацияСредствамиБСП;
ДоступнаРаботаРИБ = ПараметрыЗадания.ДоступнаРаботаРИБ;
НастройкаКонтрольВыгрузкиОбъектов = ПараметрыЗадания.НастройкаКонтрольВыгрузкиОбъектов;
ДоступнаПакетнаяРегистрация = ПараметрыЗадания.ДоступнаПакетнаяРегистрация;
РезультатВыполнения = ИзменитьРегистрациюНаСервере(ПараметрыЗадания.Команда, ПараметрыЗадания.БезУчетаАвторегистрации,
ПараметрыЗадания.Узел, ПараметрыЗадания.Данные, ИмяТаблицы, ПараметрыЗадания.СтруктураИменМетаданных);
Если АдресХранилища <> Неопределено Тогда
ПоместитьВоВременноеХранилище(РезультатВыполнения, АдресХранилища);
КонецЕсли;
Возврат РезультатВыполнения;
КонецФункции
// Возвращает начало полного имени формы для открытия по переданному объекту.
//
// Параметры:
// ТекущийОбъект - Строка, ДинамическийСписок - для которого необходимо получить имя формы.
// Возвращаемое значение:
// Строка - полное имя формы.
//
Функция ПолучитьИмяФормы(ТекущийОбъект = Неопределено) Экспорт
Тип = ТипЗнч(ТекущийОбъект);
Если Тип = Тип("ДинамическийСписок") Тогда
Возврат ТекущийОбъект.ОсновнаяТаблица + ".";
ИначеЕсли Тип = Тип("Строка") Тогда
Возврат ТекущийОбъект + ".";
КонецЕсли;
Мета = ?(ТекущийОбъект = Неопределено, Метаданные(), ТекущийОбъект.Метаданные());
Возврат Мета.ПолноеИмя() + ".";
КонецФункции
// Рекурсивное обслуживание иерархических пометок с тремя состояниями в дереве.
//
// Параметры:
// ДанныеСтроки - ДанныеФормыЭлементДерева - пометка хранится в числовой колонке "Пометка".
//
Процедура ИзменениеПометки(ДанныеСтроки) Экспорт
ДанныеСтроки.Пометка = ДанныеСтроки.Пометка % 2;
ПроставитьПометкиВниз(ДанныеСтроки);
ПроставитьПометкиВверх(ДанныеСтроки);
КонецПроцедуры
// Рекурсивное обслуживание иерархических пометок с тремя состояниями в дереве.
//
// Параметры:
// ДанныеСтроки - ДанныеФормыЭлементДерева - пометка хранится в числовой колонке "Пометка".
//
Процедура ПроставитьПометкиВниз(ДанныеСтроки) Экспорт
Значение = ДанныеСтроки.Пометка;
Для Каждого Потомок Из ДанныеСтроки.ПолучитьЭлементы() Цикл
Потомок.Пометка = Значение;
ПроставитьПометкиВниз(Потомок);
КонецЦикла;
КонецПроцедуры
// Рекурсивное обслуживание иерархических пометок с тремя состояниями в дереве.
//
// Параметры:
// ДанныеСтроки - ДанныеФормыЭлементДерева - пометка хранится в числовой колонке "Пометка".
//
Процедура ПроставитьПометкиВверх(ДанныеСтроки) Экспорт
РодительСтроки = ДанныеСтроки.ПолучитьРодителя();
Если РодительСтроки <> Неопределено Тогда
ВсеИстина = Истина;
НеВсеЛожь = Ложь;
Для Каждого Потомок Из РодительСтроки.ПолучитьЭлементы() Цикл
ВсеИстина = ВсеИстина И (Потомок.Пометка = 1);
НеВсеЛожь = НеВсеЛожь Или Булево(Потомок.Пометка);
КонецЦикла;
Если ВсеИстина Тогда
РодительСтроки.Пометка = 1;
ИначеЕсли НеВсеЛожь Тогда
РодительСтроки.Пометка = 2;
Иначе
РодительСтроки.Пометка = 0;
КонецЕсли;
ПроставитьПометкиВверх(РодительСтроки);
КонецЕсли;
КонецПроцедуры
// Чтение реквизитов узла обмена.
//
// Параметры:
// Ссылка - ПланОбменаСсылка - ссылка на узел обмена.
// Данные - Строка - список имен реквизитов для чтения через запятую.
//
// Возвращаемое значение:
// Структура - считанные данные.
//
Функция ПолучитьПараметрыУзлаОбмена(Ссылка, Данные) Экспорт
Результат = Новый Структура(Данные);
Запрос = Новый Запрос;
Запрос.УстановитьПараметр("Ссылка", Ссылка);
Запрос.Текст =
"ВЫБРАТЬ
| &ИменаРеквизитов
|ИЗ
| &ИмяТаблицыМетаданных КАК ИмяТаблицыМетаданных
|ГДЕ
| ИмяТаблицыМетаданных.Ссылка = &Ссылка";
Запрос.Текст = СтрЗаменить(Запрос.Текст, "&ИменаРеквизитов", Данные);
ИмяПланаОбмена = Ссылка.Метаданные().Имя;
Запрос.Текст = СтрЗаменить(Запрос.Текст, "&ИмяТаблицыМетаданных", ПодставитьПараметрыВСтроку("ПланОбмена.%1", ИмяПланаОбмена));
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
ЗаполнитьЗначенияСвойств(Результат, Выборка);
КонецЕсли;
Возврат Результат;
КонецФункции
// Запись реквизитов узла обмена.
//
// Параметры:
// Ссылка - ПланОбменаСсылка - ссылка на узел обмена.
// Данные - Структура - содержит значения реквизитов узла.
//
Процедура УстановитьПараметрыУзлаОбмена(Ссылка, Данные) Экспорт
ОбъектУзла = Ссылка.ПолучитьОбъект();
Если ОбъектУзла = Неопределено Тогда
// Ссылка на удаленный объект.
Возврат;
КонецЕсли;
МетаданныеУзла = ОбъектУзла.Метаданные();
НачатьТранзакцию();
Попытка
Блокировка = Новый БлокировкаДанных;
ЭлементБлокировки = Блокировка.Добавить(МетаданныеУзла.ПолноеИмя());
ЭлементБлокировки.УстановитьЗначение("Ссылка", Ссылка);
Блокировка.Заблокировать();
ЗаблокироватьДанныеДляРедактирования(Ссылка);
ОбъектУзла = Ссылка.ПолучитьОбъект();
Изменен = Ложь;
Для Каждого Элемент Из Данные Цикл
Если ОбъектУзла[Элемент.Ключ] = Элемент.Значение Тогда
Продолжить;
КонецЕсли;
ОбъектУзла[Элемент.Ключ] = Элемент.Значение;
Изменен = Истина;
КонецЦикла;
Если Изменен Тогда
ОбъектУзла.ОбменДанными.Загрузка = Истина;
ОбъектУзла.Записать();
КонецЕсли;
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
ВызватьИсключение;
КонецПопытки;
КонецПроцедуры
// Возвращает описание данных по имени таблицы/полному имени метаданных или метаданным.
//
// Параметры:
// ИмяТаблицыМетаданных - Строка - имя таблицы, например "Справочник.Валюты".
//
// Возвращаемое значение:
// Структура - описание данных в виде набора значений. Содержит следующие данные:
// * ЭтоПоследовательность - Булево - признак последовательности.
// * ЭтоКоллекция - Булево - признак коллекции значений.
// * ЭтоКонстанта - Булево - признак константы.
// * ЭтоСсылка - Булево - признак ссылочного типа данных.
// * ЭтоНабор - Булево - признак набора записей регистра
// * Менеджер - СправочникМенеджер, ДокументМенеджер, и т.п. - менеджер значения таблицы.
// * ИмяТаблицы - Строка - имя таблицы.
//
Функция ХарактеристикиПоМетаданным(ИмяТаблицыМетаданных) Экспорт
ЭтоПоследовательность = Ложь;
ЭтоКоллекция = Ложь;
ЭтоКонстанта = Ложь;
ЭтоСсылка = Ложь;
ЭтоНабор = Ложь;
Менеджер = Неопределено;
ИмяТаблицы = "";
Если ТипЗнч(ИмяТаблицыМетаданных) = Тип("Строка") Тогда
Мета = МетаданныеПоПолномуИмени(ИмяТаблицыМетаданных);
ИмяТаблицы = ИмяТаблицыМетаданных;
ИначеЕсли ТипЗнч(ИмяТаблицыМетаданных) = Тип("Тип") Тогда
Мета = Метаданные.НайтиПоТипу(ИмяТаблицыМетаданных);
ИмяТаблицы = Мета.ПолноеИмя();
Иначе
Мета = ИмяТаблицыМетаданных;
ИмяТаблицы = Мета.ПолноеИмя();
КонецЕсли;
Если Мета = Метаданные.Константы Тогда
ЭтоКоллекция = Истина;
ЭтоКонстанта = Истина;
Менеджер = Константы;
ИначеЕсли Мета = Метаданные.Справочники Тогда
ЭтоКоллекция = Истина;
ЭтоСсылка = Истина;
Менеджер = Справочники;
ИначеЕсли Мета = Метаданные.Документы Тогда
ЭтоКоллекция = Истина;
ЭтоСсылка = Истина;
Менеджер = Документы;
ИначеЕсли Мета = Метаданные.Перечисления Тогда
ЭтоКоллекция = Истина;
ЭтоСсылка = Истина;
Менеджер = Перечисления;
ИначеЕсли Мета = Метаданные.ПланыВидовХарактеристик Тогда
ЭтоКоллекция = Истина;
ЭтоСсылка = Истина;
Менеджер = ПланыВидовХарактеристик;
ИначеЕсли Мета = Метаданные.ПланыСчетов Тогда
ЭтоКоллекция = Истина;
ЭтоСсылка = Истина;
Менеджер = ПланыСчетов;
ИначеЕсли Мета = Метаданные.ПланыВидовРасчета Тогда
ЭтоКоллекция = Истина;
ЭтоСсылка = Истина;
Менеджер = ПланыВидовРасчета;
ИначеЕсли Мета = Метаданные.БизнесПроцессы Тогда
ЭтоКоллекция = Истина;
ЭтоСсылка = Истина;
Менеджер = БизнесПроцессы;
ИначеЕсли Мета = Метаданные.Задачи Тогда
ЭтоКоллекция = Истина;
ЭтоСсылка = Истина;
Менеджер = Задачи;
ИначеЕсли Мета = Метаданные.Последовательности Тогда
ЭтоНабор = Истина;
ЭтоПоследовательность = Истина;
ЭтоКоллекция = Истина;
Менеджер = Последовательности;
ИначеЕсли Мета = Метаданные.РегистрыСведений Тогда
ЭтоКоллекция = Истина;
ЭтоНабор = Истина;
Менеджер = РегистрыСведений;
ИначеЕсли Мета = Метаданные.РегистрыНакопления Тогда
ЭтоКоллекция = Истина;
ЭтоНабор = Истина;
Менеджер = РегистрыНакопления;
ИначеЕсли Мета = Метаданные.РегистрыБухгалтерии Тогда
ЭтоКоллекция = Истина;
ЭтоНабор = Истина;
Менеджер = РегистрыБухгалтерии;
ИначеЕсли Мета = Метаданные.РегистрыРасчета Тогда
ЭтоКоллекция = Истина;
ЭтоНабор = Истина;
Менеджер = РегистрыРасчета;
ИначеЕсли Метаданные.Константы.Содержит(Мета) Тогда
ЭтоКонстанта = Истина;
Менеджер = Константы[Мета.Имя];
ИначеЕсли Метаданные.Справочники.Содержит(Мета) Тогда
ЭтоСсылка = Истина;
Менеджер = Справочники[Мета.Имя];
ИначеЕсли Метаданные.Документы.Содержит(Мета) Тогда
ЭтоСсылка = Истина;
Менеджер = Документы[Мета.Имя];
ИначеЕсли Метаданные.Последовательности.Содержит(Мета) Тогда
ЭтоНабор = Истина;
ЭтоПоследовательность = Истина;
Менеджер = Последовательности[Мета.Имя];
ИначеЕсли Метаданные.Перечисления.Содержит(Мета) Тогда
ЭтоСсылка = Истина;
Менеджер = Перечисления[Мета.Имя];
ИначеЕсли Метаданные.ПланыВидовХарактеристик.Содержит(Мета) Тогда
ЭтоСсылка = Истина;
Менеджер = ПланыВидовХарактеристик[Мета.Имя];
ИначеЕсли Метаданные.ПланыСчетов.Содержит(Мета) Тогда
ЭтоСсылка = Истина;
Менеджер = ПланыСчетов[Мета.Имя];
ИначеЕсли Метаданные.ПланыВидовРасчета.Содержит(Мета) Тогда
ЭтоСсылка = Истина;
Менеджер = ПланыВидовРасчета[Мета.Имя];
ИначеЕсли Метаданные.РегистрыСведений.Содержит(Мета) Тогда
ЭтоНабор = Истина;
Менеджер = РегистрыСведений[Мета.Имя];
ИначеЕсли Метаданные.РегистрыНакопления.Содержит(Мета) Тогда
ЭтоНабор = Истина;
Менеджер = РегистрыНакопления[Мета.Имя];
ИначеЕсли Метаданные.РегистрыБухгалтерии.Содержит(Мета) Тогда
ЭтоНабор = Истина;
Менеджер = РегистрыБухгалтерии[Мета.Имя];
ИначеЕсли Метаданные.РегистрыРасчета.Содержит(Мета) Тогда
ЭтоНабор = Истина;
Менеджер = РегистрыРасчета[Мета.Имя];
ИначеЕсли Метаданные.БизнесПроцессы.Содержит(Мета) Тогда
ЭтоСсылка = Истина;
Менеджер = БизнесПроцессы[Мета.Имя];
ИначеЕсли Метаданные.Задачи.Содержит(Мета) Тогда
ЭтоСсылка = Истина;
Менеджер = Задачи[Мета.Имя];
Иначе
МетаРодитель = Мета.Родитель();
Если МетаРодитель <> Неопределено И Метаданные.РегистрыРасчета.Содержит(МетаРодитель) Тогда
// Перерасчет
ЭтоНабор = Истина;
Менеджер = РегистрыРасчета[МетаРодитель.Имя].Перерасчеты[Мета.Имя];
КонецЕсли;
КонецЕсли;
Результат = Новый Структура();
Результат.Вставить("ИмяТаблицы", ИмяТаблицы);
Результат.Вставить("Метаданные", Мета);
Результат.Вставить("Менеджер", Менеджер);
Результат.Вставить("ЭтоНабор", ЭтоНабор);
Результат.Вставить("ЭтоСсылка", ЭтоСсылка);
Результат.Вставить("ЭтоКонстанта", ЭтоКонстанта);
Результат.Вставить("ЭтоПоследовательность", ЭтоПоследовательность);
Результат.Вставить("ЭтоКоллекция", ЭтоКоллекция);
Возврат Результат;
КонецФункции
// Возвращает таблицу, описывающую измерения для регистрации изменений набора данных.
//
// Параметры:
// ИмяТаблицы - Строка - имя таблицы, например "РегистрСведений.КурсыВалют".
//
// Возвращаемое значение:
// ТаблицаЗначений:
// * Имя - Строка - имя измерения.
// * ТипЗначения - ОписаниеТипов - типы.
// * Заголовок - Строка - представление для измерения.
//
Функция ИзмеренияНабораЗаписей(ИмяТаблицы) Экспорт
Если ТипЗнч(ИмяТаблицы) = Тип("Строка") Тогда
Мета = МетаданныеПоПолномуИмени(ИмяТаблицы);
Иначе
Мета = ИмяТаблицы;
КонецЕсли;
// Определяем ключевые поля
Измерения = Новый ТаблицаЗначений;
Колонки = Измерения.Колонки;
Колонки.Добавить("Имя");
Колонки.Добавить("ТипЗначения");
Колонки.Добавить("Заголовок");
НеУчитывать = "#НомерСообщения#Узел#";
Для Каждого МетаОбщий Из Метаданные.ОбщиеРеквизиты Цикл
НеУчитывать = НеУчитывать + "#" + МетаОбщий.Имя + "#" ;
КонецЦикла;
ШаблонТекстаЗапроса =
"ВЫБРАТЬ
| *
|ИЗ
| &ИмяТаблицыМетаданных КАК ИмяТаблицыМетаданных
|ГДЕ
| ЛОЖЬ";
ИмяТаблицыМетаданных = Мета.ПолноеИмя() + ".Изменения";
ТекстЗапроса = СтрЗаменить(ШаблонТекстаЗапроса, "&ИмяТаблицыМетаданных", ИмяТаблицыМетаданных);
Запрос = Новый Запрос(ТекстЗапроса);
ПустойРезультат = Запрос.Выполнить();
Для Каждого КолонкаРезультата Из ПустойРезультат.Колонки Цикл
ИмяКолонки = КолонкаРезультата.Имя;
Если СтрНайти(НеУчитывать, "#" + ИмяКолонки + "#") = 0 Тогда
Строка = Измерения.Добавить();
Строка.Имя = ИмяКолонки;
Строка.ТипЗначения = КолонкаРезультата.ТипЗначения;
МетаИзмерение = Мета.Измерения.Найти(ИмяКолонки);
Строка.Заголовок = ?(МетаИзмерение = Неопределено, ИмяКолонки, МетаИзмерение.Представление());
КонецЕсли;
КонецЦикла;
Возврат Измерения;
КонецФункции
// Модифицирует таблицу формы, добавляя туда колонки.
//
// Параметры:
// ТаблицаФормы - ЭлементФормы - элемент, связанный с данными, в который будут добавлены колонки данных.
// СохранятьИмена - Строка - список имен колонок, которые будут сохранены, через запятую.
// Добавлять - Массив - структуры с описанием добавляемых колонок с атрибутами Имя, ТипЗначения, Заголовок.
// ГруппаКолонок - ЭлементФормы - группа колонок, в которую происходит добавление.
//
Процедура ДобавитьКолонкиВТаблицуФормы(ТаблицаФормы, СохранятьИмена, Добавлять, ГруппаКолонок = Неопределено) Экспорт
Форма = ФормаЭлементаФормы(ТаблицаФормы);
ЭлементыФормы = Форма.Элементы;
ИмяРеквизитаТаблицы = ТаблицаФормы.ПутьКДанным;
Сохраняемые = Новый Структура(СохранятьИмена);
СохраняемыеПутиДанных = Новый Соответствие;
Для Каждого Элемент Из Сохраняемые Цикл
СохраняемыеПутиДанных.Вставить(ИмяРеквизитаТаблицы + "." + Элемент.Ключ, Истина);
КонецЦикла;
ЭтоДинамическийСписок = Ложь;
Для Каждого Реквизит Из Форма.ПолучитьРеквизиты() Цикл
Если Реквизит.Имя = ИмяРеквизитаТаблицы И Реквизит.ТипЗначения.СодержитТип(Тип("ДинамическийСписок")) Тогда
ЭтоДинамическийСписок = Истина;
Прервать;
КонецЕсли;
КонецЦикла;
// Динамический пересоздает реквизиты сам.
Если Не ЭтоДинамическийСписок Тогда
УдаляемыеИмена = Новый Массив;
// Удаляем все реквизиты, которые не перечислены в СохранятьИмена.
Для Каждого Реквизит Из Форма.ПолучитьРеквизиты(ИмяРеквизитаТаблицы) Цикл
ТекИмя = Реквизит.Имя;
Если Не Сохраняемые.Свойство(ТекИмя) Тогда
УдаляемыеИмена.Добавить(Реквизит.Путь + "." + ТекИмя);
КонецЕсли;
КонецЦикла;
Добавляемые = Новый Массив;
Для Каждого Колонка Из Добавлять Цикл
ТекИмя = Колонка.Имя;
Если Не Сохраняемые.Свойство(ТекИмя) Тогда
Добавляемые.Добавить( Новый РеквизитФормы(ТекИмя, Колонка.ТипЗначения, ИмяРеквизитаТаблицы, Колонка.Заголовок) );
КонецЕсли;
КонецЦикла;
Форма.ИзменитьРеквизиты(Добавляемые, УдаляемыеИмена);
КонецЕсли;
// Удаляем элементы
Родитель = ?(ГруппаКолонок = Неопределено, ТаблицаФормы, ГруппаКолонок);
Удалять = Новый Массив;
Для Каждого Элемент Из Родитель.ПодчиненныеЭлементы Цикл
Удалять.Добавить(Элемент);
КонецЦикла;
Для Каждого Элемент Из Удалять Цикл
Если ТипЗнч(Элемент) <> Тип("ГруппаФормы") И СохраняемыеПутиДанных[Элемент.ПутьКДанным] = Неопределено Тогда
ЭлементыФормы.Удалить(Элемент);
КонецЕсли;
КонецЦикла;
// Создаем элементы
Префикс = ТаблицаФормы.Имя;
Для Каждого Колонка Из Добавлять Цикл
ТекИмя = Колонка.Имя;
ЭлементФормы = ЭлементыФормы.Вставить(Префикс + ТекИмя, Тип("ПолеФормы"), Родитель); // ПолеФормы
ЭлементФормы.Вид = ВидПоляФормы.ПолеВвода;
ЭлементФормы.ПутьКДанным = ИмяРеквизитаТаблицы + "." + ТекИмя;
ЭлементФормы.Заголовок = Колонка.Заголовок;
КонецЦикла;
КонецПроцедуры
// Возвращает подробное представление объекта.
//
// Параметры:
// - ОбъектПредставления - ЛюбаяСсылка - представление которого получаем.
//
// Возвращаемое значение:
// Строка - представление объекта.
//
Функция ПредставлениеСсылки(ОбъектПредставления) Экспорт
Если ТипЗнч(ОбъектПредставления) = Тип("Строка") Тогда
// Метаданные
Мета = Метаданные.НайтиПоПолномуИмени(ОбъектПредставления);
Результат = Мета.Представление();
Если Метаданные.Константы.Содержит(Мета) Тогда
Результат = Результат + " (константа)";
КонецЕсли;
Возврат Результат;
КонецЕсли;
// Ссылка
Результат = "";
МодульОбщегоНазначения = ОбщийМодуль("ОбщегоНазначения");
Если МодульОбщегоНазначения <> Неопределено Тогда
Результат = МодульОбщегоНазначения.ПредметСтрокой(ОбъектПредставления);
КонецЕсли;
Если ПустаяСтрока(Результат) И ОбъектПредставления <> Неопределено И Не ОбъектПредставления.Пустая() Тогда
Мета = ОбъектПредставления.Метаданные();
Если Метаданные.Документы.Содержит(Мета) Тогда
Результат = Строка(ОбъектПредставления);
Иначе
Представление = Мета.ПредставлениеОбъекта;
Если ПустаяСтрока(Представление) Тогда
Представление = Мета.Представление();
КонецЕсли;
Результат = Строка(ОбъектПредставления);
Если Не ПустаяСтрока(Представление) Тогда
Результат = Результат + " (" + Представление + ")";
КонецЕсли;
КонецЕсли;
КонецЕсли;
Если ПустаяСтрока(Результат) Тогда
Результат = НСтр("ru = 'не задано'");
КонецЕсли;
Возврат Результат;
КонецФункции
// Возвращает флаг того, что работа происходит в файловой базе.
// Возвращаемое значение:
// Булево - флаг того, что работа происходит в файловой базе.
//
Функция ЭтоФайловаяБаза() Экспорт
Возврат СтрНайти(СтрокаСоединенияИнформационнойБазы(), "File=") > 0;
КонецФункции
// Читает текущие данные из динамического списка по его настройкам и возвращает в виде таблицы значений.
//
// Параметры:
// ИсточникДанных - ДинамическийСписок - реквизит формы.
//
// Возвращаемое значение:
// ТаблицаЗначений - текущие данные динамического списка.
//
Функция ТекущиеДанныеДинамическогоСписка(ИсточникДанных) Экспорт
СхемаКомпоновки = Новый СхемаКомпоновкиДанных;
Источник = СхемаКомпоновки.ИсточникиДанных.Добавить();
Источник.Имя = "Источник";
Источник.ТипИсточникаДанных = "local";
Набор = СхемаКомпоновки.НаборыДанных.Добавить(Тип("НаборДанныхЗапросСхемыКомпоновкиДанных"));
Набор.Запрос = ИсточникДанных.ТекстЗапроса;
Набор.АвтоЗаполнениеДоступныхПолей = Истина;
Набор.ИсточникДанных = Источник.Имя;
Набор.Имя = Источник.Имя;
ИсточникНастроек = Новый ИсточникДоступныхНастроекКомпоновкиДанных(СхемаКомпоновки);
Компоновщик = Новый КомпоновщикНастроекКомпоновкиДанных;
Компоновщик.Инициализировать(ИсточникНастроек);
ТекНастройки = Компоновщик.Настройки;
// Выбранные поля
Для Каждого Элемент Из ТекНастройки.Выбор.ДоступныеПоляВыбора.Элементы Цикл
Если Не Элемент.Папка Тогда
Поле = ТекНастройки.Выбор.Элементы.Добавить(Тип("ВыбранноеПолеКомпоновкиДанных"));
Поле.Использование = Истина;
Поле.Поле = Элемент.Поле;
КонецЕсли;
КонецЦикла;
Группа = ТекНастройки.Структура.Добавить(Тип("ГруппировкаКомпоновкиДанных"));
Группа.Выбор.Элементы.Добавить(Тип("АвтоВыбранноеПолеКомпоновкиДанных"));
// Отбор
СкопироватьОтборКомпоновкиДанных(ТекНастройки.Отбор, ИсточникДанных.Отбор);
СкопироватьОтборКомпоновкиДанных(ТекНастройки.Отбор, ИсточникДанных.КомпоновщикНастроек.ПолучитьНастройки().Отбор);
// Выводим
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
Макет = КомпоновщикМакета.Выполнить(СхемаКомпоновки, ТекНастройки, , , Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений"));
Процессор = Новый ПроцессорКомпоновкиДанных;
Процессор.Инициализировать(Макет);
Вывод = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений;
Результат = Новый ТаблицаЗначений;
Вывод.УстановитьОбъект(Результат);
Вывод.Вывести(Процессор);
Возврат Результат;
КонецФункции
// Читаем настройки из общего хранилища.
// Параметры:
// КлючНастройки - Строка - ключ для чтения настроек.
//
Процедура ПрочитатьНастройки(КлючНастройки = "") Экспорт
КлючОбъекта = Метаданные().ПолноеИмя() + ".Форма.Форма";
ТекущиеНастройки = ХранилищеОбщихНастроек.Загрузить(КлючОбъекта);
Если ТипЗнч(ТекущиеНастройки) <> Тип("Соответствие") Тогда
// Умолчания
ТекущиеНастройки = Новый Соответствие;
ТекущиеНастройки.Вставить("НастройкаАвторегистрацияДвижений", Ложь);
ТекущиеНастройки.Вставить("НастройкаАвторегистрацияПоследовательностей", Ложь);
ТекущиеНастройки.Вставить("НастройкаАдресВнешнейОбработкиЗапросов", "");
ТекущиеНастройки.Вставить("НастройкаКонтрольВыгрузкиОбъектов", Истина); // Проверять через БСП
ТекущиеНастройки.Вставить("НастройкаВариантНомераСообщения", 0); // Регистрировать как новое
КонецЕсли;
НастройкаАвторегистрацияДвижений = ТекущиеНастройки["НастройкаАвторегистрацияДвижений"];
НастройкаАвторегистрацияПоследовательностей = ТекущиеНастройки["НастройкаАвторегистрацияПоследовательностей"];
НастройкаАдресВнешнейОбработкиЗапросов = ТекущиеНастройки["НастройкаАдресВнешнейОбработкиЗапросов"];
НастройкаКонтрольВыгрузкиОбъектов = ТекущиеНастройки["НастройкаКонтрольВыгрузкиОбъектов"];
НастройкаВариантНомераСообщения = ТекущиеНастройки["НастройкаВариантНомераСообщения"];
ПроверитьКорректностьНастроек(КлючНастройки);
КонецПроцедуры
// Устанавливаем флаги поддержки БСП.
//
Процедура ПрочитатьПризнакиПоддержкиБСП() Экспорт
КонфигурацияПоддерживаетБСП = БСП_ДоступнаТребуемаяВерсия();
Если КонфигурацияПоддерживаетБСП Тогда
// Используем внешний интерфейс регистрации.
ДоступнаРегистрацияСредствамиБСП = БСП_ДоступнаТребуемаяВерсия("2.1.5.11");
ДоступнаРаботаРИБ = БСП_ДоступнаТребуемаяВерсия("2.1.3.25");
ДоступнаРегистрацияАсинхронно = БСП_ДоступнаТребуемаяВерсия("2.3.5.34");
Иначе
ДоступнаРегистрацияСредствамиБСП = Ложь;
ДоступнаРаботаРИБ = Ложь;
ДоступнаРегистрацияАсинхронно = Ложь;
КонецЕсли;
КонецПроцедуры
Процедура ПрочитатьПризнакиПоддержкиБСД() Экспорт
ДоступнаПакетнаяРегистрация = БСД_ДоступнаТребуемаяВерсия("1.0.3.1");
КонецПроцедуры
// Пишем настройки в общее хранилище.
//
// Параметры:
// КлючНастройки - Строка - ключ для сохранения настроек.
//
Процедура СохранитьНастройки(КлючНастройки = "") Экспорт
КлючОбъекта = Метаданные().ПолноеИмя() + ".Форма.Форма";
ТекущиеНастройки = Новый Соответствие;
ТекущиеНастройки.Вставить("НастройкаАвторегистрацияДвижений", НастройкаАвторегистрацияДвижений);
ТекущиеНастройки.Вставить("НастройкаАвторегистрацияПоследовательностей", НастройкаАвторегистрацияПоследовательностей);
ТекущиеНастройки.Вставить("НастройкаАдресВнешнейОбработкиЗапросов", НастройкаАдресВнешнейОбработкиЗапросов);
ТекущиеНастройки.Вставить("НастройкаКонтрольВыгрузкиОбъектов", НастройкаКонтрольВыгрузкиОбъектов);
ТекущиеНастройки.Вставить("НастройкаВариантНомераСообщения", НастройкаВариантНомераСообщения);
ХранилищеОбщихНастроек.Сохранить(КлючОбъекта, "", ТекущиеНастройки)
КонецПроцедуры
// Проверяем настройки на корректность, сбрасываем в случае нарушения.
//
// Параметры:
// КлючНастройки - Строка - ключ проверяемой настройки.
// Возвращаемое значение:
// Структура - ключ - имя настройки.
// Значение - описание ошибки или Неопределено.
//
Функция ПроверитьКорректностьНастроек(КлючНастройки = "") Экспорт
Результат = Новый Структура("ЕстьОшибки,
|НастройкаАвторегистрацияДвижений, НастройкаАвторегистрацияПоследовательностей,
|НастройкаАдресВнешнейОбработкиЗапросов, НастройкаКонтрольВыгрузкиОбъектов,
|НастройкаВариантНомераСообщения",
Ложь);
// Доступность внешней обработки.
Если ПустаяСтрока(НастройкаАдресВнешнейОбработкиЗапросов) Тогда
// Убираем возможные пробелы, вариант отключен.
НастройкаАдресВнешнейОбработкиЗапросов = "";
ИначеЕсли НРег(Прав(СокрЛП(НастройкаАдресВнешнейОбработкиЗапросов), 4)) = ".epf" Тогда
// Убираем возможные пробелы, вариант отключен.
НастройкаАдресВнешнейОбработкиЗапросов = "";
Иначе
// В составе конфигурации
Если Метаданные.Обработки.Найти(НастройкаАдресВнешнейОбработкиЗапросов) = Неопределено Тогда
Текст = НСтр("ru = 'Обработка ""%1"" не найдена в составе конфигурации'");
Результат.НастройкаАдресВнешнейОбработкиЗапросов = СтрЗаменить(Текст, "%1", НастройкаАдресВнешнейОбработкиЗапросов);
Результат.ЕстьОшибки = Истина;
КонецЕсли;
КонецЕсли;
Возврат Результат;
КонецФункции
// Изменяет регистрацию переданного.
//
// Параметры:
// Команда - Булево - Истина, если надо добавлять, Ложь, если удалять.
// БезУчетаАвторегистрации - Булево - Истина, если не надо анализировать флаг авторегистрации.
// Узел - ПланОбменаСсылка - ссылка на узел плана обмена.
// Данные - ЛюбаяСсылка
// - Строка
// - Структура - данные или массив таких данных.
// ИмяТаблицы - Строка - если Данные является структурой, то содержит имя таблицы.
// ИменаМетаданных - Структура, Массив
//
// Возвращаемое значение:
// Структура:
// * Всего - Число - общее число объектов.
// * Успешно - Число - числом успешно обработанных объектов.
// * Команда - значение входящего параметра Команда для упрощения обработки результатов.
//
Функция ИзменитьРегистрациюНаСервере(Команда, БезУчетаАвторегистрации, Узел, Данные, ИмяТаблицы = Неопределено, ИменаМетаданных = Неопределено) Экспорт
ПрочитатьНастройки();
Результат = Новый Структура("Всего, Успешно", 0, 0);
// Только при добавлении и работе в составе БСП.
НадоФильтрБСП = ТипЗнч(Команда) = Тип("Булево") И Команда И КонфигурацияПоддерживаетБСП И НастройкаКонтрольВыгрузкиОбъектов;
Если ТипЗнч(Данные) = Тип("Массив") Тогда
ДанныеРегистрации = Новый Массив;
ЭтоРегистрацияПоОтбору = Ложь;
Если Команда
И ЗначениеЗаполнено(ИмяТаблицы)
И ДоступнаПакетнаяРегистрация Тогда
Описание = ХарактеристикиПоМетаданным(ИмяТаблицы);
ЭтоРегистрацияПоОтбору = Описание.ЭтоСсылка;
КонецЕсли;
Если ЭтоРегистрацияПоОтбору Тогда
МодульОбменДаннымиСобытия = ОбщийМодуль("ОбменДаннымиСобытия");
ПараметрыПР = МодульОбменДаннымиСобытия.ПараметрыПакетнойРегистрации();
МассивСсылок = Новый Массив;
Для Каждого ЭлементМассива Из Данные Цикл
МассивСсылок.Добавить(ЭлементМассива.Ссылка);
КонецЦикла;
МодульОбменДаннымиСобытия.ВыполнитьПакетнуюРегистрациюДляУзла(Узел, МассивСсылок, ПараметрыПР);
Для Каждого Ссылка Из ПараметрыПР.СсылкиПоФильтруПакетнойРегистрации Цикл
Результат.Всего = Результат.Всего + 1;
Результат.Успешно = Результат.Успешно + 1;
ПланыОбмена.ЗарегистрироватьИзменения(Узел, Ссылка);
КонецЦикла;
Если ПараметрыПР.ЕстьПРО_БезПакетнойРегистрации Тогда
Для Каждого Ссылка Из ПараметрыПР.СсылкиНеПоФильтруПакетнойРегистрации Цикл
СтруктураДанных = Новый Структура("Ссылка", Ссылка);
ДанныеРегистрации.Добавить(СтруктураДанных);
КонецЦикла;
КонецЕсли;
Иначе
ДанныеРегистрации = Данные;
КонецЕсли;
Иначе
ДанныеРегистрации = Новый Массив;
ДанныеРегистрации.Добавить(Данные);
КонецЕсли;
Для Каждого Элемент Из ДанныеРегистрации Цикл
Тип = ТипЗнч(Элемент);
Значения = Новый Массив;
Если Элемент = Неопределено Тогда
// Вся конфигурация
Если ТипЗнч(Команда) = Тип("Булево") И Команда Тогда
Если ИменаМетаданных = Неопределено Тогда
ИменаМетаданных = СформироватьСтруктуруМетаданных(Узел).СтруктураИмен;
КонецЕсли;
// Добавляем регистрацию по частям.
Для Каждого МД Из ИменаМетаданных Цикл
ДобавитьРезультаты(Результат, ИзменитьРегистрациюНаСервере(Команда, БезУчетаАвторегистрации, Узел, МД.Ключ, ИмяТаблицы, МД.Значение));
КонецЦикла;
Продолжить;
КонецЕсли;
// Удаление регистрации.
Если ИменаМетаданных = Неопределено Тогда
ИменаМетаданных = СформироватьСтруктуруМетаданных(Узел).СтруктураИмен;
КонецЕсли;
Для Каждого МД Из ИменаМетаданных Цикл
ИзменитьРегистрациюНаСервере(Команда, БезУчетаАвторегистрации, Узел, МД.Значение, ИмяТаблицы, ИменаМетаданных);
КонецЦикла;
ИначеЕсли Тип = Тип("Строка") Тогда
// Метаданные, возможно как коллекция, так и конкретный вид, на авторегистрацию смотрим.
Описание = ХарактеристикиПоМетаданным(Элемент);
Если НадоФильтрБСП Тогда
Если ТипЗнч(ИменаМетаданных) = Тип("Массив") Тогда
ИменаМетаданныхРегистрация = ИменаМетаданных;
ИначеЕсли ТипЗнч(ИменаМетаданных) = Тип("Структура") И Описание.ЭтоКоллекция Тогда
ИменаМетаданныхРегистрация = ИменаМетаданных[Описание.ИмяТаблицы];
Иначе
ИменаМетаданныхРегистрация = Неопределено;
КонецЕсли;
ДобавитьРезультаты(Результат, БСП_РегистрацияИзмененийМетаданных(Узел, Описание, БезУчетаАвторегистрации, ИменаМетаданныхРегистрация));
Продолжить;
ИначеЕсли БезУчетаАвторегистрации Тогда
Если Описание.ЭтоКоллекция Тогда
Для Каждого Мета Из Описание.Метаданные Цикл
ДобавитьРезультаты(Результат, ИзменитьРегистрациюНаСервере(Команда, БезУчетаАвторегистрации, Узел, Мета.ПолноеИмя(), ИмяТаблицы) );
КонецЦикла;
Продолжить;
Иначе
Мета = Описание.Метаданные;
ЭлементСостава = Узел.Метаданные().Состав.Найти(Мета);
Если ЭлементСостава = Неопределено Тогда
Продолжить;
КонецЕсли;
// Константа?
Значения.Добавить(Описание.Метаданные);
КонецЕсли;
Иначе
// Отсеиваем неподходящие по авторегистрации.
Если Описание.ЭтоКоллекция Тогда
// Регистрируем поодиночке
Для Каждого Мета Из Описание.Метаданные Цикл
ДобавитьРезультаты(Результат, ИзменитьРегистрациюНаСервере(Команда, БезУчетаАвторегистрации, Узел, Мета.ПолноеИмя(), ИмяТаблицы) );
КонецЦикла;
Продолжить;
Иначе
Мета = Описание.Метаданные;
ЭлементСостава = Узел.Метаданные().Состав.Найти(Мета);
Если ЭлементСостава = Неопределено Или ЭлементСостава.Авторегистрация <> АвтоРегистрацияИзменений.Разрешить Тогда
Продолжить;
КонецЕсли;
// Константа?
Значения.Добавить(Описание.Метаданные);
КонецЕсли;
КонецЕсли;
// Смотрим опциональные варианты, Значения[0] - метаданные конкретного вида с именем "Элемент".
Для Каждого ТекЭлемент Из ПолучитьДополнительныеОбъектыРегистрации(Элемент, Узел, БезУчетаАвторегистрации) Цикл
Значения.Добавить(ТекЭлемент);
КонецЦикла;
ИначеЕсли Тип = Тип("Структура") Тогда
// Это или конкретный набор записей, или результат выбора ссылочного типа отбором.
Описание = ХарактеристикиПоМетаданным(ИмяТаблицы);
Если Описание.ЭтоСсылка Тогда
ЭлементСсылка = Неопределено;
Если Элемент.Свойство("Ссылка", ЭлементСсылка) Тогда
ДобавитьРезультаты(Результат, ИзменитьРегистрациюНаСервере(Команда, БезУчетаАвторегистрации, Узел, ЭлементСсылка));
КонецЕсли;
Продолжить;
КонецЕсли;
// Конкретный набор записей, на авторегистрацию уже не смотрим.
Если НадоФильтрБСП Тогда
ДобавитьРезультаты(Результат, БСП_РегистрацияИзмененийНабора(Узел, Элемент, Описание) );
Продолжить;
КонецЕсли;
Набор = Описание.Менеджер.СоздатьНаборЗаписей();
Для Каждого КлючЗначение Из Элемент Цикл
УстановитьЗначениеЭлементаОтбора(Набор.Отбор, КлючЗначение.Ключ, КлючЗначение.Значение);
КонецЦикла;
Для Каждого Отбор Из Набор.Отбор Цикл
Если НЕ Отбор.Использование Тогда
Отбор.Использование = Истина;
КонецЕсли;
КонецЦикла;
Значения.Добавить(Набор);
// Смотрим опциональные варианты.
Для Каждого ТекЭлемент Из ПолучитьДополнительныеОбъектыРегистрации(Элемент, Узел, БезУчетаАвторегистрации, ИмяТаблицы) Цикл
Значения.Добавить(ТекЭлемент);
КонецЦикла;
Иначе
// Конкретная ссылка, на авторегистрацию уже не смотрим.
Если НадоФильтрБСП Тогда
ДобавитьРезультаты(Результат, БСП_РегистрацияИзмененийСсылки(Узел, Элемент) );
Продолжить;
КонецЕсли;
Значения.Добавить(Элемент);
// Смотрим опциональные варианты.
Для Каждого ТекЭлемент Из ПолучитьДополнительныеОбъектыРегистрации(Элемент, Узел, БезУчетаАвторегистрации) Цикл
Значения.Добавить(ТекЭлемент);
КонецЦикла;
КонецЕсли;
// Собственно регистрация, уже без фильтра.
Для Каждого ТекЗначение Из Значения Цикл
ВыполнитьКомандуРегистрацииОбъекта(Команда, Узел, ТекЗначение);
Результат.Успешно = Результат.Успешно + 1;
Результат.Всего = Результат.Всего + 1;
КонецЦикла;
КонецЦикла; // Перебор объектов в массиве данных для регистрации.
Результат.Вставить("Команда", Команда);
Возврат Результат;
КонецФункции
// Копирует отбор компоновки данных добавлением к существующим.
//
Процедура СкопироватьОтборКомпоновкиДанных(ГруппаПриемник, ГруппаИсточник)
КоллекцияИсточник = ГруппаИсточник.Элементы;
КоллекцияПриемник = ГруппаПриемник.Элементы;
Для Каждого Элемент Из КоллекцияИсточник Цикл
ТипЭлемента = ТипЗнч(Элемент);
НовыйЭлемент = КоллекцияПриемник.Добавить(ТипЭлемента);
ЗаполнитьЗначенияСвойств(НовыйЭлемент, Элемент);
Если ТипЭлемента = Тип("ГруппаЭлементовОтбораКомпоновкиДанных") Тогда
СкопироватьОтборКомпоновкиДанных(НовыйЭлемент, Элемент)
КонецЕсли;
КонецЦикла;
КонецПроцедуры
// Выполняет непосредственное действие с конечным объектом.
//
Процедура ВыполнитьКомандуРегистрацииОбъекта(Знач Команда, Знач Узел, Знач ОбъектРегистрации)
Если ТипЗнч(Команда) = Тип("Булево") Тогда
Если Команда Тогда
// Регистрация
Если НастройкаВариантНомераСообщения = 1 Тогда
// Как отправленного
НомерОтправленного = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(Узел, "НомерОтправленного");
Команда = 1 + НомерОтправленного;
Иначе
// Как нового
ЗарегистрироватьИзменения(Узел, ОбъектРегистрации);
КонецЕсли;
Иначе
// Отмена регистрации
ПланыОбмена.УдалитьРегистрациюИзменений(Узел, ОбъектРегистрации);
КонецЕсли;
КонецЕсли;
Если ТипЗнч(Команда) = Тип("Число") Тогда
// Одиночная регистрация с указанным номером сообщения.
Если Команда = 0 Тогда
// Аналогично регистрации нового.
ЗарегистрироватьИзменения(Узел, ОбъектРегистрации)
Иначе
// Изменение номера регистрации, БСП не проверяем.
ПланыОбмена.ЗарегистрироватьИзменения(Узел, ОбъектРегистрации);
Выборка = ПланыОбмена.ВыбратьИзменения(Узел, Команда, ОбъектРегистрации);
Пока Выборка.Следующий() Цикл
// Выбираем изменения для установки номера сообщения обмена данными.
КонецЦикла;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Процедура ЗарегистрироватьИзменения(Знач Узел, Знач ОбъектРегистрации)
Если Не ДоступнаРегистрацияСредствамиБСП
Или Не ЭтоУзелПланаОбменаБСП(Узел) Тогда
ПланыОбмена.ЗарегистрироватьИзменения(Узел, ОбъектРегистрации);
Возврат;
КонецЕсли;
// Заводим на регистрацию в БСП всегда, необходимы дополнительные действия.
МодульОбменДаннымиСобытия = ОбщийМодуль("ОбменДаннымиСобытия");
// На входе или объект метаданных или непосредственно объект.
Если ТипЗнч(ОбъектРегистрации) = Тип("ОбъектМетаданных") Тогда
Характеристики = ХарактеристикиПоМетаданным(ОбъектРегистрации);
Если Характеристики.ЭтоСсылка Тогда
Выборка = Характеристики.Менеджер.Выбрать();
Пока Выборка.Следующий() Цикл
МодульОбменДаннымиСобытия.ЗарегистрироватьИзмененияДанных(Узел, Выборка.Ссылка, НастройкаКонтрольВыгрузкиОбъектов);
КонецЦикла;
ИначеЕсли Характеристики.ЭтоНабор Тогда
Для Каждого ИзмерениеРегистра Из ОбъектРегистрации.Измерения Цикл
Если НедопустимоеИмяИзмеренияРегистра(ИзмерениеРегистра) Тогда
Возврат;
КонецЕсли;
КонецЦикла;
ПоляИзмерений = "";
Для Каждого Строка Из ИзмеренияНабораЗаписей(Характеристики.ИмяТаблицы) Цикл
ПоляИзмерений = ПоляИзмерений + "," + Строка.Имя
КонецЦикла;
ПоляИзмерений = Сред(ПоляИзмерений, 2);
Если ПустаяСтрока(ПоляИзмерений) Тогда
// У регистра сведений нет измерений с основным отбором.
// Регистрируются все изменения для объекта метаданных.
ПланыОбмена.ЗарегистрироватьИзменения(Узел, ОбъектРегистрации);
Иначе
ШаблонТекстаЗапроса =
"ВЫБРАТЬ РАЗЛИЧНЫЕ
| &ИменаПолей
|ИЗ
| &ИмяТаблицыМетаданных КАК ИмяТаблицыМетаданных";
ТекстЗапроса = СтрЗаменить(ШаблонТекстаЗапроса, "&ИменаПолей", ПоляИзмерений);
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&ИмяТаблицыМетаданных", Характеристики.ИмяТаблицы);
Запрос = Новый Запрос(ТекстЗапроса);
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
Данные = Новый Структура(ПоляИзмерений);
ЗаполнитьЗначенияСвойств(Данные, Выборка);
БСП_РегистрацияИзмененийНабора(Узел, Данные, Характеристики);
КонецЦикла;
КонецЕсли;
ИначеЕсли Характеристики.ЭтоКонстанта Тогда
Выборка = Характеристики.Менеджер.СоздатьМенеджерЗначения();
МодульОбменДаннымиСобытия.ЗарегистрироватьИзмененияДанных(Узел, Выборка, НастройкаКонтрольВыгрузкиОбъектов);
КонецЕсли;
Возврат;
КонецЕсли;
// Обычный объект
МодульОбменДаннымиСобытия.ЗарегистрироватьИзмененияДанных(Узел, ОбъектРегистрации, НастройкаКонтрольВыгрузкиОбъектов);
КонецПроцедуры
// Параметры:
// Измерение - ОбъектМетаданных
//
// Возвращаемое значение:
// Булево - Истина, если имя измерения регистра является недопустимым
// с точки зрения механизмов регистрации.
//
Функция НедопустимоеИмяИзмеренияРегистра(Измерение)
Возврат ВРег(Измерение.Имя) = "УЗЕЛ"
Или ВРег(Измерение.Имя) = "NODE";
КонецФункции
// Возвращает управляемую форму, которой принадлежит элемент.
//
// Параметры:
// ЭлементФормы - ЭлементыФормы
// Возвращаемое значение:
// ЭлементыФормы
//
Функция ФормаЭлементаФормы(ЭлементФормы)
Результат = ЭлементФормы;
ТипыФормы = Новый ОписаниеТипов("ФормаКлиентскогоПриложения");
Пока Не ТипыФормы.СодержитТип(ТипЗнч(Результат)) Цикл
Результат = Результат.Родитель;
КонецЦикла;
Возврат Результат;
КонецФункции
// Внутренняя для формирования группы метаданных (например справочников) в дереве метаданных.
//
Процедура СформироватьУровеньМетаданных(ТекущийНомерСтроки, Параметры, ИндексКартинки, ИндексКартинкиУзлов, ДобавлятьПодчиненные, ИмяМета, ПредставлениеМета)
ПредставленияУровня = Новый Массив;
Авторегистрации = Новый Массив;
ИменаУровня = Новый Массив;
ВсеСтроки = Параметры.Строки;
МетаПлан = Параметры.ПланОбмена;
СоставПодписокМРО = Неопределено;
ПроверятьСоставПодписокМРО = Параметры.Свойство("СоставПодписокМРО", СоставПодписокМРО);
СтрокаГруппа = ВсеСтроки.Добавить();
СтрокаГруппа.ИдентификаторСтроки = ТекущийНомерСтроки;
СтрокаГруппа.МетаПолноеИмя = ИмяМета;
СтрокаГруппа.Наименование = ПредставлениеМета;
СтрокаГруппа.ИндексКартинки = ИндексКартинки;
Строки = СтрокаГруппа.Строки;
БылиПодчиненные = Ложь;
Для Каждого Мета Из Метаданные[ИмяМета] Цикл
Если МетаПлан = Неопределено Тогда
// Без учета плана обмена
Если Не ОбъектМетаданныхДоступенПоФункциональнымОпциям(Мета) Тогда
Продолжить;
КонецЕсли;
БылиПодчиненные = Истина;
МетаПолноеИмя = Мета.ПолноеИмя();
Наименование = Мета.Представление();
Если ДобавлятьПодчиненные Тогда
НовСтрока = Строки.Добавить();
НовСтрока.МетаПолноеИмя = МетаПолноеИмя;
НовСтрока.Наименование = Наименование ;
НовСтрока.ИндексКартинки = ИндексКартинкиУзлов;
ТекущийНомерСтроки = ТекущийНомерСтроки + 1;
НовСтрока.ИдентификаторСтроки = ТекущийНомерСтроки;
КонецЕсли;
ИменаУровня.Добавить(МетаПолноеИмя);
ПредставленияУровня.Добавить(Наименование);
Иначе
Элемент = МетаПлан.Состав.Найти(Мета);
Если Элемент <> Неопределено И ПравоДоступа("Чтение", Мета) Тогда
Если ИменаСкрываемыхМетаданных.НайтиПоЗначению(Мета.ПолноеИмя()) <> Неопределено Тогда
Продолжить;
КонецЕсли;
Если КонфигурацияПоддерживаетБСП
И ПроверятьСоставПодписокМРО
И СоставПодписокМРО.Найти(Мета) = Неопределено Тогда
Продолжить;
КонецЕсли;
Если Не ОбъектМетаданныхДоступенПоФункциональнымОпциям(Мета) Тогда
Продолжить;
КонецЕсли;
БылиПодчиненные = Истина;
МетаПолноеИмя = Мета.ПолноеИмя();
Наименование = Мета.Представление();
Авторегистрация = ?(Элемент.Авторегистрация = АвтоРегистрацияИзменений.Запретить, 1, 2);
Если ДобавлятьПодчиненные Тогда
НовСтрока = Строки.Добавить();
НовСтрока.МетаПолноеИмя = МетаПолноеИмя;
НовСтрока.Наименование = Наименование ;
НовСтрока.ИндексКартинки = ИндексКартинкиУзлов;
НовСтрока.Авторегистрация = Авторегистрация;
ТекущийНомерСтроки = ТекущийНомерСтроки + 1;
НовСтрока.ИдентификаторСтроки = ТекущийНомерСтроки;
КонецЕсли;
ИменаУровня.Добавить(МетаПолноеИмя);
ПредставленияУровня.Добавить(Наименование);
Авторегистрации.Добавить(Авторегистрация);
КонецЕсли;
КонецЕсли;
КонецЦикла;
Если БылиПодчиненные Тогда
Строки.Сортировать("Наименование");
Параметры.СтруктураИмен.Вставить(ИмяМета, ИменаУровня);
Параметры.СтруктураПредставлений.Вставить(ИмяМета, ПредставленияУровня);
Если Не ДобавлятьПодчиненные Тогда
Параметры.СтруктураАвторегистрации.Вставить(ИмяМета, Авторегистрации);
КонецЕсли;
Иначе
// Виды объектов без регистрации не вставляем.
ВсеСтроки.Удалить(СтрокаГруппа);
КонецЕсли;
КонецПроцедуры
// Определяет доступность объекта метаданных по функциональным опциям.
//
// Параметры:
// ОбъектМетаданных - ОбъектМетаданных - проверяемый объект метаданных.
//
// Возвращаемое значение:
// Булево - Истина, если объект доступен.
//
Функция ОбъектМетаданныхДоступенПоФункциональнымОпциям(ОбъектМетаданных)
Если Не ЗначениеЗаполнено(ДоступностьОбъектовПоОпциям) Тогда
ДоступностьОбъектовПоОпциям = ДоступностьОбъектовПоОпциям();
КонецЕсли;
Возврат ДоступностьОбъектовПоОпциям[ОбъектМетаданных] <> Ложь;
КонецФункции
// Доступность объектов метаданных по функциональным опциям.
Функция ДоступностьОбъектовПоОпциям()
Параметры = Новый Структура();
ДоступностьОбъектов = Новый Соответствие;
Для Каждого ФункциональнаяОпция Из Метаданные.ФункциональныеОпции Цикл
Значение = -1;
Для Каждого Элемент Из ФункциональнаяОпция.Состав Цикл
Если Значение = -1 Тогда
Значение = ПолучитьФункциональнуюОпцию(ФункциональнаяОпция.Имя, Параметры);
КонецЕсли;
Если Значение = Истина Тогда
ДоступностьОбъектов.Вставить(Элемент.Объект, Истина);
Иначе
Если ДоступностьОбъектов[Элемент.Объект] = Неопределено Тогда
ДоступностьОбъектов.Вставить(Элемент.Объект, Ложь);
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецЦикла;
Возврат ДоступностьОбъектов;
КонецФункции
// Накапливаем результаты регистраций.
//
Процедура ДобавитьРезультаты(Приемник, Источник)
Приемник.Успешно = Приемник.Успешно + Источник.Успешно;
Приемник.Всего = Приемник.Всего + Источник.Всего;
КонецПроцедуры
// Возвращает массив дополнительно регистрируемых объектов согласно флагам.
//
Функция ПолучитьДополнительныеОбъектыРегистрации(ОбъектРегистрации, УзелКонтроляАвторегистрации, БезАвторегистрации, ИмяТаблицы = Неопределено)
Результат = Новый Массив;
// Смотрим на глобальные параметры.
Если (Не НастройкаАвторегистрацияДвижений) И (Не НастройкаАвторегистрацияПоследовательностей) Тогда
Возврат Результат;
КонецЕсли;
ТипЗначения = ТипЗнч(ОбъектРегистрации);
НаВходеИмя = ТипЗначения = Тип("Строка");
Если НаВходеИмя Тогда
Описание = ХарактеристикиПоМетаданным(ОбъектРегистрации);
ИначеЕсли ТипЗначения = Тип("Структура") Тогда
Описание = ХарактеристикиПоМетаданным(ИмяТаблицы);
Если Описание.ЭтоПоследовательность Тогда
Возврат Результат;
КонецЕсли;
Иначе
Описание = ХарактеристикиПоМетаданным(ОбъектРегистрации.Метаданные());
КонецЕсли;
МетаОбъект = Описание.Метаданные;
// Коллекцию рекурсивно
Если Описание.ЭтоКоллекция Тогда
Для Каждого Мета Из МетаОбъект Цикл
ДополнительныйНабор = ПолучитьДополнительныеОбъектыРегистрации(Мета.ПолноеИмя(), УзелКонтроляАвторегистрации, БезАвторегистрации, ИмяТаблицы);
Для Каждого Элемент Из ДополнительныйНабор Цикл
Результат.Добавить(Элемент);
КонецЦикла;
КонецЦикла;
Возврат Результат;
КонецЕсли;
// Одиночное
СоставУзла = УзелКонтроляАвторегистрации.Метаданные().Состав;
// Документы. Могут влиять на последовательности и движения.
Если Метаданные.Документы.Содержит(МетаОбъект) Тогда
Если НастройкаАвторегистрацияДвижений Тогда
Для Каждого Мета Из МетаОбъект.Движения Цикл
ЭлементСостава = СоставУзла.Найти(Мета);
Если ЭлементСостава <> Неопределено И (БезАвторегистрации Или ЭлементСостава.Авторегистрация = АвтоРегистрацияИзменений.Разрешить) Тогда
Если НаВходеИмя Тогда
Результат.Добавить(Мета);
Иначе
Описание = ХарактеристикиПоМетаданным(Мета);
Набор = Описание.Менеджер.СоздатьНаборЗаписей();
УстановитьЗначениеЭлементаОтбора(Набор.Отбор, "Регистратор", ОбъектРегистрации);
Набор.Прочитать();
Результат.Добавить(Набор);
// И проверим полученный набор рекурсивно.
ДополнительныйНабор = ПолучитьДополнительныеОбъектыРегистрации(Набор, УзелКонтроляАвторегистрации, БезАвторегистрации, ИмяТаблицы);
Для Каждого Элемент Из ДополнительныйНабор Цикл
Результат.Добавить(Элемент);
КонецЦикла;
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецЕсли;
Если НастройкаАвторегистрацияПоследовательностей Тогда
Для Каждого Мета Из Метаданные.Последовательности Цикл
Описание = ХарактеристикиПоМетаданным(Мета);
Если Мета.Документы.Содержит(МетаОбъект) Тогда
// Последовательность регистрируется для данного документа.
ЭлементСостава = СоставУзла.Найти(Мета);
Если ЭлементСостава <> Неопределено И (БезАвторегистрации Или ЭлементСостава.Авторегистрация = АвтоРегистрацияИзменений.Разрешить) Тогда
// Регистрируется на этом узле.
Если НаВходеИмя Тогда
Результат.Добавить(Мета);
Иначе
Набор = Описание.Менеджер.СоздатьНаборЗаписей();
УстановитьЗначениеЭлементаОтбора(Набор.Отбор, "Регистратор", ОбъектРегистрации);
Набор.Прочитать();
Результат.Добавить(Набор);
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецЕсли;
// Записи регистров. Могут влиять на последовательности.
ИначеЕсли НастройкаАвторегистрацияПоследовательностей И (
Метаданные.РегистрыСведений.Содержит(МетаОбъект)
Или Метаданные.РегистрыНакопления.Содержит(МетаОбъект)
Или Метаданные.РегистрыБухгалтерии.Содержит(МетаОбъект)
Или Метаданные.РегистрыРасчета.Содержит(МетаОбъект)) Тогда
Для Каждого Мета Из Метаданные.Последовательности Цикл
Если Мета.Движения.Содержит(МетаОбъект) Тогда
// Последовательность регистрируется для набора записей.
ЭлементСостава = СоставУзла.Найти(Мета);
Если ЭлементСостава <> Неопределено И (БезАвторегистрации Или ЭлементСостава.Авторегистрация = АвтоРегистрацияИзменений.Разрешить) Тогда
Результат.Добавить(Мета);
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецЕсли;
Возврат Результат;
КонецФункции
// Преобразует строку в число
//
// Параметры:
// Текст - Строка - строковое представление числа.
//
// Возвращаемое значение:
// Число - преобразованная строка.
// Неопределено - если строка не может быть преобразована.
//
Функция СтрокаВЧисло(Знач Текст)
ТекстЧисла = СокрЛП(СтрЗаменить(Текст, Символы.НПП, ""));
Если ПустаяСтрока(ТекстЧисла)
Или ТекстЧисла = "0" Тогда
Возврат 0;
КонецЕсли;
// Ведущие нули
Позиция = 1;
Пока Сред(ТекстЧисла, Позиция, 1) = "0" Цикл
Позиция = Позиция + 1;
КонецЦикла;
ТекстЧисла = Сред(ТекстЧисла, Позиция);
// Проверяем на результат по умолчанию.
Если ТекстЧисла = "0" Тогда
Результат = 0;
Иначе
ТипЧисло = Новый ОписаниеТипов("Число");
Результат = ТипЧисло.ПривестиЗначение(ТекстЧисла);
Если Результат = 0 Тогда
// Результат по умолчанию обработан выше, это ошибка преобразования.
Результат = Неопределено;
КонецЕсли;
КонецЕсли;
Возврат Результат;
КонецФункции
// Возвращает ссылку на общий модуль по имени.
//
// Параметры:
// Имя - Строка - имя общего модуля, например:
// "ОбщегоНазначения",
// "ОбщегоНазначенияКлиент".
//
// Возвращаемое значение:
// ОбщийМодуль
//
Функция ОбщийМодуль(Имя)
Если Метаданные.ОбщиеМодули.Найти(Имя) <> Неопределено Тогда
УстановитьБезопасныйРежим(Истина);
Модуль = Вычислить(Имя); // АПК:488 "Вычислить" вместо "ОбщегоНазначения.ВычислитьВБезопасномРежиме()", так как обработка автономная
Иначе
Модуль = Неопределено;
КонецЕсли;
Если ТипЗнч(Модуль) <> Тип("ОбщийМодуль") Тогда
ВызватьИсключение ПодставитьПараметрыВСтроку(НСтр("ru = 'Общий модуль ""%1"" не существует.'"), Имя);
КонецЕсли;
Возврат Модуль;
КонецФункции
Функция ЭтоУзелПланаОбменаБСП(Узел)
МодульОбменДаннымиПовтИсп = ОбщийМодуль("ОбменДаннымиПовтИсп");
Если МодульОбменДаннымиПовтИсп = Неопределено Тогда
Возврат Ложь;
КонецЕсли;
Возврат МодульОбменДаннымиПовтИсп.ПланыОбменаБСП().Найти(МодульОбменДаннымиПовтИсп.ПолучитьИмяПланаОбмена(Узел)) <> Неопределено;
КонецФункции
// Возвращает флаг того, что БСП в текущей конфигурации обеспечивает функционал.
//
Функция БСП_ДоступнаТребуемаяВерсия(Знач Версия = Неопределено)
ТекущаяВерсия = Неопределено;
МодульСтандартныеПодсистемыСервер = ОбщийМодуль("СтандартныеПодсистемыСервер");
Если МодульСтандартныеПодсистемыСервер <> Неопределено Тогда
Попытка
ТекущаяВерсия = МодульСтандартныеПодсистемыСервер.ВерсияБиблиотеки();
Исключение
ТекущаяВерсия = Неопределено;
КонецПопытки;
КонецЕсли;
Если ТекущаяВерсия = Неопределено Тогда
// Отсутствует или поломан метод определения версии, считаем БСП недоступной.
Возврат Ложь
КонецЕсли;
ТекущаяВерсия = СтрЗаменить(ТекущаяВерсия, ".", Символы.ПС);
НужнаяВерсия = СтрЗаменить(?(Версия = Неопределено, "2.2.2", Версия), ".", Символы.ПС);
Для Индекс = 1 По СтрЧислоСтрок(НужнаяВерсия) Цикл
ЧастьТекущейВерсии = СтрокаВЧисло(СтрПолучитьСтроку(ТекущаяВерсия, Индекс));
ЧастьНужнойВерсии = СтрокаВЧисло(СтрПолучитьСтроку(НужнаяВерсия, Индекс));
Если ЧастьТекущейВерсии = Неопределено Тогда
Возврат Ложь;
ИначеЕсли ЧастьТекущейВерсии > ЧастьНужнойВерсии Тогда
Возврат Истина;
ИначеЕсли ЧастьТекущейВерсии < ЧастьНужнойВерсии Тогда
Возврат Ложь;
КонецЕсли;
КонецЦикла;
Возврат Истина;
КонецФункции
// Возвращает флаг того, что БСД в текущей конфигурации обеспечивает функционал.
//
Функция БСД_ДоступнаТребуемаяВерсия(Знач Версия = Неопределено)
ТекущаяВерсия = Неопределено;
МодульСтандартныеПодсистемыПовтИсп = ОбщийМодуль("СтандартныеПодсистемыПовтИсп");
Если МодульСтандартныеПодсистемыПовтИсп <> Неопределено Тогда
Попытка
ТекущаяВерсия = СтандартныеПодсистемыПовтИсп.ОписанияПодсистем().ПоИменам["БиблиотекаСинхронизацииДанных"].Версия
Исключение
ТекущаяВерсия = Неопределено;
КонецПопытки;
КонецЕсли;
Если ТекущаяВерсия = Неопределено Тогда
// Отсутствует или поломан метод определения версии, считаем БСД недоступной.
Возврат Ложь
КонецЕсли;
ТекущаяВерсия = СтрЗаменить(ТекущаяВерсия, ".", Символы.ПС);
НужнаяВерсия = СтрЗаменить(?(Версия = Неопределено, "2.2.2", Версия), ".", Символы.ПС);
Для Индекс = 1 По СтрЧислоСтрок(НужнаяВерсия) Цикл
ЧастьТекущейВерсии = СтрокаВЧисло(СтрПолучитьСтроку(ТекущаяВерсия, Индекс));
ЧастьНужнойВерсии = СтрокаВЧисло(СтрПолучитьСтроку(НужнаяВерсия, Индекс));
Если ЧастьТекущейВерсии = Неопределено Тогда
Возврат Ложь;
ИначеЕсли ЧастьТекущейВерсии > ЧастьНужнойВерсии Тогда
Возврат Истина;
ИначеЕсли ЧастьТекущейВерсии < ЧастьНужнойВерсии Тогда
Возврат Ложь;
КонецЕсли;
КонецЦикла;
Возврат Истина;
КонецФункции
// Возвращает флаг контроля объекта в БСП.
//
Функция БСП_КонтрольВыгрузкиОбъекта(Узел, ОбъектРегистрации)
Отправка = ОтправкаЭлементаДанных.Авто;
МодульОбменДаннымиСобытия = ОбщийМодуль("ОбменДаннымиСобытия");
Если МодульОбменДаннымиСобытия <> Неопределено Тогда
МодульОбменДаннымиСобытия.ПриОтправкеДанныхКорреспонденту(ОбъектРегистрации, Отправка, , Узел);
Возврат Отправка = ОтправкаЭлементаДанных.Авто;
КонецЕсли;
// Неизвестная версия БСП
Возврат Истина;
КонецФункции
// Проверяет ссылку на возможность регистрации изменения в БСП.
// Возвращает структуру с полями "Всего" и "Успешно", описывающей количества регистраций.
//
Функция БСП_РегистрацияИзмененийСсылки(Узел, Ссылка, БезУчетаАвторегистрации = Истина)
Результат = Новый Структура("Всего, Успешно", 0, 0);
Если БезУчетаАвторегистрации Тогда
СоставУзла = Неопределено;
Иначе
СоставУзла = Узел.Метаданные().Состав;
КонецЕсли;
ЭлементСостава = ?(СоставУзла = Неопределено, Неопределено, СоставУзла.Найти(Ссылка.Метаданные()));
Если ЭлементСостава = Неопределено Или ЭлементСостава.Авторегистрация = АвтоРегистрацияИзменений.Разрешить Тогда
// Сам объект
Результат.Всего = 1;
ОбъектРегистрации = Ссылка.ПолучитьОбъект();
// Для битых ссылок ОбъектРегистрации будет Неопределено.
Если ОбъектРегистрации = Неопределено Или БСП_КонтрольВыгрузкиОбъекта(Узел, ОбъектРегистрации) Тогда
ВыполнитьКомандуРегистрацииОбъекта(Истина, Узел, Ссылка);
Результат.Успешно = 1;
КонецЕсли;
ОбъектРегистрации = Неопределено;
КонецЕсли;
// Смотрим опциональные варианты.
Если Результат.Успешно > 0 Тогда
Для Каждого Элемент Из ПолучитьДополнительныеОбъектыРегистрации(Ссылка, Узел, БезУчетаАвторегистрации) Цикл
Результат.Всего = Результат.Всего + 1;
Если БСП_КонтрольВыгрузкиОбъекта(Узел, Элемент) Тогда
ВыполнитьКомандуРегистрацииОбъекта(Истина, Узел, Элемент);
Результат.Успешно = Результат.Успешно + 1;
КонецЕсли;
КонецЦикла;
КонецЕсли;
Возврат Результат;
КонецФункции
// Проверяет набор значений на возможность регистрации изменения в БСП.
// Возвращает структуру с полями "Всего" и "Успешно", описывающей количества регистраций.
//
Функция БСП_РегистрацияИзмененийНабора(Узел, СтруктураПолей, Описание, БезУчетаАвторегистрации = Истина)
Результат = Новый Структура("Всего, Успешно", 0, 0);
Если БезУчетаАвторегистрации Тогда
СоставУзла = Неопределено;
Иначе
СоставУзла = Узел.Метаданные().Состав;
КонецЕсли;
ЭлементСостава = ?(СоставУзла = Неопределено, Неопределено, СоставУзла.Найти(Описание.Метаданные));
Если ЭлементСостава = Неопределено Или ЭлементСостава.Авторегистрация = АвтоРегистрацияИзменений.Разрешить Тогда
Результат.Всего = 1;
Набор = Описание.Менеджер.СоздатьНаборЗаписей();
Для Каждого КлючЗначение Из СтруктураПолей Цикл
УстановитьЗначениеЭлементаОтбора(Набор.Отбор, КлючЗначение.Ключ, КлючЗначение.Значение);
КонецЦикла;
Набор.Прочитать();
Если БСП_КонтрольВыгрузкиОбъекта(Узел, Набор) Тогда
ВыполнитьКомандуРегистрацииОбъекта(Истина, Узел, Набор);
Результат.Успешно = 1;
КонецЕсли;
КонецЕсли;
// Смотрим опциональные варианты.
Если Результат.Успешно > 0 Тогда
Для Каждого Элемент Из ПолучитьДополнительныеОбъектыРегистрации(Набор, Узел, БезУчетаАвторегистрации) Цикл
Результат.Всего = Результат.Всего + 1;
Если БСП_КонтрольВыгрузкиОбъекта(Узел, Элемент) Тогда
ВыполнитьКомандуРегистрацииОбъекта(Истина, Узел, Элемент);
Результат.Успешно = Результат.Успешно + 1;
КонецЕсли;
КонецЦикла;
КонецЕсли;
Возврат Результат;
КонецФункции
// Проверяет константу на возможность регистрации изменения в БСП.
// Возвращает структуру с полями "Всего" и "Успешно", описывающей количества регистраций.
//
Функция БСП_РегистрацияИзмененийКонстанты(Узел, Описание, БезУчетаАвторегистрации = Истина)
Результат = Новый Структура("Всего, Успешно", 0, 0);
Если БезУчетаАвторегистрации Тогда
СоставУзла = Неопределено;
Иначе
СоставУзла = Узел.Метаданные().Состав;
КонецЕсли;
ЭлементСостава = ?(СоставУзла = Неопределено, Неопределено, СоставУзла.Найти(Описание.Метаданные));
Если ЭлементСостава = Неопределено Или ЭлементСостава.Авторегистрация = АвтоРегистрацияИзменений.Разрешить Тогда
Результат.Всего = 1;
ОбъектРегистрации = Описание.Менеджер.СоздатьМенеджерЗначения();
Если БСП_КонтрольВыгрузкиОбъекта(Узел, ОбъектРегистрации) Тогда
ВыполнитьКомандуРегистрацииОбъекта(Истина, Узел, ОбъектРегистрации);
Результат.Успешно = 1;
КонецЕсли;
КонецЕсли;
Возврат Результат;
КонецФункции
// Проверяет набор метаданных на возможность регистрации изменения в БСП.
// Возвращает структуру с полями "Всего" и "Успешно", описывающей количества регистраций.
//
Функция БСП_РегистрацияИзмененийМетаданных(Узел, Описание, БезУчетаАвторегистрации, ИменаМетаданных = Неопределено)
Результат = Новый Структура("Всего, Успешно", 0, 0);
Если ИменаМетаданных <> Неопределено
И Не Описание.ЭтоКоллекция
И ИменаМетаданных.Найти(Описание.ИмяТаблицы) = Неопределено Тогда
Возврат Результат;
КонецЕсли;
Если Описание.ЭтоКоллекция Тогда
Для Каждого МетаВид Из Описание.Метаданные Цикл
ТекОписание = ХарактеристикиПоМетаданным(МетаВид);
ДобавитьРезультаты(Результат, БСП_РегистрацияИзмененийМетаданных(Узел, ТекОписание, БезУчетаАвторегистрации, ИменаМетаданных));
КонецЦикла;
Иначе;
ДобавитьРезультаты(Результат, БСП_РегистрацияИзмененийОбъектаМетаданных(Узел, Описание, БезУчетаАвторегистрации) );
КонецЕсли;
Возврат Результат;
КонецФункции
// Проверяет объект метаданных на возможность регистрации изменения в БСП.
// Возвращает структуру с полями "Всего" и "Успешно", описывающей количества регистраций.
//
Функция БСП_РегистрацияИзмененийОбъектаМетаданных(Узел, Описание, БезУчетаАвторегистрации)
Результат = Новый Структура("Всего, Успешно", 0, 0);
ЭлементСостава = Узел.Метаданные().Состав.Найти(Описание.Метаданные);
Если ЭлементСостава = Неопределено Тогда
// Вообще не регистрируется
Возврат Результат;
КонецЕсли;
Если (Не БезУчетаАвторегистрации) И ЭлементСостава.Авторегистрация <> АвтоРегистрацияИзменений.Разрешить Тогда
// Отсечение по авторегистрации.
Возврат Результат;
КонецЕсли;
ТекИмяТаблицы = Описание.ИмяТаблицы;
Если Описание.ЭтоКонстанта Тогда
ДобавитьРезультаты(Результат, БСП_РегистрацияИзмененийКонстанты(Узел, Описание) );
Возврат Результат;
ИначеЕсли Описание.ЭтоСсылка Тогда
ПоляИзмерений = "Ссылка";
ИначеЕсли Описание.ЭтоНабор Тогда
ПоляИзмерений = "";
Для Каждого Строка Из ИзмеренияНабораЗаписей(ТекИмяТаблицы) Цикл
ПоляИзмерений = ПоляИзмерений + "," + Строка.Имя
КонецЦикла;
ПоляИзмерений = Сред(ПоляИзмерений, 2);
Если ПустаяСтрока(ПоляИзмерений) Тогда
// У РС нет измерений с основным отбором.
// Регистрируются все изменения для объекта метаданных.
ПланыОбмена.ЗарегистрироватьИзменения(Узел, Описание.Метаданные);
// Для подсчета результата.
ШаблонТекстаЗапроса =
"ВЫБРАТЬ
| Количество(*) КАК Количество
|ИЗ
| &ИмяТаблицыМетаданных КАК ИмяТаблицыМетаданных";
ТекстЗапроса = СтрЗаменить(ШаблонТекстаЗапроса, "&ИмяТаблицыМетаданных", ТекИмяТаблицы);
Запрос = Новый Запрос(ТекстЗапроса);
Выборка = Запрос.Выполнить().Выбрать();
Выборка.Следующий();
Результат.Всего = Выборка.Количество;
Результат.Успешно = Выборка.Количество;
Возврат Результат;
КонецЕсли;
Иначе
Возврат Результат;
КонецЕсли;
ШаблонТекстаЗапроса =
"ВЫБРАТЬ РАЗЛИЧНЫЕ
| &ИменаПолейИлиРеквизитов
|ИЗ
| &ИмяТаблицыМетаданных КАК ИмяТаблицыМетаданных";
ТекстЗапроса = СтрЗаменить(ШаблонТекстаЗапроса, "&ИменаПолейИлиРеквизитов", ПоляИзмерений);
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&ИмяТаблицыМетаданных", ТекИмяТаблицы);
Запрос = Новый Запрос(ТекстЗапроса);
Если Описание.ЭтоСсылка И ДоступнаПакетнаяРегистрация Тогда
МодульОбменДаннымиСобытия = ОбщийМодуль("ОбменДаннымиСобытия");
МассивСсылок = Запрос.Выполнить().Выгрузить().ВыгрузитьКолонку("Ссылка");
ПараметрыПР = МодульОбменДаннымиСобытия.ПараметрыПакетнойРегистрации();
МодульОбменДаннымиСобытия.ВыполнитьПакетнуюРегистрациюДляУзла(Узел, МассивСсылок, ПараметрыПР);
Для Каждого Ссылка Из ПараметрыПР.СсылкиПоФильтруПакетнойРегистрации Цикл
Результат.Успешно = Результат.Успешно + 1;
ПланыОбмена.ЗарегистрироватьИзменения(Узел, Ссылка);
КонецЦикла;
Если ПараметрыПР.ЕстьПРО_БезПакетнойРегистрации Тогда
Для Каждого Ссылка Из ПараметрыПР.СсылкиНеПоФильтруПакетнойРегистрации Цикл
ДобавитьРезультаты(Результат, БСП_РегистрацияИзмененийСсылки(Узел, Ссылка, БезУчетаАвторегистрации));
КонецЦикла;
КонецЕсли;
Результат.Всего = МассивСсылок.Количество();
Возврат Результат;
КонецЕсли;
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
Если Описание.ЭтоНабор Тогда
Данные = Новый Структура(ПоляИзмерений);
ЗаполнитьЗначенияСвойств(Данные, Выборка);
ДобавитьРезультаты(Результат, БСП_РегистрацияИзмененийНабора(Узел, Данные, Описание) );
ИначеЕсли Описание.ЭтоСсылка Тогда
ДобавитьРезультаты(Результат, БСП_РегистрацияИзмененийСсылки(Узел, Выборка.Ссылка, БезУчетаАвторегистрации) );
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
// Обновляет данные ИОМ и регистрируем на переданном узле.
//
// Параметры:
// Узел - ПланОбменаСсылка
//
// Возвращаемое значение:
// Структура:
// * Всего - Число
// * Успешно - Число
// * Команда - Булево
//
Функция БСП_ОбновитьИЗарегистрироватьИОМГлавногоУзла(Знач Узел) Экспорт
Результат = Новый Структура("Всего, Успешно", 0 , 0);
МетаПланОбменаУзла = Узел.Метаданные();
Если (Не ДоступнаРаботаРИБ) // Недоступна работа с ИОМ из-за версии БСП.
Или (ПланыОбмена.ГлавныйУзел() <> Неопределено) // Текущая база - подчиненный узел.
Или (Не МетаПланОбменаУзла.РаспределеннаяИнформационнаяБаза) Тогда // Узел-параметр не РИБ
Возврат Результат;
КонецЕсли;
// Для РИБ все регистрируем без контроля правил БСП.
// Сам справочник
МетаСправочник = Метаданные.Справочники["ИдентификаторыОбъектовМетаданных"];
Если МетаПланОбменаУзла.Состав.Содержит(МетаСправочник) Тогда
ПланыОбмена.ЗарегистрироватьИзменения(Узел, МетаСправочник);
Запрос = Новый Запрос("ВЫБРАТЬ КОЛИЧЕСТВО(Ссылка) КАК КоличествоЭлементов ИЗ Справочник.ИдентификаторыОбъектовМетаданных");
Результат.Успешно = Запрос.Выполнить().Выгрузить()[0].КоличествоЭлементов;
КонецЕсли;
// Предопределенные элементы
Результат.Успешно = Результат.Успешно
+ ЗарегистрироватьИзменениеПредопределенныхДляУзла(Узел, Метаданные.Справочники)
+ ЗарегистрироватьИзменениеПредопределенныхДляУзла(Узел, Метаданные.ПланыВидовХарактеристик)
+ ЗарегистрироватьИзменениеПредопределенныхДляУзла(Узел, Метаданные.ПланыСчетов)
+ ЗарегистрироватьИзменениеПредопределенныхДляУзла(Узел, Метаданные.ПланыВидовРасчета);
Результат.Всего = Результат.Успешно;
Результат.Вставить("Команда", Истина);
Возврат Результат;
КонецФункции
Функция ЗарегистрироватьИзменениеПредопределенныхДляУзла(Знач Узел, Знач КоллекцияМетаданных)
СоставУзла = Узел.Метаданные().Состав;
Результат = 0;
Запрос = Новый Запрос;
ШаблонТекстаЗапроса =
"ВЫБРАТЬ
| ИмяТаблицыМетаданных.Ссылка
|ИЗ
| &ИмяТаблицыМетаданных КАК ИмяТаблицыМетаданных
|ГДЕ
| ИмяТаблицыМетаданных.Предопределенный";
Для Каждого ОбъектМетаданных Из КоллекцияМетаданных Цикл
Если СоставУзла.Содержит(ОбъектМетаданных) Тогда
ТекстЗапроса = СтрЗаменить(ШаблонТекстаЗапроса, "&ИмяТаблицыМетаданных", ОбъектМетаданных.ПолноеИмя());
Запрос.Текст = ТекстЗапроса;
Выборка = Запрос.Выполнить().Выбрать();
Результат = Результат + Выборка.Количество();
// Для РИБ регистрируем без контроля правил БСП.
Пока Выборка.Следующий() Цикл
ПланыОбмена.ЗарегистрироватьИзменения(Узел, Выборка.Ссылка);
КонецЦикла;
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
// Параметры:
// Отбор - Отбор - произвольный отбор.
// КлючЭлемента - Строка - имя элемента отбора.
// ЗначениеЭлемента - Произвольный - значение элемента отбора.
//
Процедура УстановитьЗначениеЭлементаОтбора(Отбор, КлючЭлемента, ЗначениеЭлемента) Экспорт
ЭлементОтбора = Отбор.Найти(КлючЭлемента);
Если ЭлементОтбора <> Неопределено Тогда
ЭлементОтбора.Установить(ЗначениеЭлемента);
КонецЕсли;
КонецПроцедуры
// Возвращаемое значение:
// ДеревоЗначений:
// * Наименование - Строка - представление вида объекта метаданных.
// * МетаПолноеИмя - Строка - полное имя объекта метаданных.
// * ИндексКартинки - Число - зависит от метаданных.
// * Пометка - Неопределено - далее используется для хранения пометок
// * ИдентификаторСтроки - Число - индекс добавленной строки (обход дерева сверху вниз слева направо).
// * Авторегистрация - Булево - если указан ИмяПланаОбмена, то для листьев: 1-разрешена,
// 2-запрещена. Иначе Неопределено.
// * КоличествоИзменений - Число - количество измененных записей.
// * КоличествоВыгруженных - Число - количество выгруженных записей.
// * КоличествоНевыгруженных - Число - количество не выгруженных записей.
// * КоличествоИзмененийСтрокой - Число - строковое представление количества измененных записей.
//
Функция ДеревоОбъектовМетаданных()
Дерево = Новый ДеревоЗначений;
Колонки = Дерево.Колонки;
Колонки.Добавить("Наименование");
Колонки.Добавить("МетаПолноеИмя");
Колонки.Добавить("ИндексКартинки");
Колонки.Добавить("Пометка");
Колонки.Добавить("ИдентификаторСтроки");
Колонки.Добавить("Авторегистрация");
Колонки.Добавить("КоличествоИзменений");
Колонки.Добавить("КоличествоВыгруженных");
Колонки.Добавить("КоличествоНевыгруженных");
Колонки.Добавить("КоличествоИзмененийСтрокой");
Возврат Дерево;
КонецФункции
////////////////////////////////////////////////////////////////////////////////
// Процедуры и функции из базовой функциональности для обеспечения автономности.
Функция ПодставитьПараметрыВСтроку(Знач СтрокаПодстановки, Знач Параметр1, Знач Параметр2 = Неопределено, Знач Параметр3 = Неопределено)
СтрокаПодстановки = СтрЗаменить(СтрокаПодстановки, "%1", Параметр1);
СтрокаПодстановки = СтрЗаменить(СтрокаПодстановки, "%2", Параметр2);
СтрокаПодстановки = СтрЗаменить(СтрокаПодстановки, "%3", Параметр3);
Возврат СтрокаПодстановки;
КонецФункции
#КонецОбласти
#Иначе
ВызватьИсключение НСтр("ru = 'Недопустимый вызов объекта на клиенте.'");
#КонецЕсли