Предназначен для быстрой организации HTTP сервиса, которые предоставляет функции, необходимые для большинства связанных с ним операцией.
В рамках разработки создан универсальный модуль с функциями, которые ускоряют и упрощают этот процесс.
Рассказ о том, как получился этот модуль, был сделан на Инфостарте 2024.
https://event.infostart.ru/2024/agenda/2190185/
Модуль предлагаю брать за 1 стартмани (100 рублей, труда в эти функции в часах разработчика вложено существенно больше), он постоянно развивается. Для меня это показатель, насколько актуально развитие этого модуля и ему подобных.
ОбщийМодуль состоит из 2 частей
1. Функции для работы с HTTP Сервисом, проверка обязательных параметров, преобразование параметров, приведение к нижнему регистру, преобразование результата запроса в готовую структуру для кодировки в JSON (редактировать выданный результат можно через редактирование запроса в 1с)
2. Преобразование любого объекта 1с в структуру с детализацией по вложениям (любой справочник/документ можно преобразовать в структуру с информацией по вложенным объектам и выдать как готовый результат.) - удобно для интерграции или прямой выдачи объектов из 1с в сторонние системы. Может использоваться как элемент HTTP Сервиса или для самостоятельной выгрузки данных .
Часть 1. Быстрая Организация HTTP Сервиса. (Пошаговое описание)
1. Создаем единый входящий шаблон
Функция ОбщийШаблонGET(Запрос)
Ответ = Новый HTTPСервисОтвет(200);
ОтветАпи = {ОбщийМодульГдеБудутФормароватьсяОтветы}.ВыполнитьФункциюАпи(Запрос);
Ответ.УстановитьТелоИзСтроки(ОтветАпи);
Ответ.Заголовки.Вставить("Accept","application/json");
Ответ.Заголовки.Вставить("Content-Type","application/json");
Возврат Ответ;
КонецФункции
2. Создаем роутер входящих сообщений.
Создаем отдельный общий модуль, где будет определяться, какая функция должна использоваться для обработки входящего запроса.
Функция ВыполнитьФункциюАпи(Запрос) экспорт
ПараметрыURL = Запрос.ПараметрыURL;
// /{resouse}/{comand}
HTTPМетод = Запрос.HTTPМетод;
resourse = ?(ПараметрыURL.получить("resourse") =Неопределено,Неопределено,нрег(ПараметрыURL.получить("resourse")));
comand = ?(ПараметрыURL.получить("comand") =Неопределено,Неопределено,нрег(ПараметрыURL.получить("comand")));
Если resourse = "apireqest" И comand = "list" тогда // шаблон с вумя значениями
ОтветАпи = ФункцияОбрабатывающаяЗапрос(Запрос);
ИначеЕсли resourse = Неопределено И comand = "list" тогда // шаблон с 1 значением
ОтветАпи = ФункцияОбрабатывающаяЗапрос(Запрос);
ИначеЕсли resourse = Неопределено И comand = "list" тогда
ОтветАпи = ФункцияОбрабатывающаяЗапрос(Запрос);
Иначе
ОтветАпи = НегативныйОтвет("Не определена команда для выполнения");
КонецЕсли;
Возврат ОтветАпи;
КонецФункции
3. Преобразовать параметры.
Далее входящие обязательные параметры можно преобразовать в конкретные значения.
Функция ПреобразоватьПараметры(СтрДанных) Экспорт
массивОшибок = Новый массив;
НоваяСтруктура = Новый Структура("Успех,Ошибка",Ложь,"");
// дата
Если СтрДанных.Свойство("date") тогда
Попытка
ДатаДок = Дата(СтрДанных.date + " 00:00:00");
НоваяСтруктура.Вставить("date",ДатаДок);
Исключение
массивОшибок.Добавить("Не удалось преобразовать дату date.");
КонецПопытки;
КонецЕсли;
// Дата начала
Если СтрДанных.Свойство("datestart") тогда
Попытка
ДатаДок = Дата(СтрДанных.datestart + " 00:00:00");
НоваяСтруктура.Вставить("datestart",ДатаДок);
Исключение
массивОшибок.Добавить("Не удалось преобразовать дату datestart.");
КонецПопытки;
КонецЕсли;
// Датаокончания
Если СтрДанных.Свойство("dateend") тогда
Попытка
ДатаДок = Дата(СтрДанных.dateend + " 23:59:59");
НоваяСтруктура.Вставить("dateend",ДатаДок);
Исключение
массивОшибок.Добавить("Не удалось преобразовать дату dateend.");
КонецПопытки;
КонецЕсли;
// Смотрим другие значения
Если массивОшибок.Количество() > 0 Тогда
НоваяСтруктура.Вставить("Успех",Ложь);
Ошибка = СтрСоединить(массивОшибок,",");
НоваяСтруктура.Вставить("Ошибка",Ошибка);
Возврат НоваяСтруктура;
КонецЕсли;
НоваяСтруктура.Успех = Истина;
Возврат НоваяСтруктура;
КонецФункции
4. Создаем типовую функцию, которая обрабатывает итоговый ответ
В ней пошагово проверяем Обязательные параметры, преобразуем в значения.
Формируем запроса с именами полей как они должны быть выданы в итоговом ответе,
выполняем запрос и с помощью функции ЗначениеРезультатаЗапросаВСтруктуру(РезультатЗапроса,МножественноеЗначение) получаем результирующую структуру/массив
Если это одно значение, то МножественноеЗначение = ложь и вам вернется структура первого значения
Если это выборка нескольких значений, тогда нужно указать МножественноеЗначение = Истина, вернется массив.
Итоговый ответ надо упаковать в НегативныйОтвет или ПозитивныйОтвет, которая преобразуют сформированный объект в JSON в итоговый ответ в виде строки.
Итоговая функция, которая принимает запрос и выдает результат, будет выглядеть следующим образом с этим модулем.
Функция ДетализацияИспользованногоСырьяПоПекарнеЗаДень(HTTPЗапрос) Экспорт
мПараметров = Новый массив;
мПараметров.Добавить("bakerycode");
мПараметров.Добавить("date");
мПараметров.Добавить("resourcecode");
Рез = АпиСервисСервер.ПроверитьНаличиеОбязательныхПараметров(HTTPЗапрос,мПараметров);
Если Рез.успех = ложь тогда
Возврат НегативныйОтвет(Рез.ошибка);
КонецЕсли;
Данные = Рез.Данные;
ПреобразованныеПараметры = АпиСервисСервер.ПреобразоватьПараметры(Данные);
Если ПреобразованныеПараметры.Успех = Ложь Тогда
Возврат НегативныйОтвет(ПреобразованныеПараметры.Ошибка);
КонецЕсли;
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ВЫБОР
| КОГДА ТИПЗНАЧЕНИЯ(ФактическийВыпускРасчетРасчетСписанногоСырья.Продукция) = ТИП(Справочник.Номенклатура)
| ТОГДА ""good""
| КОГДА ТИПЗНАЧЕНИЯ(ФактическийВыпускРасчетРасчетСписанногоСырья.Продукция) = ТИП(Справочник.Полуфабрикат)
| ТОГДА ""halfstuff""
| ИНАЧЕ """"
| КОНЕЦ КАК producttype,
| ФактическийВыпускРасчетРасчетСписанногоСырья.Продукция.Код КАК productcode,
| ФактическийВыпускРасчетРасчетСписанногоСырья.Продукция.Наименование КАК productname,
| ФактическийВыпускРасчетРасчетСписанногоСырья.Сырье.Наименование КАК rawmaterialname,
| ФактическийВыпускРасчетРасчетСписанногоСырья.Сырье.Код КАК rawmaterialcode,
| ФактическийВыпускРасчетРасчетСписанногоСырья.Количество КАК resoursetotal,
| ФактическийВыпускРасчетРасчетСписанногоСырья.КоличествоПродукции КАК produced,
| ФактическийВыпускРасчетРасчетСписанногоСырья.КоличествоНаЕдиницу КАК resoursetounit
|ИЗ
| Документ.ФактическийВыпускРасчет.РасчетСписанногоСырья КАК ФактическийВыпускРасчетРасчетСписанногоСырья
|ГДЕ
| ФактическийВыпускРасчетРасчетСписанногоСырья.Ссылка.ТорговаяТочка = &ТорговаяТочка
| И ФактическийВыпускРасчетРасчетСписанногоСырья.Ссылка.Дата МЕЖДУ &ДатаН И &ДатаК
| И ФактическийВыпускРасчетРасчетСписанногоСырья.Ссылка.Проведен = ИСТИНА
| И ФактическийВыпускРасчетРасчетСписанногоСырья.Сырье = &Сырье";
Запрос.УстановитьПараметр("ДатаН", НачалоДня(ПреобразованныеПараметры.date));
Запрос.УстановитьПараметр("ДатаК", КонецДня(ПреобразованныеПараметры.date));
Запрос.УстановитьПараметр("ТорговаяТочка", ПреобразованныеПараметры.bakerycode);
Запрос.УстановитьПараметр("Сырье", ПреобразованныеПараметры.resourcecode);
РезультатЗапроса = Запрос.Выполнить();
СтрРезультат = АпиСервисСервер.ЗначениеРезультатаЗапросаВСтруктуру(РезультатЗапроса,Истина);
Возврат АпиСервисСервер.ПозитивныйОтвет(,СтрРезультат);
КонецФункции
2 Часть. Описание объекта в виде структуры
Надо отправить объект в функцию ПолучитьСтруктуруОбъекта(ссылкаНаобъект,Истина) вернется результат структуры объекта.
Возвращаемый объект буде в формате json (Пример - объект номенклатура из УНФ)
{
"тип": "справочник",
"уид": "0ba5b320-ecf2-11ee-b56d-00155d6fd10d",
"код": "НФ-00000060",
"естьиерархия": true,
"родитель": "",
"этогруппа": false,
"владелец": "",
"метаданные": "Номенклатура",
"пометкаудаления": false,
"артикул": "",
"алкогольнаяпродукция": false,
"вес": 0,
"вариантограничениясертификата": {
"тип": "перечисление",
"наименование": "ВариантыОграниченийСкидокПоНоменклатуре",
"значение": ""
},
"вариантпечатинабора": {
"тип": "перечисление",
"наименование": "ВариантыПечатиНаборов",
"значение": ""
},
"верхняяграницаостатков": 0,
"единицаизмерения": {
"тип": "справочник",
"уид": "6c4c9b97-c52f-11ee-b534-00155d6fd10e",
"код": "796",
"естьиерархия": false,
"родитель": "",
"этогруппа": false,
"владелец": "",
"метаданные": "КлассификаторЕдиницИзмерения",
"пометкаудаления": false
},
"весовой": false,
"видалкогольнойпродукции": {
"тип": "справочник",
"уид": "",
"код": "",
"естьиерархия": false,
"родитель": "",
"этогруппа": false,
"владелец": "",
"метаданные": "ВидыАлкогольнойПродукции",
"пометкаудаления": false
},
"видмаркировки": {
"тип": "перечисление",
"наименование": "ВидыМаркировки",
"значение": "НеМаркируется"
},
"видпродукцииис": {
"тип": "перечисление",
"наименование": "ВидыПродукцииИС",
"значение": ""
},
"автоматическигенерироватьпартии": false,
"выписыватьгарантийныйталон": false,
"высота": 0,
"гарантийныйсрок": 0,
"датаизменения": "17.10.2024 18:43:25",
"датаокончаниядействия": "01.01.0001 0:00:00",
"длина": 0,
"использоватьсерииноменклатуры": false,
"изготовитель": {
"тип": "справочник",
"уид": "",
"код": "",
"естьиерархия": true,
"родитель": "",
"этогруппа": false,
"владелец": "",
"метаданные": "СтруктурныеЕдиницы",
"пометкаудаления": false
},
"импортнаяалкогольнаяпродукция": false,
"исключитьизпрайслистов": false,
"использоватьдатупроизводствапартии": false,
"использоватьзаписьскладскогожурналаветиспартии": false,
"использоватьидентификаторпартииветиспартии": false,
"использоватьномерпартии": false,
"использоватьпартии": false,
"использоватьпроизводителяветиспартии": false,
"наименованиеполное": "наименование",
"использоватьсрокгодностипартии": false,
"использоватьхарактеристики": false,
"категорияноменклатуры": {
"тип": "справочник",
"уид": "e2b4776b-df89-11ee-b55a-00155d6fd10d",
"код": "НФ-000001",
"естьиерархия": true,
"родитель": "",
"этогруппа": false,
"владелец": "",
"метаданные": "КатегорииНоменклатуры",
"пометкаудаления": false
},
"кизгисм": false,
"кизгисмgtin": "",
"кизгисмвид": {
"тип": "перечисление",
"наименование": "ВидыКиЗГИСМ",
"значение": ""
},
"кизгисмразмер": {
"тип": "перечисление",
"наименование": "РазмерыКиЗГИСМ",
"значение": ""
},
"кизгисмспособвыпускавоборот": {
"тип": "перечисление",
"наименование": "СпособыВыпускаВОборотГИСМ",
"значение": ""
},
"кодмедицинскогоизделия": "",
"количествопериодовдействия": 0,
"комментарий": "",
"крепость": 0,
"методоценки": {
"тип": "перечисление",
"наименование": "МетодОценкиЗапасов",
"значение": "ПоСредней"
},
"странапроисхождения": {
"тип": "справочник",
"уид": "",
"код": "",
"естьиерархия": false,
"родитель": "",
"этогруппа": false,
"владелец": "",
"метаданные": "СтраныМира",
"пометкаудаления": false
},
"направлениедеятельности": {
"тип": "справочник",
"уид": "6c4c9b98-c52f-11ee-b534-00155d6fd10e",
"код": "000000001",
"естьиерархия": true,
"родитель": "",
"этогруппа": false,
"владелец": "",
"метаданные": "НаправленияДеятельности",
"пометкаудаления": false
},
"недействителен": false,
"нижняяграницаостатков": 0,
"номинал": 0,
"нормавремени": 0,
"обувнаяпродукция": false,
"объем": 0,
"объемдал": 0,
"периодичность": {
"тип": "перечисление",
"наименование": "Периодичность",
"значение": ""
},
"подконтрольнаяпродукцияветис": false,
"поставщик": {
"тип": "справочник",
"уид": "",
"код": "",
"естьиерархия": true,
"родитель": "",
"этогруппа": false,
"владелец": "",
"метаданные": "Контрагенты",
"пометкаудаления": false
},
"проверятьзаполнениепартий": false,
"проверятьзаполнениехарактеристики": false,
"производитель": {
"тип": "справочник",
"уид": "",
"код": "",
"естьиерархия": true,
"родитель": "",
"этогруппа": false,
"владелец": "",
"метаданные": "Контрагенты",
"пометкаудаления": false
},
"производительимпортералкогольнойпродукции": {
"тип": "справочник",
"уид": "",
"код": "",
"естьиерархия": true,
"родитель": "",
"этогруппа": false,
"владелец": "",
"метаданные": "Контрагенты",
"пометкаудаления": false
},
"произвольныйноминал": false,
"реквизитдопупорядочиванияунф": 0,
"рекомендуемзаказать": false,
"склад": {
"тип": "справочник",
"уид": "46738cf9-c52f-11ee-b534-00155d6fd10e",
"код": "00-000001",
"естьиерархия": true,
"родитель": "",
"этогруппа": false,
"владелец": "",
"метаданные": "СтруктурныеЕдиницы",
"пометкаудаления": false
},
"способограничениясертификата": {
"тип": "перечисление",
"наименование": "СпособыОграниченияПодарочныхСертификатов",
"значение": ""
},
"способпополнения": {
"тип": "перечисление",
"наименование": "СпособыПополненияЗапасов",
"значение": "Закупка"
},
"способрасчетаценынабора": {
"тип": "перечисление",
"наименование": "СпособыРасчетаЦеныНабора",
"значение": ""
},
"средствоиндивидуальнойзащиты": false,
"срокдействияфлагановинка": "01.01.0001 0:00:00",
"срокисполнениязаказа": 1,
"срокпополнения": 0,
"видставкиндс": {
"тип": "перечисление",
"наименование": "ВидыСтавокНДС",
"значение": "БезНДС"
},
"счетучетадоходов": {
"тип": "ПланСчетов",
"Код": "",
"КодБыстрогоВыбора": "",
"Наименование": ""
},
"счетучетазапасов": {
"тип": "ПланСчетов",
"Код": "10 ",
"КодБыстрогоВыбора": "",
"Наименование": "Сырье и материалы"
},
"счетучетазатрат": {
"тип": "ПланСчетов",
"Код": "20 ",
"КодБыстрогоВыбора": "",
"Наименование": "Незавершенное производство"
},
"табачнаяпродукция": false,
"удалитьставкандс": {
"тип": "справочник",
"уид": "",
"код": "",
"естьиерархия": false,
"родитель": "",
"этогруппа": false,
"владелец": "",
"метаданные": "СтавкиНДС",
"пометкаудаления": false
},
"типсрокадействия": {
"тип": "перечисление",
"наименование": "СрокДействияПодарочныхСертификатов",
"значение": "БезОграниченияСрока"
},
"тнвэдгисм": "",
"товарнаяноменклатуравэд": {
"тип": "справочник",
"уид": "",
"код": "",
"естьиерархия": false,
"родитель": "",
"этогруппа": false,
"владелец": "",
"метаданные": "КлассификаторТНВЭД",
"пометкаудаления": false
},
"толькоподдержкаостаткаприрасчетепотребностей": false,
"удалитьспецификация": {
"тип": "справочник",
"уид": "",
"код": "",
"естьиерархия": false,
"родитель": "",
"этогруппа": false,
"владелец": "",
"метаданные": "Спецификации",
"пометкаудаления": false
},
"типноменклатуры": {
"тип": "перечисление",
"наименование": "ТипыНоменклатуры",
"значение": "Запас"
},
"файлкартинки": {
"тип": "справочник",
"уид": "",
"код": "",
"естьиерархия": false,
"родитель": "",
"этогруппа": false,
"владелец": "",
"метаданные": "НоменклатураПрисоединенныеФайлы",
"пометкаудаления": false
},
"фиксированнаястоимость": true,
"ценоваягруппа": {
"тип": "справочник",
"уид": "",
"код": "",
"естьиерархия": true,
"родитель": "",
"этогруппа": false,
"владелец": "",
"метаданные": "ЦеновыеГруппы",
"пометкаудаления": false
},
"частичноепогашение": false,
"шиныипокрышки": false,
"ширина": 0,
"этонабор": false,
"этоновинка": false,
"ячейка": {
"тип": "справочник",
"уид": "",
"код": "",
"естьиерархия": true,
"родитель": "",
"этогруппа": false,
"владелец": "",
"метаданные": "Ячейки",
"пометкаудаления": false
},
"подакцизныйтовар": false,
"политикаучетасерий": {
"тип": "справочник",
"уид": "",
"код": "",
"естьиерархия": false,
"родитель": "",
"этогруппа": false,
"владелец": "",
"метаданные": "ПолитикаУчетаСерий",
"пометкаудаления": false
},
"индивидуальныенастройкиполитикиучетасерий": false,
"использоватьсрокгодностисерии": false,
"использоватьдатупроизводствасерии": false,
"точностьуказаниясрокагодностисерии": {
"тип": "перечисление",
"наименование": "ТочностиУказанияСрокаГодности",
"значение": ""
},
"использоватьуникальныесерии": false,
"этоагентскаяуслуга": false,
"договор": {
"тип": "справочник",
"уид": "",
"код": "",
"естьиерархия": true,
"родитель": "",
"этогруппа": false,
"владелец": "",
"метаданные": "ДоговорыКонтрагентов",
"пометкаудаления": false
},
"срокгодности": 0,
"единицаизмерениясрокагодности": {
"тип": "перечисление",
"наименование": "ЕдиницыИзмеренияВремени",
"значение": ""
},
"прослеживаемыйтовар": false,
"веспосертификатутовара": 0,
"кодокпд2": "",
"наборединицизмерения": {
"тип": "справочник",
"уид": "",
"код": "",
"естьиерархия": false,
"родитель": "",
"этогруппа": false,
"владелец": "",
"метаданные": "НаборыЕдиницИзмерения",
"пометкаудаления": false
},
"использоватьнаборыединицизмерения": false,
"единицадляотчетов": {
"тип": "справочник",
"уид": "",
"код": "",
"естьиерархия": false,
"родитель": "",
"этогруппа": false,
"владелец": "",
"метаданные": "ЕдиницыИзмерения",
"пометкаудаления": false
},
"коэффициентединицыдляотчетов": 1,
"штрихкод": "",
"кодтру": "",
"прослеживаемыйкомплект": false,
"признакпредметарасчета": {
"тип": "перечисление",
"наименование": "ПризнакиПредметаРасчета",
"значение": "Товар"
},
"характеристикацен": {
"тип": "справочник",
"уид": "",
"код": "",
"естьиерархия": false,
"родитель": "",
"этогруппа": false,
"владелец": "",
"метаданные": "ХарактеристикиНоменклатуры",
"пометкаудаления": false
},
"запретитьвводдробногоколичества": false,
"счетучетандспоприобретеннымценностям": {
"тип": "ПланСчетов",
"Код": "19 ",
"КодБыстрогоВыбора": "",
"Наименование": "НДС по приобретенным ценностям"
},
"счетучетандспореализации": {
"тип": "ПланСчетов",
"Код": "90.03 ",
"КодБыстрогоВыбора": "",
"Наименование": "Налог на добавленную стоимость"
},
"продаетсяврозлив": false,
"единицадляценников": {
"тип": "справочник",
"уид": "",
"код": "",
"естьиерархия": false,
"родитель": "",
"этогруппа": false,
"владелец": "",
"метаданные": "КлассификаторЕдиницИзмерения",
"пометкаудаления": false
},
"числитель": 0,
"знаменатель": 0,
"видподакцизноготовара": {
"тип": "перечисление",
"наименование": "ВидыПодакцизныхТоваров",
"значение": ""
},
"кодвидаподакцизноготовара": {
"тип": "справочник",
"уид": "",
"код": "",
"естьиерархия": false,
"родитель": "",
"этогруппа": false,
"владелец": "",
"метаданные": "КодыВидовПодакцизныхТоваров",
"пометкаудаления": false
},
"единицаизмерениядлярасчетаакциза": {
"тип": "справочник",
"уид": "",
"код": "",
"естьиерархия": false,
"родитель": "",
"этогруппа": false,
"владелец": "",
"метаданные": "КлассификаторЕдиницИзмерения",
"пометкаудаления": false
},
"счетучетаакцизапоимпорту": {
"тип": "ПланСчетов",
"Код": "",
"КодБыстрогоВыбора": "",
"Наименование": ""
},
"коэффициентпересчета": 0,
"ДополнительныеРеквизиты": [],
"НоменклатураГруппыЦеновыеГруппы": []
}
Как использовать.
Скачать, добавить общий модуль, скопировать текст.
Модуль локализован, поэтому можно добавлять в чистую базу.
Если будут проблемы, пишите.
Тестировалась и работает на версии платформе 1С:Предприятие 8.3 (8.3.23.1912) на самописной конфигурации.