В начало

План обмена справочника «Должности»

 

            Очередной пример плана обмена простенького справочника «Должности» между главной базой, выполненной на обычных формочках и базой филиала некой организации на управляемых формах в интерфейсе Такси.

 

Рис. Структура и внешний вид справочника «Должности» в главной базе

 

            Сначала создаем план обмена в разделе метаданных «Общие – Планы обмена», называем его скажем «ОбменДолжностей». Сразу переходим на закладку свойств объекта и изменяем состав плана обмена, а именно добавляем пресловутый справочник «Должности». Конечно, можно сразу надобавлять различных объектов в один план объекта, но торопиться не будем, ибо незачем.

Рис. Свойства объекта «ОбменДолжносте»,

закладка «Основные»

 

            Далее переходим на вкладку свойств «Данные» и создаём реквизит «ГлавныйУзел» с типом «Булево» для разрешения конфликтной ситуации, когда одновременно в двух базах был изменен один и тот же элемент справочника «Должности». Естественно, более приоритетными будут изменения совершенные в главном узле.

Рис. Свойства плана обмена «ОбменДолжностей» в конфигураторе,

Закладка «Данные»

 

            Потом переходим на закладку «Формы» свойств плана обмена «ОбменДолжностей» и создаем формы: ФормуУзла и ФормуСписка.

Рис. Свойства плана обмена «ОбменДолжностей»,

закладка «Формы»

 

            Теперь нужно добавить необходимый код. Начинаем с модуля объекта. В данном модуле нужно размести две процедуры для записи и чтения сообщений, а именно: ПрочитатьСообщениеСИзменениями() и ЗаписатьСообщениеСИзменениями().

 

Листинг. Модуль объекта плана обмена «ОбменДолжностей»

Процедура ПрочитатьСообщениеСИзменениями() Экспорт

            Каталог = КаталогВременныхФайлов();

            // Сформировать имя файла.

            ИмяФайла = Каталог + ?(Прав(Каталог, 1) = "\", "", "\") + "Сообщение_ОбменДолжностей_" + СокрЛП(Ссылка.Код) + "-" +

            СокрЛП(ПланыОбмена.ОбменСотрудников.ЭтотУзел().Код) + ".xml";

            Файл = Новый Файл(ИмяФайла);

            Если Не Файл.Существует() Тогда

                        Возврат;

            КонецЕсли;

            // *** Чтение документов XML

            // Попытаться открыть файл.

            ЧтениеXML = Новый ЧтениеXML;

            Попытка

                        ЧтениеXML.ОткрытьФайл(ИмяФайла);

            Исключение

                        Сообщение = Новый СообщениеПользователю;

                        Сообщение.Текст = "Невозможно открыть файл обмена данными";

                        Сообщение.Сообщить();

                        Возврат;

            КонецПопытки;

            Сообщение = Новый СообщениеПользователю;

            Сообщение.Текст = "-------- Загрузка из " + Строка(ЭтотОбъект) + " ------------";

            Сообщение.Сообщить();

            Сообщение = Новый СообщениеПользователю;

            Сообщение.Текст = " – Считывается файл " + ИмяФайла;

            Сообщение.Сообщить();

            // Загрузить из найденного файла

            // *** Инфраструктура сообщений.

            ЧтениеСообщения = ПланыОбмена.СоздатьЧтениеСообщения();

            // Читать заголовок сообщения обмена данными – файла XML.

            ЧтениеСообщения.НачатьЧтение(ЧтениеXML);

            // Сообщение предназначено не для этого узла.

            Если ЧтениеСообщения.Отправитель <> Ссылка Тогда

                        ВызватьИсключение "Неверный узел";

            КонецЕсли;

            // Удаляем регистрацию изменений для узла отправителя сообщения

            // *** Служба регистрации изменений.

            ПланыОбмена.УдалитьРегистрациюИзменений(ЧтениеСообщения.Отправитель,

            ЧтениеСообщения.НомерПринятого);

            // Читаем данные из сообщения *** XML-сериализация

            Пока ВозможностьЧтенияXML(ЧтениеXML) Цикл

                        // Читаем очередное значение.

                        Данные = ПрочитатьXML(ЧтениеXML);

                        // Не переносим изменение, полученное в главный из НЕ главного,

                        // если есть регистрация изменения

                        Если Не ЧтениеСообщения.Отправитель.ГлавныйУзел И

                                   ПланыОбмена.ИзменениеЗарегистрировано(

                                   ЧтениеСообщения.Отправитель, Данные) Тогда

                                   Сообщение = Новый СообщениеПользователю;

                                   Сообщение.Текст = " – Изменения отклонены";

                                   Сообщение.Сообщить();

                                   Продолжить;

                        КонецЕсли;

                        // Записать полученные данные

                        Данные.ОбменДанными.Отправитель = ЧтениеСообщения.Отправитель;

                        Данные.ОбменДанными.Загрузка = Истина;

                        Данные.Записать();

            КонецЦикла;

            ЧтениеСообщения.ЗакончитьЧтение();

            ЧтениеXML.Закрыть();

            УдалитьФайлы(ИмяФайла);

            Сообщение = Новый СообщениеПользователю;

            Сообщение.Текст = "-------- Конец загрузки ------------";

            Сообщение.Сообщить();

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

 

Процедура ЗаписатьСообщениеСИзменениями() Экспорт

            Сообщение = Новый СообщениеПользователю;

            Сообщение.Текст = "-------- Выгрузка в узел " + Строка(ЭтотОбъект) + " ------------";

            Сообщение.Сообщить();

            Каталог = КаталогВременныхФайлов();

            // Сформировать имя временного файла.

            ИмяФайла = Каталог + ?(Прав(Каталог, 1) = "\","", "\") + "Сообщение_ОбменДолжностей_" +

            СокрЛП(ПланыОбмена.ОбменСотрудников.ЭтотУзел().Код) + "-" + СокрЛП(Ссылка.Код) + ".xml";

            // Создать объект записи XML

            // *** ЗаписьXML-документов.

            ЗаписьXML = Новый ЗаписьXML;

            ЗаписьXML.ОткрытьФайл(ИмяФайла);

            ЗаписьXML.ЗаписатьОбъявлениеXML();

            // *** Инфраструктура сообщений

            ЗаписьСообщения = ПланыОбмена.СоздатьЗаписьСообщения();

            ЗаписьСообщения.НачатьЗапись(ЗаписьXML, Ссылка);

            Сообщение = Новый СообщениеПользователю;

            Сообщение.Текст = " Номер сообщения: " + ЗаписьСообщения.НомерСообщения;

            Сообщение.Сообщить();

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

            // *** Механизм регистрации изменений

            ВыборкаИзменений = ПланыОбмена.ВыбратьИзменения(ЗаписьСообщения.

            Получатель,ЗаписьСообщения.НомерСообщения);

            Пока ВыборкаИзменений.Следующий() Цикл

                        // Записать данные в сообщение *** XML-сериализация.

                        ЗаписатьXML(ЗаписьXML, ВыборкаИзменений.Получить());

            КонецЦикла;

            ЗаписьСообщения.ЗакончитьЗапись();

            ЗаписьXML.Закрыть();

            Сообщение = Новый СообщениеПользователю;

            Сообщение.Текст = "-------- Конец выгрузки ------------";

            Сообщение.Сообщить();

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

 

            Далее переходим к модулю формы узла и добавляем обработчик события «ПередОткрытием», в котором пишем код для установки доступности элемента формы «Главный узел».

Листинг. Модуль формы узла плана обмена «ОбменДолжностей»

Процедура ПередОткрытием(Отказ, СтандартнаяОбработка)

            Если ЭтотОбъект.Ссылка = ПланыОбмена.ОбменДолжностей.ЭтотУзел() Тогда

                        ЭлементыФормы.ГлавныйУзел.Доступность = Ложь;

            КонецЕсли;

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

            Затем переходим к форме списка плана обмена «ОбменДолжностей». Создаём на данной форме кнопочку «Зарегистрировать изменения». Добавляем обработчик нажатия кнопки. А также добавляем код «ПриАктивацииСтроки», который будет управлять доступностью кнопки «ЗарегистрироватьИзменения» для нажатия.

 

Листинг. Модуль формы списка плана обмена «ОбменДолжностей»

Процедура ЗарегистрироватьИзмененияНажатие(Элемент)

            ПланыОбмена.ЗарегистрироватьИзменения(ЭлементыФормы.ПланОбменаСписок.ТекущаяСтрока);           

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

 

Функция ЭтоПредопределенныйУзел(Узел)

            Возврат Узел = ПланыОбмена.ОбменДолжностей.ЭтотУзел();

КонецФункции

 

Процедура ПланОбменаСписокПриАктивизацииСтроки(Элемент)

            Если ЭтоПредопределенныйУзел(ЭлементыФормы.ПланОбменаСписок.ТекущаяСтрока) Тогда

                        ЭлементыФормы.ЗарегистрироватьИзменения.Доступность = Ложь;

            Иначе

                        ЭлементыФормы.ЗарегистрироватьИзменения.Доступность = Истина;

            КонецЕсли;

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

 

            Теперь запустим программу в режиме «1С:Предприятие» и настроим план обмена. Необходимо заполнить код и наименование для главного узла и филиала, примерно как показано далее.

Рис. План обмена «Обмен должностей»

            И наконец, возвращаемся в конфигуратор и создаем обработку «ОбменДолжностей», для которой создаём форму обработки. Добавляем код на кнопку «Выполнить обмен».

Рис. Форма обработки «ОбменДолжностей» в конфигураторе

 

            Далее приведен листинг модуля формы с кодом обработчика нажатия кнопки.

 

Листинг. Модуль формы обработки «ОбменДолжностей»

Процедура КнопкаВыполнитьНажатие(Кнопка)

            ВыборкаУзлов = ПланыОбмена.ОбменДолжностей.Выбрать();

            Пока ВыборкаУзлов.Следующий() Цикл

                        // Произвести обмен данными со всеми узлами, кроме текущего (ЭтотУзел)

                        Если ВыборкаУзлов.Ссылка <> ПланыОбмена.ОбменДолжностей.ЭтотУзел() Тогда

                                   УзелОбъект = ВыборкаУзлов.ПолучитьОбъект();

                                   //Далее идут процедуры, описанные в модуле плана обмена

                                   УзелОбъект.ПрочитатьСообщениеСИзменениями();

                                   УзелОбъект.ЗаписатьСообщениеСИзменениями();

                        КонецЕсли;

            КонецЦикла;

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

 

            Протестируем данную обработку. Для этого запустимся в режиме отладки, откроем обработку «ОбменДолжностей», нажмем кнопочку «Выполнить обмен». При этом должен сформировать XML-файл сообщения с данными для обмена между главной базой и базой филиала. Файл можно найти в каталоге временных файлов, а его имя – «Сообщение_ОбменДолжностей_ЦБ-ФЛ.xml». Данный файл можно открыть или в текстовом редакторе или браузере.

 

Листинг. Кусок кода файла обмена «Сообщение_ОбменДолжностей_ЦБ-ФЛ.xml»

<?xml version="1.0" encoding="UTF-8"?>

<v8msg:Message xmlns:v8msg="http://v8.1c.ru/messages">

            <v8msg:Header>

                        <v8msg:ExchangePlan>ОбменДолжностей</v8msg:ExchangePlan>

                        <v8msg:To>ФЛ</v8msg:To>

                        <v8msg:From>ЦБ</v8msg:From>

                        <v8msg:MessageNo>1</v8msg:MessageNo>

                        <v8msg:ReceivedNo>0</v8msg:ReceivedNo>

            </v8msg:Header>

            <v8msg:Body>

                        <CatalogObject.Должности>

                                   <Ref>1e9a4575-fb18-11ea-80dc-001eec3547a4</Ref>

                                   <DeletionMark>false</DeletionMark>

                                   <Code>000000001</Code>

                                   <Description>Менеджер</Description>

                        </CatalogObject.Должности>

                        <CatalogObject.Должности>

                                   <Ref>1e9a4579-fb18-11ea-80dc-001eec3547a4</Ref>

                                   <DeletionMark>false</DeletionMark>

                                   <Code>000000003</Code>

 

            Далее настроим базу филиала аналогичным образом. Начнем с создания плана обмена «ОбменДолжностей».  Код в модуле объекта «ОбменДолжностей» аналогичен тому, что расположен в конфигурации главной базы.

Создаем для плана обмена «ОбменДолжностей» форму узла.

Рис. Форма узла плана обмена в конфигурации филиала

 

            В модуль формы узла добавляем обработчик «ПриСозданииНаСервере».

 

Листинг. Модуль узла плана обмена «ОбменДолжностей»

&НаСервере

Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)

            Если Объект.Ссылка = ПланыОбмена.ОбменДолжностей.ЭтотУзел() Тогда

                        Элементы.ГлавныйУзел.Доступность = Ложь;

            КонецЕсли;

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

 

            Далее добавляем форму списка, создаем команду «ЗарегистрироватьИзменения» и перетаскивая ее в левую часть конструктора формы, создаем, таким образом, одноимённую кнопку, для которой добавляем обработчик нажатия.

Рис. Форма списка плана обмена «ОбменДолжностей»

в конструкторе конфигурации филиала фирмы

 

            Также необходимо добавить обработчик «ПриАктивацииСтроки» для списка формы списка. Приведен ниже листинг формы списка для наглядности.

 

Листинг. Модуль формы списка плана обмена «ОбменДолжностей»

в конфигурации филиала организации

&НаСервереБезКонтекста

Функция ЭтоПредопределенныйУзел(Узел)

            Возврат Узел = ПланыОбмена.ОбменДолжностей.ЭтотУзел();

КонецФункции

 

&НаСервереБезКонтекста

Процедура ЗарегистрироватьИзмененияНаСервере(Узел)

            ПланыОбмена.ЗарегистрироватьИзменения(Узел)

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

 

&НаКлиенте

Процедура ЗарегистрироватьИзменения(Команда)

            ЗарегистрироватьИзмененияНаСервере(Элементы.Список.ТекущаяСтрока);

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

 

&НаКлиенте

Процедура СписокПриАктивизацииСтроки(Элемент)

            Если ЭтоПредопределенныйУзел(Элемент.ТекущаяСтрока) Тогда

                        Элементы.ЗарегистрироватьИзменения.Доступность = Ложь;

            Иначе

                        Элементы.ЗарегистрироватьИзменения.Доступность = Истина;

            КонецЕсли;

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

 

            Протестируем план обмена в режиме отладки. Также нужно изменить код и наименование предопределённого узла и создать узел для центральной базы. Для центральной базы нужно установить галочку «Главный узел» на форме узла.

Рис. План обмена «Обмен должностей»

 

            Теперь вернемся в конфигуратор и создадим обработку «ОбменДолжностей». Для обработки сделаем формочку и добавим команду/кнопку выполнить обмен.

Рис. Форма обработки «ОбменДолжностей» в конфигураторе

 

            Далее привожу процедуры, расположенные модуле формы обработки.

 

Листинг. Модуль формы обработки «Обмен должностей»

&НаСервереБезКонтекста

Процедура ВыполнитьОбменНаСервере()

            ВыборкаУзлов = ПланыОбмена.ОбменДолжностей.Выбрать();

            Пока ВыборкаУзлов.Следующий() Цикл

                        // Произвести обмен данными со всеми узлами, кроме текущего (ЭтотУзел).

                        Если ВыборкаУзлов.Ссылка <> ПланыОбмена.ОбменДолжностей.ЭтотУзел() Тогда

                                   УзелОбъект = ВыборкаУзлов.ПолучитьОбъект();

                                  

                                   //Вызов процедур из модуля плана обмена

                                   УзелОбъект.ПрочитатьСообщениеСИзменениями();

                                   УзелОбъект.ЗаписатьСообщениеСИзменениями();

                        КонецЕсли;

            КонецЦикла;

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

 

&НаКлиенте

Процедура ВыполнитьОбмен(Команда)

            ВыполнитьОбменНаСервере();

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

 

            Протестируем обработку в режиме отладки. Открываем план обмена «ОбменДолжностей», нажимаем кнопочку «Зарегистрировать изменения». Далее запускаем обработку «Обмен должностей» и нажимаем кнопу «Выполнить обмен». Если ошибок нет, то будет прочитан файл, созданный в главной базе «Сообщение_ОбменСотрудников_ЦБ-ФЛ.xml», а вместо него создан другой «Сообщение_ОбменСотрудников_ФЛ-ЦБ.xml». При этом будут внесены изменения в справочник «Должности».

 

Рис. Справочник «Должности»:

в главной базе (слева) и базе филиала (справа)

 

            Проверяем обмен, удаляем,  добавляем элементы справочника «Должности» в разных базах и одновременно. Все работает.