ПРЕДЫДУЩАЯ ЧАСТЬ. ЧАСТЬ ІІ. ДОКУМЕНТЫ
Если Вы уже знакомы с сериями об обмене справочниками и обмене документами, то уже догадываетесь/знаете, как мы "будем строить" наш обмен.
Перечислим процедуры и функции, которыми мы воспользуемся из предыдущих частей:
Функция ПолучитьКаналСвязиССерверомСбораДаних() // не изменится в этой статье, см. Часть І. Справочники
Функция НормализироватьКОбмену(ЭтотРеквизит) // не изменится в этой статье, , см. Часть І. Справочники
Функция СоединенияССерверомСбораДанныхУстановлено() Экспорт // не изменится в этой статье, , см. Часть І. Справочники
Процедура ОтправитьНаСерверСбораДанных(СсылкаИсточник, 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 >>>
Спасибо, что дочитали до конца! 🙂
Последняя часть будет?
(2) к сожалению (или к счастью) конвертирование на ходу на нашем проекте не понадобилось, поэтому пока конкретной идеи как ее реализовать нет. но фундаментом было получать правила конвертации из хранилищ (регистров), и соответственно транслировать одни объекты в другие
Плюсанул все три статьи — и позаимствовал куски кода, спасибо!
…Расширил у себя границы применения — ограничение «между идентичными конфигурациями» снимается достаточно простой доработкой: передаем (например, в структуре) все необходимые для формирования тела и заголовка запроса данные (такие как GUID, наименование объекта конфигурации базы-корреспондента, наименования и значения реквизитов для заполнения).