phase-3: replace CFE with main-config patch (per user request)

User decided to patch the main BIT.RA configuration instead of installing an extension.
- bitra-cfe/ removed in previous step
- bitra-patch/ added with BSL files for direct copy-paste into Configurator:
  - CommonModules/bfd_IntegrationAPIHelpers/Module.bsl (134 lines) — privileged server helpers
  - HTTPServices/bfd_IntegrationAPI/Module.bsl (478 lines) — 11 GET handlers
- README.md (274 lines): step-by-step Configurator instructions:
  - object properties (CommonModule flags, HTTPService rootURL, URL templates, methods)
  - role permissions matrix (15 BIT.RA objects + HTTPService + CommonModule)
  - user bfd_api_user creation
  - Apache publication
  - curl tests for each endpoint
This commit is contained in:
Roman Chesnokov
2026-05-14 19:42:48 +05:00
parent 7da9d9dae1
commit f70bbf53f3
9 changed files with 287 additions and 669 deletions
@@ -0,0 +1,134 @@
////////////////////////////////////////////////////////////////////////////////
// Общий модуль bfd_IntegrationAPIHelpers
//
// Назначение: вспомогательные процедуры/функции для HTTP-сервиса bfd_IntegrationAPI
// (read-only REST API для проекта bit-flight-deck).
//
// Свойства модуля (выставить в Конфигураторе):
// Сервер = Истина
// Вызов сервера = Истина
// Внешнее соединение = Истина (для всякого случая)
// Привилегированный = Истина (важно — позволяет читать всё в обход RLS)
////////////////////////////////////////////////////////////////////////////////
#Область ПрограммныйИнтерфейс
// Формирует HTTPСервисОтвет с JSON-телом.
// Параметры:
// Данные — Произвольный (Структура / Массив / Число / Строка / Дата / Булево / Неопределено)
// Код — Число (по умолчанию 200)
// Возвращаемое значение: HTTPСервисОтвет
//
Функция СформироватьОтветJSON(Знач Данные, Знач Код = 200) Экспорт
ЗаписьJSON = Новый ЗаписьJSON;
ПараметрыJSON = Новый ПараметрыЗаписиJSON(ПереносСтрокJSON.БезПереносов, "", Ложь, "yyyy-MM-ddTHH:mm:ss");
ЗаписьJSON.УстановитьСтроку(ПараметрыJSON);
ЗаписатьJSON(ЗаписьJSON, Данные);
Ответ = Новый HTTPСервисОтвет(Код);
Ответ.Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");
Ответ.УстановитьТелоИзСтроки(ЗаписьJSON.Закрыть(), КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);
Возврат Ответ;
КонецФункции
// Сериализованная ошибка.
//
Функция СформироватьОтветОшибки(Знач СообщениеОшибки, Знач Код = 500) Экспорт
Структура = Новый Структура("error", СообщениеОшибки);
Возврат СформироватьОтветJSON(Структура, Код);
КонецФункции
// Парсит ISO 8601 дату из строки query-параметра.
// Возвращает Дату или '00010101' при ошибке/пусто.
//
Функция ПарсДатуISO(Знач СтрокаДаты) Экспорт
Если ПустаяСтрока(СтрокаДаты) Тогда
Возврат Дата(1, 1, 1);
КонецЕсли;
ОчищеннаяСтрока = СтрЗаменить(СтрЗаменить(СтрокаДаты, "T", " "), "Z", "");
Попытка
Возврат Дата(ОчищеннаяСтрока);
Исключение
Возврат Дата(1, 1, 1);
КонецПопытки;
КонецФункции
// Строковое представление GUID ссылки или пустая строка.
//
Функция UUID(Знач Ссылка) Экспорт
Если НЕ ЗначениеЗаполнено(Ссылка) Тогда
Возврат "";
КонецЕсли;
Возврат Строка(Ссылка.УникальныйИдентификатор());
КонецФункции
// Извлекает email из ТЧ КонтактнаяИнформация пользователя.
//
Функция ИзвлечьEmail(Знач Пользователь) Экспорт
Если НЕ ЗначениеЗаполнено(Пользователь) Тогда
Возврат "";
КонецЕсли;
Попытка
Объект = Пользователь.ПолучитьОбъект();
Исключение
Возврат "";
КонецПопытки;
Если Объект = Неопределено Тогда
Возврат "";
КонецЕсли;
Попытка
Для Каждого Стр Из Объект.КонтактнаяИнформация Цикл
ВидНаименование = "";
Если ЗначениеЗаполнено(Стр.Вид) Тогда
ВидНаименование = Строка(Стр.Вид);
КонецЕсли;
Если СтрНайти(НРег(ВидНаименование), "email") > 0 ИЛИ СтрНайти(НРег(ВидНаименование), "почта") > 0 Тогда
Если ЗначениеЗаполнено(Стр.Представление) Тогда
Возврат Стр.Представление;
КонецЕсли;
КонецЕсли;
КонецЦикла;
Исключение
Возврат "";
КонецПопытки;
Возврат "";
КонецФункции
// Лимит выборки из query-параметра.
//
Функция ПарсЛимит(Знач Запрос, Знач MaxDefault = 1000, Знач MaxAllowed = 10000) Экспорт
Параметр = Запрос.ПараметрыЗапроса.Получить("limit");
Если ПустаяСтрока(Параметр) Тогда
Возврат MaxDefault;
КонецЕсли;
Попытка
Значение = Число(Параметр);
Исключение
Возврат MaxDefault;
КонецПопытки;
Если Значение <= 0 Тогда
Возврат MaxDefault;
КонецЕсли;
Возврат Мин(Значение, MaxAllowed);
КонецФункции
#КонецОбласти