Пример простого обмена двух баз через файл с квитированием
В общем виде обмен с квитированием осущетвляется в несколько шагов:
- Создание сообщения обмена в источнике
- Чтение и обработка сообщения обмена в приемнике
- Создание подтверждающего сообщения в приемнике (квитирование)
- Чтение и удаление успешно переданного из плана обмена в источнике
Сообщение обмена Источник-Приемник
Создание сообщения
Создаем план обмена, реализуем выгрузку. В примере в плане обмена источника зарегистрирован один справочник “Номенклатура”
// Узел обмена - целевой узел обмена базы приемника в плане обменаПроцедура ВыгрузитьНоменклатуруВФайл(УзелОбмена) Экспорт
Если Не ЗначениеЗаполнено(УзелОбмена) Тогда ВызватьИсключение "Не установлен узел обмена"; КонецЕсли;
// полное имя файла, куда будет записываться выгрузка ИмяСообщения = "C:\путь-до-папки-обмена\Выгрузка_Источник_Приемник.xml";
ЗаписьXML = Новый ЗаписьXML; ЗаписьXML.ОткрытьФайл(ИмяСообщения, "UTF-8");
ЗаписьСообщения = ПланыОбмена.СоздатьЗаписьСообщения();
// тут записываются служебные заголовки сообщения - узел, номер сообщения и пр. ЗаписьСообщения.НачатьЗапись(ЗаписьXML, УзелОбмена);
// выгружаем все изменения, дополнительно устанавливаем номер сообщения из ЗаписьСообщения, // т.к. до выгрузки изменений номер сообщения в таблице изменений = NULL ВыборкаИзменений = ПланыОбмена.ВыбратьИзменения(УзелОбмена, ЗаписьСообщения.НомерСообщения);
// Записываем данные любым способом, которым удобно // тут приведен пример примитивной поузловой записи ЗаписьXML.ЗаписатьНачалоЭлемента("СписокНоменклатуры");
Пока ВыборкаИзменений.Следующий() Цикл
Данные = ВыборкаИзменений.Получить();
ЗаписьXML.ЗаписатьНачалоЭлемента("Номенклатура");
ЗаписьXML.ЗаписатьНачалоЭлемента("Код"); ЗаписьXML.ЗаписатьТекст(Данные.Код); ЗаписьXML.ЗаписатьКонецЭлемента();
...
ЗаписьXML.ЗаписатьНачалоЭлемента("ПометкаУдаления"); ЗаписьXML.ЗаписатьТекст(Строка(Данные.ПометкаУдаления)); ЗаписьXML.ЗаписатьКонецЭлемента();
ЗаписьXML.ЗаписатьКонецЭлемента();
КонецЦикла;
ЗаписьXML.ЗаписатьКонецЭлемента();
// закрываем служебные узлы сообщения ЗаписьСообщения.ЗакончитьЗапись();
ЗаписьXML.Закрыть();
Сообщение = Новый СообщениеПользователю; Сообщение.Текст = "Успешная выгрузка"; Сообщение.Сообщить();
КонецПроцедуры
В результате получим xml вида:
<!--Начало блока, добавляемого методом ЗаписьСообщения.НачатьЗапись()--><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>16</v8msg:MessageNo> <v8msg:ReceivedNo>0</v8msg:ReceivedNo> </v8msg:Header> <v8msg:Body><!--конец блока, добавляемого методом ЗаписьСообщения.НачатьЗапись()-->
<!--Начало блока, который формируется нами вручную--> <СписокНоменклатуры> <Номенклатура> <Код>000000006</Код> ... <ПометкаУдаления>Нет</ПометкаУдаления> </Номенклатура> <Номенклатура> ... </Номенклатура> ... <Номенклатура> ... </Номенклатура> </СписокНоменклатуры><!--Конец блока, который формируется нами вручную-->
<!--Начало блока, добавляемого методом ЗаписьСообщения.ЗакончитьЗапись()--> </v8msg:Body></v8msg:Message><!--Конец блока, добавляемого методом ЗаписьСообщения.ЗакончитьЗапись()-->
Чтение сообщения в базе-приемнике
ВАЖНО! В приемнике должен быть план обмена с таким же именем, что и в источнике. Также нужно, чтобы код узла базы приемника совпадал с кодом, указанным в шапке сообщения в блоке
<v8msg:To>
. Это необходимо для того, чтобы методы чтения сообщения корректно сработали
Считываем данные для обработки в приемнике
// ПолноеИмяФайла - путь к файлу обмена, созданному источником// ТаблицаДляЗагрузки - промежуточная таблица для последующей загрузки в запросПроцедура ЗаполнитьТаблицуДляЗагрузки(ПолноеИмяФайла, ТаблицаДляЗагрузки)
СоответствиеКолонокУзлам = Новый Соответствие; СоответствиеКолонокУзлам.Вставить("Наименование", "Наименование"); ... СоответствиеКолонокУзлам.Вставить("ПометкаУдаления", "ПометкаУдаления");
// Создаем объект чтения сообщения ЧтениеСообщения = ПланыОбмена.СоздатьЧтениеСообщения();
// Создаем объект, который будет использоваться чтением сообщения ЧтениеXML = Новый ЧтениеXML; ЧтениеXML.ОткрытьФайл(ПолноеИмяФайла);
// Считываем служебную информацию сообщения. Код узла, номера сообщений и пр. ЧтениеСообщения.НачатьЧтение(ЧтениеXML);
// Проверяем, что отправитель это именно та база, откуда мы ожидаем сообщение Если ЧтениеСообщения.Отправитель <> "ИБ" Тогда //Обработка ошибки Возврат; КонецЕсли;
// Считываем данные, записанные в <body> узле сообщения Пока ЧтениеXML.Прочитать() Цикл
// Мы должны закончить чтение на узле </v8msg:Body>, // иначе метод ЧтениеСообщения.ЗакончитьЧтение() завершится с ошибкой Если ЧтениеXML.ТипУзла = ТипУзлаXML.КонецЭлемента И ЧтениеXML.Имя = "v8msg:Body" Тогда Прервать; КонецЕсли;
Если ЧтениеXML.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда
ИмяТекущегоУзла = ЧтениеXML.Имя; Если ИмяТекущегоУзла = "Номенклатура" Тогда СтрокаТаблицы = ТаблицаДляЗагрузки.Добавить(); КонецЕсли;
ИначеЕсли ЧтениеXML.ТипУзла = ТипУзлаXML.Текст Тогда
ИмяКолонкиТаблицы = СоответствиеКолонокУзлам.Получить(ИмяТекущегоУзла);
Если ИмяКолонкиТаблицы <> Неопределено Тогда СтрокаТаблицы[ИмяКолонкиТаблицы] = ЧтениеXML.Значение; КонецЕсли;
КонецЕсли;
КонецЦикла;
// Считываем закрывающие служебные тэги сообщения ЧтениеСообщения.ЗакончитьЧтение();
// завершаем чтение файла ЧтениеXML.Закрыть();
КонецПроцедуры
Чтение будет проходить следующими этапами
<!--ЧтениеСообщения.НачатьЧтение()--><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>16</v8msg:MessageNo> <v8msg:ReceivedNo>0</v8msg:ReceivedNo> </v8msg:Header> <v8msg:Body><!--Конец ЧтениеСообщения.НачатьЧтение()-->
<!--ЧтениеXML.Прочитать()--> <СписокНоменклатуры> <Номенклатура> <Код>000000006</Код> ... <ПометкаУдаления>Нет</ПометкаУдаления> </Номенклатура> <Номенклатура> ... </Номенклатура> <Номенклатура> ... </Номенклатура> ... <Номенклатура> ... </Номенклатура> </СписокНоменклатуры><!--Конец ЧтениеXML.Прочитать()-->
<!--ЧтениеСообщения.ЗакончитьЧтение()--> </v8msg:Body></v8msg:Message><!--Конец ЧтениеСообщения.ЗакончитьЧтение()-->
<!--ЧтениеXML.Закрыть()-->
Дальше обрабатываем данные файла в приемнике как нужно.
Сообщение Приемник-Источник. Квитирование (гарантия доставки)
Формирование сообщения в базе приемнике
Квитирование необходимо для того, чтобы дать источнику данные о том, какие сообщения приемник получил и успешно обработал. Записи таблицы изменений, где номер сообщения меньше либо равен номеру, указанному в квитанции можно удалять из таблицы изменений.
Простыми словами, после того, как в базе источнике мы обработали все данные, нужно сформировать ответное сообщение только с шапкой, без данных. В шапке будет указан НомерПринятого
, который будет равен НомеруОтправленного
из полученного ранее сообщения
Процедура СформироватьКвитанциюЗаписатьВКаталогОбмена()
// куда сохраняем квитанцию ИмяФайла = "C:\путь-до-папки-обмена\Квитанция_ПБ_ИБ.xml";
// Узел в плане обмена, которому направляем квитанцию о получении Узел = ПланыОбмена.СН_ОбменСПриемником.НайтиПоКоду("ИБ"); Если Не ЗначениеЗаполнено(Узел) Тогда ВызватьИсключение "Неопределенный узел получателя квитанции"; КонецЕсли;
Запись = Новый ЗаписьXML; Запись.ОткрытьФайл(ИмяФайла);
// Тут записываем шапку ЗаписьСообщения = ПланыОбмена.СоздатьЗаписьСообщения(); ЗаписьСообщения.НачатьЗапись(Запись, Узел);
// заканчиваем запись, не записывая тело. Только шапка ЗаписьСообщения.ЗакончитьЗапись();
// Закрываем файл Запись.Закрыть();
КонецПроцедуры
Пример квитанции
<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>4</v8msg:MessageNo> <v8msg:ReceivedNo>20</v8msg:ReceivedNo> </v8msg:Header> <v8msg:Body/></v8msg:Message>
Чтение квитанции в базе-источнике. Удаление записей о регистрации изменений
В источнике нужно считать квитанцию, сформированную выше, и удалить из таблиц изменений все записи, номер отправленного которых меньше или равен номеру принятого в квитанции
Процедура ПрочитатьКвитанциюУдалитьИзмененияИзПланаОбмена(УзелОбмена) Экспорт
ПутьКФайлу = "C:\путь-до-папки-обмена\Квитанция_ПБ_ИБ.xml";
ЧтениеСообщения = ПланыОбмена.СоздатьЧтениеСообщения();
Чтение = Новый ЧтениеXML; Чтение.ОткрытьФайл(ПутьКФайлу);
// считываем квитанцию ЧтениеСообщения.НачатьЧтение(Чтение);
НомерПринятого = ЧтениеСообщения.НомерПринятого;
// удаляем переданное по номеру принятого, указанного в квитанции ПланыОбмена.УдалитьРегистрациюИзменений(УзелОбмена, НомерПринятого);
ЧтениеСообщения.ЗакончитьЧтение();
Чтение.Закрыть();
// удаляем квитанции УдалитьФайлы(ПутьКФайлу);
КонецПроцедуры