Универсальный обмен между идентичными конфигурациями через REST интерфейс OData. Часть ІІІ: Регистры сведений

Часть III публикаций об универсальном обмен через REST интерфейс OData — обмен регистрами сведений

 

ПРЕДЫДУЩАЯ ЧАСТЬ. ЧАСТЬ ІІ. ДОКУМЕНТЫ

 

Если Вы уже знакомы с сериями об обмене справочниками и обмене документами, то уже догадываетесь/знаете, как мы "будем строить" наш обмен.

Перечислим процедуры и функции, которыми мы воспользуемся из предыдущих частей:

Функция ПолучитьКаналСвязиССерверомСбораДаних() // не изменится в этой статье, см. Часть І. Справочники
Функция НормализироватьКОбмену(ЭтотРеквизит) // не изменится в этой статье, , см. Часть І. Справочники
Функция СоединенияССерверомСбораДанныхУстановлено() Экспорт // не изменится в этой статье, , см. Часть І. Справочники
Процедура ОтправитьНаСерверСбораДанных(СсылкаИсточник, DELETE = Ложь, ТипОбъекта = 0, // не изменится в этой статье, см. Часть ІІ. Документы
БезКопии = Ложь, ОписаниеРеквизитовОтправки = Неопределено) Экспорт

 

Итак, для начала, в модуль набора записей регистра сведений в процедуру ПриЗаписи мы вставим следующее:

Если ОбменССерверомСбораДанных.СоединенияССерверомСбораДанныхУстановлено() Тогда // если база "подключена" к серверу
Если ЭтотОбъект.Количество() Тогда // и если есть что передавать (ЭтотОбъект - это набор записей регистра)
ОбменССерверомСбораДанных.ОтправитьНаСерверСбораДанных(ЭтотОбъект,, 3); // 3 - значит это регистр сведений
КонецЕсли;
КонецЕсли;

 

Далле через процедуру ОтправитьНаСерверСбораДанных мы попадем соответственно в такую функцию "доставки" записей регистра на сервер сбора данных (главную в этой статье):

 

 Функция РегистрСведенийДоставленоУспешно(НаборЗаписей, DELETE, Тень = Ложь)

 

Функция РегистрСведенийДоставленоУспешно(НаборЗаписей, DELETE, Тень = Ложь)

Связь = ПолучитьКаналСвязиССерверомСбораДаних(); // служебное - см. Часть І. Справочники

ИмяРегистра = НаборЗаписей.Метаданные().Имя;
Если Тень Тогда
ИмяРегистра = СтрЗаменить(ИмяРегистра,"_с_","");
КонецЕсли;

АдресРесурса = "/" + Связь.Порт + "/odata/standard.odata/InformationRegister_" + ИмяРегистра;

Соединение = Новый HTTPСоединение(Связь.Сервер);

ЗаголовокHTTP = Новый Соответствие();

ТекстШапкиЗапроса = "<?xml version=""1.0"" encoding=""UTF-8""?>
|<entry xmlns=""http://www.w3.org/2005/Atom""
|       xmlns:d=""http://schemas.microsoft.com/ado/2007/08/dataservices""
|        xmlns:m=""http://schemas.microsoft.com/ado/2007/08/dataservices/metadata""
|        xmlns:georss=""http://www.georss.org/georss""
|        xmlns:gml=""http://www.opengis.net/gml"">
|<category term=""StandardODATA.InformationRegister_" + ИмяРегистра + """ scheme=""http://schemas.microsoft.com/ado/2007/08/dataservices/scheme""/>
|<title type=""text""/>
|<content type=""application/xml"">
|<m:properties xmlns:d=""http://schemas.microsoft.com/ado/2007/08/dataservices"" xmlns:m=""http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"">";

// каждая запись будет доставляться отдельно
Для Каждого кЗапись Из НаборЗаписей Цикл

Если Константы.СерверСбораДанныхОфлайн.Получить() И (НЕ Тень) Тогда
//СоздатьТеневуюКопиюРегистраСведенийДляОтложеннойОправки(НаборЗаписей, кЗапись); // отложенная отправка
Продолжить;
КонецЕсли;

// чтобы успешно доставить запись сначала очистим данные по ключевым полям
хАдресРесурса = АдресРесурса;

хСписокСтандартов = СоздатьОписанияОбязательнихРеквизитовРегистраСведений(НаборЗаписей, кЗапись);  // новое служебное - смотри далее
хСписокИзмерений = СоздатьОписанияЗаписиРегистра(НаборЗаписей, кЗапись, "Измерения"); // новое служебное - смотри далее

Если хСписокСтандартов.Количество() ИЛИ хСписокИзмерений.Количество() Тогда
хАдресРесурса = хАдресРесурса + "(";

Итератор = 1;
Для Каждого хОписаниеРеквизита ИЗ хСписокСтандартов Цикл
хАдресРесурса = хАдресРесурса + хОписаниеРеквизита.Ключ + "='" + хОписаниеРеквизита.Значение + "'" + ?(Итератор = хСписокСтандартов.Количество() + хСписокИзмерений.Количество(),"",",");
Итератор = Итератор + 1;
КонецЦикла;

Для Каждого хОписаниеИземерения ИЗ хСписокИзмерений Цикл
хАдресРесурса = хАдресРесурса + хОписаниеИземерения.Ключ + "='" + хОписаниеИземерения.Значение + "'" + ?(Итератор = хСписокСтандартов.Количество() + хСписокИзмерений.Количество(),"",",");
Итератор = Итератор + 1;
КонецЦикла;

хАдресРесурса = хАдресРесурса + ")";

КонецЕсли;

Попытка
хСоединение = Новый HTTPСоединение(Связь.Сервер);
хЗапрос = Новый HTTPЗапрос(хАдресРесурса);
хОтвет = хСоединение.ВызватьHTTPМетод("DELETE", хЗапрос);
Исключение
КонецПопытки;

// следовательно, "предыдущая" запись удалена, если она была
// создаем новую

ТекстЗапроса = ТекстШапкиЗапроса;

// соответствие стандартных реквизитов
Для Каждого ОписаниеРеквизита ИЗ хСписокСтандартов Цикл  // были описаны выше
ТекстЗапроса = ТекстЗапроса + "
|         <d:" + ОписаниеРеквизита.Ключ + ">" + СокрЛП(ОписаниеРеквизита.Значение) + "</d:" + ОписаниеРеквизита.Ключ + ">";
КонецЦикла;

// соответствие Измерений
Для Каждого ОписаниеИзмерения ИЗ хСписокИзмерений Цикл // были описаны выше
ТекстЗапроса = ТекстЗапроса + "
|         <d:" + ОписаниеИзмерения.Ключ + ">" + СокрЛП(ОписаниеИзмерения.Значение) + "</d:" + ОписаниеИзмерения.Ключ + ">";
КонецЦикла;

// соответствие Ресурсов
ОписаниеРесурсов = СоздатьОписанияЗаписиРегистра(НаборЗаписей, кЗапись, "Ресурсы");
Для Каждого ОписаниеРесурса ИЗ ОписаниеРесурсов Цикл
ТекстЗапроса = ТекстЗапроса + "
|         <d:" + ОписаниеРесурса.Ключ + ">" + СокрЛП(ОписаниеРесурса.Значение) + "</d:" + ОписаниеРесурса.Ключ + ">";
КонецЦикла;

// соответствие Реквизитов
ОписаниеРеквизитов = СоздатьОписанияЗаписиРегистра(НаборЗаписей, кЗапись, "Реквизиты");
Для Каждого ОписаниеРеквизита ИЗ ОписаниеРеквизитов Цикл
ТекстЗапроса = ТекстЗапроса + "
|         <d:" + ОписаниеРеквизита.Ключ + ">" + СокрЛП(ОписаниеРеквизита.Значение) + "</d:" + ОписаниеРеквизита.Ключ + ">";
КонецЦикла;

ТекстЗапроса = ТекстЗапроса + "
|      </m:properties>
|   </content>
|</entry>";

Попытка
Запрос = Новый HTTPЗапрос(АдресРесурса, ЗаголовокHTTP);

Запрос.УстановитьТелоИзСтроки(ТекстЗапроса);

Ответ = Соединение.ВызватьHTTPМетод("POST", Запрос);
Исключение
КонецПопытки;

Если Ответ.КодСостояния <> 200 Тогда
Если НЕ Тень Тогда
//СоздатьТеневуюКопиюРегистраСведенийДляОтложеннойОправки(НаборЗаписей, кЗапись);  // отложенная отправка
КонецЕсли;
Иначе
Если Тень Тогда // если это отложена доставка
НаборЗаписей.Очистить();
НаборЗаписей.Записать(Истина);
КонецЕсли;
КонецЕсли;
КонецЦикла;

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

 

 

Список необходимых функций обозначенных комментарием "новое служебное":

 

 Функция СоздатьОписанияОбязательнихРеквизитовРегистраСведений(НаборЗаписей, этаЗапись)

 

 Функция СоздатьОписанияЗаписиРегистра(НаборЗаписей, ЭтаЗапись, КоллекцияМетаданныхКОписанию)

Вот и все — единственный нюанс передачи регистров, перед тем как передать запись надо подготовить под нее место — удалить уже существующую на сервере (если она есть).

 

<<< В части IV (последней)  опишем конвертацию "на ходу" по протоколу OData >>>

 

Спасибо, что дочитали до конца! 🙂

3 Comments

  1. izidakg

    Последняя часть будет?

    Reply
  2. V.Stavinsky

    (2) к сожалению (или к счастью) конвертирование на ходу на нашем проекте не понадобилось, поэтому пока конкретной идеи как ее реализовать нет. но фундаментом было получать правила конвертации из хранилищ (регистров), и соответственно транслировать одни объекты в другие

    Reply
  3. e-9

    Плюсанул все три статьи — и позаимствовал куски кода, спасибо!

    …Расширил у себя границы применения — ограничение «между идентичными конфигурациями» снимается достаточно простой доработкой: передаем (например, в структуре) все необходимые для формирования тела и заголовка запроса данные (такие как GUID, наименование объекта конфигурации базы-корреспондента, наименования и значения реквизитов для заполнения).

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *