Initial project import
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
# Development oracle for additional requisites
|
||||
|
||||
`additional_attributes_readonly.bsl` is server-side BSL intended only for the
|
||||
isolated `upo_test` development configuration. It is an oracle for comparing
|
||||
the platform result with the SQL adapter result; it is never a dependency of
|
||||
the adapter, including in `upo_test`. It does not write application data or
|
||||
configuration metadata. `additional_attributes_http_handler.bsl` is an
|
||||
optional URL-template handler for manual development checks.
|
||||
|
||||
The service must expose two authenticated read-only operations:
|
||||
|
||||
- `additional_attributes.find` → `НайтиДополнительныеРеквизиты`;
|
||||
- `additional_attributes.storage.resolve` → `МаршрутЗначенийДополнительногоРеквизита`.
|
||||
|
||||
The HTTP wrapper must accept/return JSON and restrict calls to the test
|
||||
network. It must pass only `query`, `include_deleted`, a property UUID, and
|
||||
the public owner selector. Do not accept arbitrary BSL or query text.
|
||||
|
||||
Use the result only to create SQL adapter fixtures and verify its semantic
|
||||
mapping. The adapter itself must not call this endpoint, read its URL, or
|
||||
depend on a 1C runtime connection. A missing physical source in `upo_test`
|
||||
must therefore produce explicit SQL diagnostics, never a platform fallback.
|
||||
|
||||
Before publishing:
|
||||
|
||||
1. Add both modules to a test-only extension or HTTP service in Designer and
|
||||
bind `ОбработатьRPC` to `POST /rpc`.
|
||||
2. Restrict the service to read-only calls and test-network access.
|
||||
3. Create or identify a non-deleted test property `Ответственное направление`.
|
||||
4. Verify that the service returns its UUID, formula identifier, property set,
|
||||
and value type; then verify the storage-route response for
|
||||
`Справочник.СтруктурныеЕдиницы`.
|
||||
@@ -0,0 +1,60 @@
|
||||
// Обработчик URL-шаблона HTTP-сервиса, например POST /runtime-bridge/rpc.
|
||||
// Требует общий серверный модуль ДополнительныеРеквизитыReadOnly
|
||||
// (additional_attributes_readonly.bsl) в составе тестового расширения.
|
||||
|
||||
Функция ОбработатьRPC(Запрос) Экспорт
|
||||
Попытка
|
||||
ДанныеЗапроса = ПрочитатьJSONИзСтроки(Запрос.ПолучитьТелоКакСтроку());
|
||||
Метод = ДанныеЗапроса.method;
|
||||
Параметры = ДанныеЗапроса.payload;
|
||||
Если Метод = "additional_attributes.find" Тогда
|
||||
ТекстПоиска = ПолучитьПараметр(Параметры, "query", "");
|
||||
ВключатьУдаленные = ПолучитьПараметр(Параметры, "include_deleted", Ложь);
|
||||
Результат = Новый Структура("status,properties", "found", ДополнительныеРеквизитыReadOnly.НайтиДополнительныеРеквизиты(ТекстПоиска, ВключатьУдаленные));
|
||||
Если Результат.properties.Количество() = 0 Тогда
|
||||
Результат.status = "not_found";
|
||||
КонецЕсли;
|
||||
ИначеЕсли Метод = "additional_attributes.storage.resolve" Тогда
|
||||
СсылкаСвойства = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.ПолучитьСсылку(Новый УникальныйИдентификатор(Параметры.property_ref));
|
||||
Маршрут = ДополнительныеРеквизитыReadOnly.МаршрутЗначенийДополнительногоРеквизита(СсылкаСвойства, Параметры.owner_ref);
|
||||
Результат = Новый Структура("status,property_ref,owner_ref,storage,scd_join", "confirmed", Параметры.property_ref, Параметры.owner_ref,
|
||||
Новый Структура("source_ref,source_kind,fields", Маршрут.source, "TabularSection", Новый Структура("object,property,value", Маршрут.object_field, Маршрут.property_field, Маршрут.value_field)),
|
||||
Новый Структура("source,alias,condition,value_expression,parameters", Маршрут.source, "ДополнительныеРеквизиты", Маршрут.query_join, "ДополнительныеРеквизиты.Значение", Новый Структура("Свойство", Маршрут.parameter)));
|
||||
Иначе
|
||||
Возврат ОтветJSON(405, Новый Структура("status,error", "invalid_argument", "Unsupported read-only bridge method."));
|
||||
КонецЕсли;
|
||||
Возврат ОтветJSON(200, Результат);
|
||||
Исключение
|
||||
// Не передаем внутренний стек и сведения о подключении.
|
||||
Возврат ОтветJSON(400, Новый Структура("status,error", "error", "Invalid read-only bridge request."));
|
||||
КонецПопытки;
|
||||
КонецФункции
|
||||
|
||||
Функция ПолучитьПараметр(СтруктураПараметров, Имя, ЗначениеПоУмолчанию) Экспорт
|
||||
Значение = ЗначениеПоУмолчанию;
|
||||
Если СтруктураПараметров.Свойство(Имя, Значение) Тогда
|
||||
Возврат Значение;
|
||||
КонецЕсли;
|
||||
Возврат ЗначениеПоУмолчанию;
|
||||
КонецФункции
|
||||
|
||||
Функция ПрочитатьJSONИзСтроки(ТекстJSON) Экспорт
|
||||
ЧтениеJSON = Новый ЧтениеJSON;
|
||||
ЧтениеJSON.УстановитьСтроку(ТекстJSON);
|
||||
Попытка
|
||||
Возврат ПрочитатьJSON(ЧтениеJSON);
|
||||
Наконец
|
||||
ЧтениеJSON.Закрыть();
|
||||
КонецПопытки;
|
||||
КонецФункции
|
||||
|
||||
Функция ОтветJSON(КодСостояния, Данные) Экспорт
|
||||
ЗаписьJSON = Новый ЗаписьJSON;
|
||||
ЗаписьJSON.УстановитьСтроку();
|
||||
ЗаписатьJSON(ЗаписьJSON, Данные);
|
||||
ТекстJSON = ЗаписьJSON.Закрыть();
|
||||
Ответ = Новый HTTPСервисОтвет(КодСостояния);
|
||||
Ответ.УстановитьТелоИзСтроки(ТекстJSON, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);
|
||||
Ответ.Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");
|
||||
Возврат Ответ;
|
||||
КонецФункции
|
||||
@@ -0,0 +1,85 @@
|
||||
// Общий модуль серверного HTTP-сервиса. Все экспортные методы только читают данные.
|
||||
// Модуль предназначен для публикации в тестовой конфигурации, а не для выполнения
|
||||
// из SQL-адаптера. Аутентификацию и разбор HTTP-запроса реализует модуль сервиса.
|
||||
|
||||
Функция НайтиДополнительныеРеквизиты(ТекстПоиска = "", ВключатьПомеченныеНаУдаление = Ложь) Экспорт
|
||||
|
||||
Результат = Новый Массив;
|
||||
Выборка = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.Выбрать();
|
||||
Пока Выборка.Следующий() Цикл
|
||||
Если Не ВключатьПомеченныеНаУдаление И Выборка.ПометкаУдаления Тогда
|
||||
Продолжить;
|
||||
КонецЕсли;
|
||||
Если ЗначениеЗаполнено(ТекстПоиска)
|
||||
И СтрНайти(НРег(Выборка.Наименование), НРег(ТекстПоиска)) = 0 Тогда
|
||||
Продолжить;
|
||||
КонецЕсли;
|
||||
|
||||
ОбъектСвойства = Выборка.ПолучитьОбъект();
|
||||
СтрокаСвойства = Новый Структура;
|
||||
СтрокаСвойства.Вставить("ref", Строка(Выборка.Ссылка.УникальныйИдентификатор()));
|
||||
СтрокаСвойства.Вставить("description", Выборка.Наименование);
|
||||
СтрокаСвойства.Вставить("marked_for_deletion", Выборка.ПометкаУдаления);
|
||||
ДобавитьСвойствоЕслиЕсть(СтрокаСвойства, ОбъектСвойства, "Имя", "name");
|
||||
ДобавитьСвойствоЕслиЕсть(СтрокаСвойства, ОбъектСвойства, "ИдентификаторДляФормул", "identifier_for_formula");
|
||||
ДобавитьСвойствоЕслиЕсть(СтрокаСвойства, ОбъектСвойства, "НаборСвойств", "property_set");
|
||||
ДобавитьСвойствоЕслиЕсть(СтрокаСвойства, ОбъектСвойства, "ТипЗначения", "value_type");
|
||||
// Отдельно фиксируем наличие реквизита в объекте ПВХ. Это позволяет
|
||||
// SQL-разработке отличить пустое значение от отсутствующей семантики.
|
||||
СтрокаСвойства.Вставить("semantic_fields", Новый Структура(
|
||||
"name,identifier_for_formula,property_set,value_type",
|
||||
СтрокаСвойства.Свойство("name"),
|
||||
СтрокаСвойства.Свойство("identifier_for_formula"),
|
||||
СтрокаСвойства.Свойство("property_set"),
|
||||
СтрокаСвойства.Свойство("value_type")));
|
||||
Результат.Добавить(СтрокаСвойства);
|
||||
КонецЦикла;
|
||||
|
||||
Возврат Результат;
|
||||
КонецФункции
|
||||
|
||||
Функция МаршрутЗначенийДополнительногоРеквизита(Свойство, ВладелецМетаданных) Экспорт
|
||||
|
||||
Если ТипЗнч(Свойство) <> Тип("ПланВидовХарактеристикСсылка.ДополнительныеРеквизитыИСведения") Тогда
|
||||
ВызватьИсключение "Свойство должно быть ссылкой ПВХ ДополнительныеРеквизитыИСведения.";
|
||||
КонецЕсли;
|
||||
Если ВладелецМетаданных <> "Справочник.СтруктурныеЕдиницы" Тогда
|
||||
ВызватьИсключение "Маршрут подтвержден только для Справочник.СтруктурныеЕдиницы.";
|
||||
КонецЕсли;
|
||||
|
||||
// Текст предназначен для СКД и не исполняется сервисом. В этой
|
||||
// конфигурации значения подтверждённо находятся в табличной части владельца.
|
||||
Возврат Новый Структура(
|
||||
"source,object_field,property_field,value_field,query_join,parameter",
|
||||
"Справочник.СтруктурныеЕдиницы.ДополнительныеРеквизиты",
|
||||
"Ссылка",
|
||||
"Свойство",
|
||||
"Значение",
|
||||
"ЛЕВОЕ СОЕДИНЕНИЕ Справочник.СтруктурныеЕдиницы.ДополнительныеРеквизиты КАК ДополнительныеРеквизиты "
|
||||
+ "ПО ДополнительныеРеквизиты.Ссылка = СтруктурныеЕдиницы.Ссылка "
|
||||
+ "И ДополнительныеРеквизиты.Свойство = &Свойство",
|
||||
Строка(Свойство.УникальныйИдентификатор())
|
||||
);
|
||||
КонецФункции
|
||||
|
||||
Процедура ДобавитьСвойствоЕслиЕсть(Приемник, Источник, ИмяСвойства, ИмяПоля) Экспорт
|
||||
ЗначениеСвойства = Неопределено;
|
||||
Если Источник.Свойство(ИмяСвойства, ЗначениеСвойства) Тогда
|
||||
Приемник.Вставить(ИмяПоля, ПредставлениеДляJSON(ЗначениеСвойства));
|
||||
КонецЕсли;
|
||||
КонецПроцедуры
|
||||
|
||||
Функция ПредставлениеДляJSON(ЗначениеСвойства) Экспорт
|
||||
Если ЗначениеСвойства = Неопределено Тогда
|
||||
Возврат Неопределено;
|
||||
КонецЕсли;
|
||||
Если ТипЗнч(ЗначениеСвойства) = Тип("Структура") Или ТипЗнч(ЗначениеСвойства) = Тип("Массив") Тогда
|
||||
Возврат ЗначениеСвойства;
|
||||
КонецЕсли;
|
||||
Попытка
|
||||
УникальныйИдентификатор = ЗначениеСвойства.УникальныйИдентификатор();
|
||||
Возврат Новый Структура("ref,presentation", Строка(УникальныйИдентификатор), Строка(ЗначениеСвойства));
|
||||
Исключение
|
||||
КонецПопытки;
|
||||
Возврат Строка(ЗначениеСвойства);
|
||||
КонецФункции
|
||||
Reference in New Issue
Block a user