Решил пощупать мобильный клиент и рассказать, что и как прошло, но подумал, что чисто про мобильный клиент будет неинтересно рассказывать, поэтому придумал небольшую задачку для демонстрации вышеописанной связки.
Задача: На основе разработки //infostart.ru/public/811834/ создать маленькую конфигурацию с таким же функционалом, которая будет подключаться к другим конфигурациям посредством http сервиса, который будет встраиваться посредством расширения конфигураций. В http сервисах будет описано два метода. Первый должен собирать метаданные и передавать в управляющую конфигурацию, второй должен передавать массив выбранных элементов и делать их доступными по стандартному интерфейсу OData.
Для решения использовано следующее программное обеспечение:
Платформы 8.3.10.2650 и 8.3.12.1412, Мобильная платформа 8.3.12.46, телефон на android 7.0, IIS 6 и 7, (Android Studio 3.1.1 это было необязательно, но хотелось попробовать вариант с установкой мобильной платформы на телефон через USB из конфигуратора)
1 Создаем расширение в любой конфигурации от 8.3.10, так как необходима возможность создания http сервиса и модуля. (Хотя такой функционал был и в 8.3.9, но так как конфигурации были под 8.3.8, а потом сразу 8.3.10 я считаю 8.3.9 "мертвым релизом", таким же как и 8.3.11...)
-Создаем http сервис MC_HTTPMob с UrlШаблоном -> /V1/{ВхДанные}
-Создаем http сервис с методом get (PingMe) код обработчика:
Функция MobClientHTTPPingMe(Запрос)
перВхИмя = Запрос.ПараметрыURL["ВхДанные"];
Ответочка = ?(перВхИмя = "ПроверкаПодключения","Все ОК!","Все ОК! Вы написали "+перВхИмя);
Ответ = Новый HTTPСервисОтвет(200);
Ответ.УстановитьТелоИзСтроки(Ответочка,КодировкаТекста.UTF8);
Ответ.Заголовки.Вставить("Content-Type","text/html; charset=utf-8");
Возврат Ответ;
КонецФункции
-Создаем http сервис с методом post (POST_Servis) код обработчика:
Функция MobClientHTTPPOST_Servis(Запрос)
перИмяМетода = Запрос.ПараметрыURL["ВхДанные"];
ЗапросОтКлиентаJSON = Запрос.ПолучитьТелоКакСтроку();
СтруктураОтвет = MC_МодульHTTPMob.ОбработкаВходящихДанныхHTTP_Сервиса(ЗапросОтКлиентаJSON,перИмяМетода);
Ответ = Новый HTTPСервисОтвет(СтруктураОтвет.КодОтвета);
Если СтруктураОтвет.Отработало Тогда
Ответ.УстановитьТелоИзСтроки(СтруктураОтвет.ДанныеОтвета,КодировкаТекста.UTF8);
Иначе
Ответ.УстановитьТелоИзСтроки(СтруктураОтвет.ТекстОшибки,КодировкаТекста.UTF8);
КонецЕсли;
Ответ.Заголовки.Вставить("Content-Type","text/html; charset=utf-8");
Возврат Ответ;
КонецФункции
-Создаем модуль MC_МодульHTTPMob который содержит следующий код
Функция ОбработкаВходящихДанныхHTTP_Сервиса(ЗапросОтКлиентаJSON,перИмяМетода) Экспорт
СтруктураОтвет = Новый Структура("ДанныеОтвета,Отработало,ТекстОшибки,КодОтвета","",Истина,"",200);
Если ВРег(перИмяМетода) = ВРег("GiveAllMetadate") Тогда
ОтдайМетаданныеOData(СтруктураОтвет,ЗапросОтКлиентаJSON);
ИначеЕсли ВРег(перИмяМетода) = ВРег("GoodMetadate") Тогда
ОткройМетаданныеODate(СтруктураОтвет,ЗапросОтКлиентаJSON);
Иначе
СтруктураОтвет.КодОтвета = 400;
СтруктураОтвет.ТекстОшибки = "Unknown method!!!";
СтруктураОтвет.Отработало = Ложь;
СтруктураОтвет.ДанныеОтвета = "";
КонецЕсли;
Возврат СтруктураОтвет;
КонецФункции
Процедура ОтдайМетаданныеOData(СтруктураОтвет,ЗапросОтКлиентаJSON)
СписокОбъектовOdata = ПолучитьСписокОбъектовOData();
УстановитьПривилегированныйРежим(Истина);
СоставСтандартногоИнтерфейсаOData = ПолучитьСоставСтандартногоИнтерфейсаOData();
РезультатОтвет = Новый Массив;
Для Каждого СтрокаСпискаОбъектов Из СписокОбъектовOdata Цикл
Состояние = Истина;
ПрефиксИмениURL = ?(ПустаяСтрока(СтрокаСпискаОбъектов.Представление),"",СтрокаСпискаОбъектов.Представление);
ИмяЗначение = СтрокаСпискаОбъектов.Значение;
МассивДанногоТипа = Новый Массив;
Для Каждого ОбъектМетаданных Из Метаданные[ИмяЗначение] Цикл
НайденOData = СоставСтандартногоИнтерфейсаOData.Найти(ОбъектМетаданных) <> Неопределено;
МассивДанногоТипа.Добавить(Новый Структура("Имя,Синоним,ПрефиксИмениURL,Состояние",
ОбъектМетаданных.Имя,
ОбъектМетаданных.ПолноеИмя(),
?(ПустаяСтрока(ПрефиксИмениURL),"",ПрефиксИмениURL+"_"+ОбъектМетаданных.Имя),
НайденOData));
Если не НайденOData и Состояние Тогда
Состояние = Ложь;
КонецЕсли;
КонецЦикла;
РезультатОтвет.Добавить(Новый Структура("ИмяЗначение,ПрефиксИмениURL,Состояние,МассивДанногоТипа",
СтрокаСпискаОбъектов.Значение,
ПрефиксИмениURL,
Состояние,
МассивДанногоТипа));
КонецЦикла;
УстановитьПривилегированныйРежим(Ложь);
//Все нормально
ПараметрыJSON = Новый ПараметрыЗаписиJSON(ПереносСтрокJSON.Нет, " " , Истина, ЭкранированиеСимволовJSON.Нет, Ложь, Ложь, Ложь, Ложь);
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.ПроверятьСтруктуру = Истина;
ЗаписьJSON.УстановитьСтроку(ПараметрыJSON);
ЗаписатьJSON(ЗаписьJSON, РезультатОтвет);
СтрокаJSON = ЗаписьJSON.Закрыть();
ЗаполнитьСтруктуруОтвета(СтруктураОтвет,200,"",Истина,СтрокаJSON);
КонецПроцедуры
Процедура ОткройМетаданныеODate(СтруктураОтвет,ЗапросОтКлиентаJSON)
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.УстановитьСтроку(ЗапросОтКлиентаJSON);
Попытка
ДопДанные = ПрочитатьJSON(ЧтениеJSON);
Исключение
ЗаполнитьСтруктуруОтвета(СтруктураОтвет,406,"Не удалось получить данные!",Ложь,"X");
Возврат;
КонецПопытки;
Если ТипЗнч(ДопДанные) = Тип("Массив") Тогда
УстановитьПривилегированныйРежим(Истина);
Попытка
УстановитьСоставСтандартногоИнтерфейсаOData(ДопДанные);
Исключение
ЗаполнитьСтруктуруОтвета(СтруктураОтвет,406,ОписаниеОшибки(),Ложь,"X");
Возврат;
КонецПопытки;
Иначе
ЗаполнитьСтруктуруОтвета(СтруктураОтвет,406,"Передан не массив!",Ложь,"X");
Возврат;
КонецЕсли;
ЗаполнитьСтруктуруОтвета(СтруктураОтвет,200,"",Истина,"ОК!");
КонецПроцедуры
Функция ПолучитьСписокОбъектовOData()
СписокОбъектовOdata = Новый СписокЗначений;
СписокОбъектовOdata.Добавить("Справочники", "Catalog");
СписокОбъектовOdata.Добавить("Документы", "Document");
СписокОбъектовOdata.Добавить("ЖурналыДокументов", "DocumentJournal");
СписокОбъектовOdata.Добавить("Константы", "Constant");
СписокОбъектовOdata.Добавить("ПланыОбмена", "ExchangePlan");
СписокОбъектовOdata.Добавить("ПланыСчетов", "ChartOfAccounts");
СписокОбъектовOdata.Добавить("ПланыВидовРасчета", "ChartOfCalculationTypes");
СписокОбъектовOdata.Добавить("ПланыВидовХарактеристик", "ChartOfCharacteristicTypes");
СписокОбъектовOdata.Добавить("РегистрыСведений", "InformationRegister");
СписокОбъектовOdata.Добавить("РегистрыНакопления", "AccumulationRegister");
СписокОбъектовOdata.Добавить("РегистрыРасчета", "CalculationRegister");
СписокОбъектовOdata.Добавить("РегистрыБухгалтерии", "AccountingRegister");
СписокОбъектовOdata.Добавить("БизнесПроцессы", "BusinessProcess");
СписокОбъектовOdata.Добавить("Задачи", "Task");
СписокОбъектовOdata.Добавить("Перечисления", "");
Возврат СписокОбъектовOdata;
КонецФункции
Процедура ЗаполнитьСтруктуруОтвета(СтруктураОтвет,КодОтвета,ТекстОшибки,Отработало,ДанныеОтвета)
СтруктураОтвет.КодОтвета = КодОтвета;
СтруктураОтвет.ТекстОшибки = ТекстОшибки;
СтруктураОтвет.Отработало = Отработало;
СтруктураОтвет.ДанныеОтвета = ДанныеОтвета;
КонецПроцедуры
-Помещаем данное расширение в нужные нам конфигурации и публикуем на вэб сервере.
Незабываем сделать публикацию с учетом OData и расширения!!!
После проверяем через браузер, опубликовалось или нет.
В моем случае http://127.0.0.1/DemoRetail22723/hs/MC_HTTPMob/V1/Привет
2 Создаем Управляющую конфигурацию
-Создаем справочник для хранения настроек подключений к другим конфигурациям
Реквизит НастройкиПодключения я сделал с типом ХранилищеЗначения.
На форму добавил кнопку с подключением к get методу PingMe
-Добавляем в конфигурацию обработку (//infostart.ru/public/811834/) и переделываем ее под такой вид:
-ПриОткрытии я использовал новую директиву МобильныйКлиент (глава на ИТС 26.5.2. Подготовка конфигурации для работы в мобильном клиенте)
#Если не МобильныйКлиент Тогда
Элементы.СписокМетаданныхГруппаФлажки.Отображение = ОтображениеГруппыКнопок.Компактное;
Элементы.СписокМетаданныхГруппаВсернутьРазвернуть.Отображение = ОтображениеГруппыКнопок.Компактное;
Элементы.СписокМетаданныхПрефиксИмениURL.Видимость = Истина;
Элементы.Система.ПодсказкаВвода = "";
НеМобильныйШрифт = Новый Шрифт(Элементы.СписокМетаданныхЗаписатьИзменения.Шрифт,,12,истина);
Элементы.СписокМетаданныхЗаписатьИзменения.Шрифт = НеМобильныйШрифт;
#Иначе
Элементы.СписокМетаданныхВыбран.Заголовок = "Выбрать";
Элементы.СписокМетаданныхСпасибо.Видимость = Ложь;
#КонецЕсли
-Прописываем действие команды ЗагрузитьМетаданныеСистемы
&НаКлиенте
Процедура ЗагрузитьМетаданныеСистемы(Команда)
Если Не ЗначениеЗаполнено(Система) Тогда
Возврат;
КонецЕсли;
ЗагрузитьМетаданныеСистемыНаСервере();
КонецПроцедуры
&НаСервере
Процедура ЗагрузитьМетаданныеСистемыНаСервере()
СтруктураПараметры = Система.НастройкиПодключения.Получить();
Если ТипЗнч(СтруктураПараметры) = Тип("Структура") Тогда
Если СтруктураПараметры.Свойство("БлокНастройкиПодключенияHTTP") Тогда
СтрБлокНастройкиПодключенияHTTP = СтруктураПараметры.БлокНастройкиПодключенияHTTP;
Если СтрБлокНастройкиПодключенияHTTP.Свойство("HTTPСервер") Тогда
Сервер = СтрБлокНастройкиПодключенияHTTP.HTTPСервер;
КонецЕсли;
Если СтрБлокНастройкиПодключенияHTTP.Свойство("HTTPПорт") Тогда
Порт = СтрБлокНастройкиПодключенияHTTP.HTTPПорт;
КонецЕсли;
Если СтрБлокНастройкиПодключенияHTTP.Свойство("HTTPРесурсНаСервере") Тогда
РесурсНаСервере = СтрБлокНастройкиПодключенияHTTP.HTTPРесурсНаСервере;
КонецЕсли;
Если СтрБлокНастройкиПодключенияHTTP.Свойство("HTTPПользователь") Тогда
Пользователь = СтрБлокНастройкиПодключенияHTTP.HTTPПользователь;
КонецЕсли;
Если СтрБлокНастройкиПодключенияHTTP.Свойство("HTTPПароль") Тогда
Пароль = СтрБлокНастройкиПодключенияHTTP.HTTPПароль;
КонецЕсли;
КонецЕсли;
КонецЕсли;
Если ПустаяСтрока(Сервер) Тогда
Сообщить("Не заполнен ""Сервер""!");
Возврат;
Иначе
перСервер = Сервер;
КонецЕсли;
Если ПустаяСтрока(РесурсНаСервере) Тогда
Сообщить("Не заполнен ""Ресурс на сервере""!");
Возврат;
Иначе
перРесурсНаСервере = РесурсНаСервере;
КонецЕсли;
перПользователь = Пользователь;
перПароль = Пароль;
Если Порт > 0 Тогда
перПорт = Порт;
Иначе
перПорт = 0;
КонецЕсли;
ИмяМетода = "GiveAllMetadate";
перРесурсНаСервере = ?(Лев(перРесурсНаСервере,1)<>"/","/","") + перРесурсНаСервере + ?(Прав(перРесурсНаСервере,1)<>"/","/","") + ИмяМетода;
Попытка
Если перПорт <= 0 Тогда
HTTPСоединение = Новый HTTPСоединение(перСервер,,перПользователь,перПароль);
Иначе
HTTPСоединение = Новый HTTPСоединение(перСервер,перПорт,перПользователь,перПароль);
КонецЕсли;
HTTPЗапрос = Новый HTTPЗапрос(перРесурсНаСервере);
HTTPЗапрос.УстановитьТелоИзСтроки("");
HTTPОтвет = HTTPСоединение.ОтправитьДляОбработки(HTTPЗапрос);
//Получаем ответный массив или текст ошибки
Ответочка = HTTPОтвет.ПолучитьТелоКакСтроку(КодировкаТекста.UTF8);
Исключение
Сообщить("Подключение не прошло по причине "+ОписаниеОшибки());
//Подчищаем соединение
HTTPСоединение = Неопределено;
Возврат;
КонецПопытки;
//Подчищаем соединение
HTTPСоединение = Неопределено;
Если HTTPОтвет.КодСостояния <> 200 Тогда
Сообщить(Строка(Ответочка));
Иначе
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.УстановитьСтроку(Ответочка);
Попытка
ДопДанные = ПрочитатьJSON(ЧтениеJSON);
Исключение
Сообщить("Неудалось получить данные!");
Возврат;
КонецПопытки;
КонецЕсли;
перСписокМетаданных = РеквизитФормыВЗначение("СписокМетаданных");
перСписокМетаданных.Строки.Очистить();
Если ТипЗнч(ДопДанные) = Тип("Массив") Тогда
Для Каждого СтрокаМассива из ДопДанные Цикл
Если ТипЗнч(СтрокаМассива) = Тип("Структура") Тогда
ВерхнийУровеньДерева = перСписокМетаданных.Строки.Добавить();
ВерхнийУровеньДерева.Выбран = ?(СтрокаМассива.Свойство("Состояние"),СтрокаМассива.Состояние,Ложь);
ВерхнийУровеньДерева.Состояние = ВерхнийУровеньДерева.Выбран;
ВерхнийУровеньДерева.Имя = ?(СтрокаМассива.Свойство("ИмяЗначение"),СтрокаМассива.ИмяЗначение,"");
ВерхнийУровеньДерева.Синоним = ВерхнийУровеньДерева.Имя;
ВерхнийУровеньДерева.ПрефиксИмениURL= ?(СтрокаМассива.Свойство("ПрефиксИмениURL"),СтрокаМассива.ПрефиксИмениURL,"");
Если СтрокаМассива.Свойство("МассивДанногоТипа") Тогда
Если ТипЗнч(СтрокаМассива.МассивДанногоТипа) = Тип("Массив") Тогда
Для Каждого ОбъектМетаданных Из СтрокаМассива.МассивДанногоТипа Цикл
Если ТипЗнч(ОбъектМетаданных) = Тип("Структура") Тогда
ПодчиненныйУровеньДерева = ВерхнийУровеньДерева.Строки.Добавить();
ПодчиненныйУровеньДерева.Имя = ?(ОбъектМетаданных.Свойство("Имя"),ОбъектМетаданных.Имя,"");
ПодчиненныйУровеньДерева.Синоним = ?(ОбъектМетаданных.Свойство("Синоним"),ОбъектМетаданных.Синоним,"");
ПодчиненныйУровеньДерева.ПрефиксИмениURL= ?(ОбъектМетаданных.Свойство("ПрефиксИмениURL"),ОбъектМетаданных.ПрефиксИмениURL,"");
ПодчиненныйУровеньДерева.Состояние = ?(ОбъектМетаданных.Свойство("Состояние"),ОбъектМетаданных.Состояние,Ложь);
ПодчиненныйУровеньДерева.Выбран = ПодчиненныйУровеньДерева.Состояние;
Иначе
Сообщить("Элемент массива не является структурой!")
КонецЕсли
КонецЦикла;
Иначе
Сообщить("МассивДанногоТипа не массив!")
КонецЕсли;
Иначе
Сообщить("Отсутствует ""МассивДанногоТипа""!")
КонецЕсли
Иначе
Сообщить("Элемент массива не является структурой!")
КонецЕсли
КонецЦикла;
Иначе
Сообщить("Вернулся не массив!")
КонецЕсли;
ЗначениеВРеквизитФормы(перСписокМетаданных, "СписокМетаданных");
Модифицированность = Ложь;
КонецПроцедуры
-Описываем действие команды ЗаписатьИзменения
&НаКлиенте
Процедура ЗаписатьИзменения(Команда)
ЗаписатьИзмененияНаСервере();
КонецПроцедуры
&НаСервере
Процедура ЗаписатьИзмененияНаСервере()
СоставСтандартногоИнтерфейсаOData = Новый Массив;
перСписокМетаданных = РеквизитФормыВЗначение("СписокМетаданных");
//Проверим ниже модифицировано или нет
Модифицированность = Ложь;
Для Каждого ВерхнийУровеньДерева Из перСписокМетаданных.Строки Цикл
Для Каждого ПодчиненныйУровеньДерева Из ВерхнийУровеньДерева.Строки Цикл
Если ПодчиненныйУровеньДерева.Выбран Тогда
СоставСтандартногоИнтерфейсаOData.Добавить(ПодчиненныйУровеньДерева.Синоним);
КонецЕсли;
//Может ничего и не меняли
Если ПодчиненныйУровеньДерева.Выбран<>ПодчиненныйУровеньДерева.Состояние И не Модифицированность Тогда
Модифицированность = Истина;
КонецЕсли;
КонецЦикла;
КонецЦикла;
//Если меняли записываем
Если Модифицированность Тогда
СтруктураПараметры = Система.НастройкиПодключения.Получить();
Если ТипЗнч(СтруктураПараметры) = Тип("Структура") Тогда
Если СтруктураПараметры.Свойство("БлокНастройкиПодключенияHTTP") Тогда
СтрБлокНастройкиПодключенияHTTP = СтруктураПараметры.БлокНастройкиПодключенияHTTP;
Если СтрБлокНастройкиПодключенияHTTP.Свойство("HTTPСервер") Тогда
Сервер = СтрБлокНастройкиПодключенияHTTP.HTTPСервер;
КонецЕсли;
Если СтрБлокНастройкиПодключенияHTTP.Свойство("HTTPПорт") Тогда
Порт = СтрБлокНастройкиПодключенияHTTP.HTTPПорт;
КонецЕсли;
Если СтрБлокНастройкиПодключенияHTTP.Свойство("HTTPРесурсНаСервере") Тогда
РесурсНаСервере = СтрБлокНастройкиПодключенияHTTP.HTTPРесурсНаСервере;
КонецЕсли;
Если СтрБлокНастройкиПодключенияHTTP.Свойство("HTTPПользователь") Тогда
Пользователь = СтрБлокНастройкиПодключенияHTTP.HTTPПользователь;
КонецЕсли;
Если СтрБлокНастройкиПодключенияHTTP.Свойство("HTTPПароль") Тогда
Пароль = СтрБлокНастройкиПодключенияHTTP.HTTPПароль;
КонецЕсли;
КонецЕсли;
КонецЕсли;
Если ПустаяСтрока(Сервер) Тогда
Сообщить("Не заполнен ""Сервер""!");
Возврат;
Иначе
перСервер = Сервер;
КонецЕсли;
Если ПустаяСтрока(РесурсНаСервере) Тогда
Сообщить("Не заполнен ""Ресурс на сервере""!");
Возврат;
Иначе
перРесурсНаСервере = РесурсНаСервере;
КонецЕсли;
перПользователь = Пользователь;
перПароль = Пароль;
Если Порт > 0 Тогда
перПорт = Порт;
Иначе
перПорт = 0;
КонецЕсли;
ИмяМетода = "GoodMetadate";
перРесурсНаСервере = ?(Лев(перРесурсНаСервере,1)<>"/","/","") + перРесурсНаСервере + ?(Прав(перРесурсНаСервере,1)<>"/","/","") + ИмяМетода;
Попытка
Если перПорт <= 0 Тогда
HTTPСоединение = Новый HTTPСоединение(перСервер,,перПользователь,перПароль);
Иначе
HTTPСоединение = Новый HTTPСоединение(перСервер,перПорт,перПользователь,перПароль);
КонецЕсли;
ПараметрыJSON = Новый ПараметрыЗаписиJSON(ПереносСтрокJSON.Нет, " " , Истина, ЭкранированиеСимволовJSON.Нет, Ложь, Ложь, Ложь, Ложь);
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.ПроверятьСтруктуру = Истина;
ЗаписьJSON.УстановитьСтроку(ПараметрыJSON);
ЗаписатьJSON(ЗаписьJSON, СоставСтандартногоИнтерфейсаOData);
СтрокаJSON = ЗаписьJSON.Закрыть();
HTTPЗапрос = Новый HTTPЗапрос(перРесурсНаСервере);
HTTPЗапрос.УстановитьТелоИзСтроки(СтрокаJSON);
HTTPОтвет = HTTPСоединение.ОтправитьДляОбработки(HTTPЗапрос);
//Получаем ответный массив или текст ошибки
Ответочка = HTTPОтвет.ПолучитьТелоКакСтроку(КодировкаТекста.UTF8);
Исключение
Сообщить("Подключение не прошло по причине "+ОписаниеОшибки());
//Подчищаем соединение
HTTPСоединение = Неопределено;
Возврат;
КонецПопытки;
//Подчищаем соединение
HTTPСоединение = Неопределено;
Если HTTPОтвет.КодСостояния <> 200 Тогда
Сообщить(Строка(Ответочка));
Иначе
Модифицированность = Ложь;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
3 Проверяем в тонком клиенте
4 Публикуем и устанавливаем мобильную платформу на телефон.
Есть два способа, простой и сложный.
Простой: В настройках телефона в меню безопасность включаем Неизвестные источники и скачиваем мобильную платформу и закидываем ее на телефон.
Сложный способ: Качаем и устанавливаем Android Studio 3.1.1 (https://developer.android.com/studio/index.html) и качаем мобильную платформу.
-На телефоне включаем отладку по USB (чаще всего в меню разработчика) и включаем Неизвестные источники.
-В конфигураторе прописываем путь к SDK и мобильной платформе, ставим галочку Использование Android debug bridge.
-подключаем телефон по usb и в конфигураторе: Главное меню \ Конфигурация \Мобильный клиент\ Использование Android debug bridge \ Установить мобильный клиент.
Более подробно описано на ИТС в главе 26.6.2. Установка инструментов разработчика.
5 Тестируем Мобильный клиент
Открываем мобильную платформу и добавляем нашу конфигурацию
У меня так:
Выкладываю Расширение конфигурации, его можно встроить в любую конфигурацию с поддержкой 8.3.10 и выше и выкладываю Управляющую конфигурацию.