//////////////////////////////////////////////////////////////////////////////// // HTTPService bfd_IntegrationAPI — read-only REST API для bit-flight-deck. // // Корневой URL (RootURL) — bfd-api // После публикации: http:////hs/bfd-api/v1/... // // Все методы GET. Аутентификация Basic (пользователь bfd_api_user). // Ошибки → JSON {"error":"..."} с HTTP-кодом 500. // Все ID объектов сериализуются как строковый UUID без префикса класса. //////////////////////////////////////////////////////////////////////////////// #Область ОбработчикиЗапросов // GET /v1/health // Функция HealthGet(Запрос) Экспорт Ответ = Новый Структура; Ответ.Вставить("status", "ok"); Ответ.Вставить("service", "bfd_IntegrationAPI"); Ответ.Вставить("server_time", Формат(ТекущаяДатаСеанса(), "ДФ=yyyy-MM-ddTHH:mm:ss")); Возврат bfd_IntegrationAPIHelpers.СформироватьОтветJSON(Ответ); КонецФункции // GET /v1/employees // // Email берётся одним запросом через РегистрСведений.КонтактнаяИнформация БСП // (подзапрос с ПЕРВЫЕ 1 — если у пользователя несколько email-адресов, берём первый). // Функция EmployeesGet(Запрос) Экспорт Попытка Запрос1С = Новый Запрос; Запрос1С.УстановитьПараметр("ТипEmail", Перечисления.ТипыКонтактнойИнформации.АдресЭлектроннойПочты); Запрос1С.Текст = "ВЫБРАТЬ | Пользователи.Ссылка КАК Ссылка, | Пользователи.Наименование КАК ФИО, | Пользователи.EVA_ID КАК EvaID, | Пользователи.Офис КАК Офис, | Пользователи.Подразделение КАК Подразделение, | Пользователи.Ставка КАК Ставка, | Пользователи.Недействителен КАК Недействителен, | Пользователи.ДолженЗаполнятьОтчет КАК ДолженЗаполнятьОтчет, | МАКСИМУМ(КИ.Представление) КАК Email |ИЗ | Справочник.Пользователи КАК Пользователи | ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.КонтактнаяИнформация КАК КИ | ПО КИ.Объект = Пользователи.Ссылка | И КИ.Тип = &ТипEmail |ГДЕ | НЕ Пользователи.ПометкаУдаления |СГРУППИРОВАТЬ ПО | Пользователи.Ссылка, | Пользователи.Наименование, | Пользователи.EVA_ID, | Пользователи.Офис, | Пользователи.Подразделение, | Пользователи.Ставка, | Пользователи.Недействителен, | Пользователи.ДолженЗаполнятьОтчет |УПОРЯДОЧИТЬ ПО | Пользователи.Наименование"; Выборка = Запрос1С.Выполнить().Выбрать(); Результат = Новый Массив; Пока Выборка.Следующий() Цикл Запись = Новый Структура; Запись.Вставить("id", bfd_IntegrationAPIHelpers.UUID(Выборка.Ссылка)); Запись.Вставить("full_name", Выборка.ФИО); Запись.Вставить("email", НРег(?(Выборка.Email = Null, "", Строка(Выборка.Email)))); Запись.Вставить("eva_id", Выборка.EvaID); Запись.Вставить("office", Строка(Выборка.Офис)); Запись.Вставить("department", Строка(Выборка.Подразделение)); Запись.Вставить("rate", Выборка.Ставка); Запись.Вставить("is_active", НЕ Выборка.Недействителен); Запись.Вставить("should_fill_report", Выборка.ДолженЗаполнятьОтчет); Результат.Добавить(Запись); КонецЦикла; Возврат bfd_IntegrationAPIHelpers.СформироватьОтветJSON(Результат); Исключение Возврат bfd_IntegrationAPIHelpers.СформироватьОтветОшибки(ОписаниеОшибки()); КонецПопытки; КонецФункции // GET /v1/works?modified_since=&limit=N // Функция WorksGet(Запрос) Экспорт Попытка МодифицированоПосле = bfd_IntegrationAPIHelpers.ПарсДатуISO(Запрос.ПараметрыЗапроса.Получить("modified_since")); Лимит = bfd_IntegrationAPIHelpers.ПарсЛимит(Запрос, 1000, 10000); Запрос1С = Новый Запрос; Запрос1С.УстановитьПараметр("МодифицированоПосле", МодифицированоПосле); Запрос1С.Текст = "ВЫБРАТЬ ПЕРВЫЕ " + Формат(Лимит, "ЧГ=") + " | ДокРаботы.Ссылка КАК Ссылка, | ДокРаботы.Номер КАК Номер, | ДокРаботы.Дата КАК Дата, | ДокРаботы.Исполнитель КАК Исполнитель, | ДокРаботы.Автор КАК Автор, | ДокРаботы.Подразделение КАК Подразделение, | ДокРаботы.Офис КАК Офис, | ДокРаботы.Утвержден КАК Утвержден, | ДокРаботы.Комментарий КАК Комментарий, | ДокРаботы.ИтогоЧасов КАК ИтогоЧасов |ИЗ | Документ.Работы КАК ДокРаботы |ГДЕ | ДокРаботы.Дата >= &МодифицированоПосле | И ДокРаботы.Проведен |УПОРЯДОЧИТЬ ПО | ДокРаботы.Дата УБЫВ"; Выборка = Запрос1С.Выполнить().Выбрать(); Результат = Новый Массив; Пока Выборка.Следующий() Цикл Запись = Новый Структура; Запись.Вставить("id", bfd_IntegrationAPIHelpers.UUID(Выборка.Ссылка)); Запись.Вставить("number", Выборка.Номер); Запись.Вставить("date", Формат(Выборка.Дата, "ДФ=yyyy-MM-ddTHH:mm:ss")); Запись.Вставить("employee_id", bfd_IntegrationAPIHelpers.UUID(Выборка.Исполнитель)); Запись.Вставить("author_id", bfd_IntegrationAPIHelpers.UUID(Выборка.Автор)); Запись.Вставить("department", Строка(Выборка.Подразделение)); Запись.Вставить("office", Строка(Выборка.Офис)); Запись.Вставить("approved", Выборка.Утвержден); Запись.Вставить("comment", Выборка.Комментарий); Запись.Вставить("total_hours", Выборка.ИтогоЧасов); Запись.Вставить("rows", ПолучитьСтрокиРаботы(Выборка.Ссылка)); Результат.Добавить(Запись); КонецЦикла; Возврат bfd_IntegrationAPIHelpers.СформироватьОтветJSON(Результат); Исключение Возврат bfd_IntegrationAPIHelpers.СформироватьОтветОшибки(ОписаниеОшибки()); КонецПопытки; КонецФункции // GET /v1/projects // Функция ProjectsGet(Запрос) Экспорт Попытка Запрос1С = Новый Запрос; Запрос1С.Текст = "ВЫБРАТЬ | Проекты.Ссылка КАК Ссылка, | Проекты.Код КАК Код, | Проекты.Наименование КАК Наименование, | Проекты.EVA_ID КАК EvaID, | Проекты.Кодификатор КАК Кодификатор, | Проекты.Клиент КАК Клиент, | Проекты.Клиент.Наименование КАК КлиентИмя, | Проекты.Договор КАК Договор, | Проекты.Конфигурация КАК Конфигурация, | Проекты.Офис КАК Офис, | Проекты.РуководительПроекта КАК РуководительПроекта, | Проекты.МенеджерПроекта КАК МенеджерПроекта, | Проекты.СтатусПроекта КАК СтатусПроекта, | Проекты.СтатусДоговора КАК СтатусДоговора, | Проекты.ДатаСтарта КАК ДатаСтарта, | Проекты.ДатаФиниш КАК ДатаФиниш, | Проекты.Бюджет КАК Бюджет, | Проекты.ПометкаУдаления КАК ПометкаУдаления |ИЗ | Справочник.Проекты КАК Проекты"; Выборка = Запрос1С.Выполнить().Выбрать(); Результат = Новый Массив; Пока Выборка.Следующий() Цикл Запись = Новый Структура; Запись.Вставить("id", bfd_IntegrationAPIHelpers.UUID(Выборка.Ссылка)); Запись.Вставить("code", Выборка.Код); Запись.Вставить("name", Выборка.Наименование); Запись.Вставить("eva_id", Выборка.EvaID); Запись.Вставить("project_code", Выборка.Кодификатор); Запись.Вставить("client_id", bfd_IntegrationAPIHelpers.UUID(Выборка.Клиент)); Запись.Вставить("client_name", Выборка.КлиентИмя); Запись.Вставить("contract_id", bfd_IntegrationAPIHelpers.UUID(Выборка.Договор)); Запись.Вставить("configuration", Строка(Выборка.Конфигурация)); Запись.Вставить("office", Строка(Выборка.Офис)); Запись.Вставить("manager_id", bfd_IntegrationAPIHelpers.UUID(Выборка.РуководительПроекта)); Запись.Вставить("project_manager_id", bfd_IntegrationAPIHelpers.UUID(Выборка.МенеджерПроекта)); Запись.Вставить("status", Строка(Выборка.СтатусПроекта)); Запись.Вставить("contract_status", Строка(Выборка.СтатусДоговора)); Запись.Вставить("start_date", ?(ЗначениеЗаполнено(Выборка.ДатаСтарта), Формат(Выборка.ДатаСтарта, "ДФ=yyyy-MM-dd"), "")); Запись.Вставить("finish_date", ?(ЗначениеЗаполнено(Выборка.ДатаФиниш), Формат(Выборка.ДатаФиниш, "ДФ=yyyy-MM-dd"), "")); Запись.Вставить("budget", Выборка.Бюджет); Запись.Вставить("deleted", Выборка.ПометкаУдаления); Результат.Добавить(Запись); КонецЦикла; Возврат bfd_IntegrationAPIHelpers.СформироватьОтветJSON(Результат); Исключение Возврат bfd_IntegrationAPIHelpers.СформироватьОтветОшибки(ОписаниеОшибки()); КонецПопытки; КонецФункции // GET /v1/stages // // Catalog.ЭтапыПроектов — подчинённый справочник, Владелец = Catalog.Проекты // (стандартный реквизит, через Subordination ToItems). // Функция StagesGet(Запрос) Экспорт Попытка Запрос1С = Новый Запрос; Запрос1С.Текст = "ВЫБРАТЬ | ЭтапыПроектов.Ссылка КАК Ссылка, | ЭтапыПроектов.Код КАК Код, | ЭтапыПроектов.Наименование КАК Наименование, | ЭтапыПроектов.Владелец КАК Проект, | ЭтапыПроектов.Родитель КАК Родитель, | ЭтапыПроектов.ЭтоГруппа КАК ЭтоГруппа, | ЭтапыПроектов.Кодификатор КАК Кодификатор, | ЭтапыПроектов.ДатаНачала КАК ДатаНачала, | ЭтапыПроектов.ДатаОкончания КАК ДатаОкончания, | ЭтапыПроектов.Выполнен КАК Выполнен, | ЭтапыПроектов.АктПодписан КАК АктПодписан, | ЭтапыПроектов.ПометкаУдаления КАК ПометкаУдаления |ИЗ | Справочник.ЭтапыПроектов КАК ЭтапыПроектов"; Выборка = Запрос1С.Выполнить().Выбрать(); Результат = Новый Массив; Пока Выборка.Следующий() Цикл Запись = Новый Структура; Запись.Вставить("id", bfd_IntegrationAPIHelpers.UUID(Выборка.Ссылка)); Запись.Вставить("code", Выборка.Код); Запись.Вставить("name", Выборка.Наименование); Запись.Вставить("project_id", bfd_IntegrationAPIHelpers.UUID(Выборка.Проект)); Запись.Вставить("parent_id", bfd_IntegrationAPIHelpers.UUID(Выборка.Родитель)); Запись.Вставить("is_folder", Выборка.ЭтоГруппа); Запись.Вставить("codifier", Выборка.Кодификатор); Запись.Вставить("start_date", ?(ЗначениеЗаполнено(Выборка.ДатаНачала), Формат(Выборка.ДатаНачала, "ДФ=yyyy-MM-dd"), "")); Запись.Вставить("end_date", ?(ЗначениеЗаполнено(Выборка.ДатаОкончания), Формат(Выборка.ДатаОкончания, "ДФ=yyyy-MM-dd"), "")); Запись.Вставить("completed", Выборка.Выполнен); Запись.Вставить("act_signed", Выборка.АктПодписан); Запись.Вставить("deleted", Выборка.ПометкаУдаления); Результат.Добавить(Запись); КонецЦикла; Возврат bfd_IntegrationAPIHelpers.СформироватьОтветJSON(Результат); Исключение Возврат bfd_IntegrationAPIHelpers.СформироватьОтветОшибки(ОписаниеОшибки()); КонецПопытки; КонецФункции // GET /v1/work_types // Функция WorkTypesGet(Запрос) Экспорт Попытка Результат = Новый Массив; МетаОбъект = Метаданные.Перечисления.ВидыРабот; Для Каждого ЗначениеМД Из МетаОбъект.ЗначенияПеречисления Цикл Запись = Новый Структура; Запись.Вставить("code", ЗначениеМД.Имя); Запись.Вставить("label", ЗначениеМД.Синоним); Результат.Добавить(Запись); КонецЦикла; Возврат bfd_IntegrationAPIHelpers.СформироватьОтветJSON(Результат); Исключение Возврат bfd_IntegrationAPIHelpers.СформироватьОтветОшибки(ОписаниеОшибки()); КонецПопытки; КонецФункции // GET /v1/dictionaries // Функция DictionariesGet(Запрос) Экспорт Попытка Ответ = Новый Структура; Ответ.Вставить("offices", ПростойСправочник("Офис")); Ответ.Вставить("departments", ПростойСправочник("Подразделение")); Ответ.Вставить("managers", ПростойСправочник("Менеджеры")); Ответ.Вставить("configurations", ПростойСправочник("Конфигурации")); Ответ.Вставить("contracts", ПростойСправочник("Договоры")); Ответ.Вставить("planning_scenarios", ПростойСправочник("СценарииПланирования")); Возврат bfd_IntegrationAPIHelpers.СформироватьОтветJSON(Ответ); Исключение Возврат bfd_IntegrationAPIHelpers.СформироватьОтветОшибки(ОписаниеОшибки()); КонецПопытки; КонецФункции // GET /v1/dept_history?modified_since= // Функция DeptHistoryGet(Запрос) Экспорт Попытка МодифицированоПосле = bfd_IntegrationAPIHelpers.ПарсДатуISO(Запрос.ПараметрыЗапроса.Получить("modified_since")); Запрос1С = Новый Запрос; Запрос1С.УстановитьПараметр("МодифицированоПосле", МодифицированоПосле); Запрос1С.Текст = "ВЫБРАТЬ | ИсторияПодразделений.Период КАК Период, | ИсторияПодразделений.Сотрудник КАК Сотрудник, | ИсторияПодразделений.Подразделение КАК Подразделение |ИЗ | РегистрСведений.ПодразделениеСотрудников КАК ИсторияПодразделений |ГДЕ | ИсторияПодразделений.Период >= &МодифицированоПосле"; Выборка = Запрос1С.Выполнить().Выбрать(); Результат = Новый Массив; Пока Выборка.Следующий() Цикл Запись = Новый Структура; Запись.Вставить("period", Формат(Выборка.Период, "ДФ=yyyy-MM-dd")); Запись.Вставить("employee_id", bfd_IntegrationAPIHelpers.UUID(Выборка.Сотрудник)); Запись.Вставить("department_id", bfd_IntegrationAPIHelpers.UUID(Выборка.Подразделение)); Запись.Вставить("department_name", Строка(Выборка.Подразделение)); Результат.Добавить(Запись); КонецЦикла; Возврат bfd_IntegrationAPIHelpers.СформироватьОтветJSON(Результат); Исключение Возврат bfd_IntegrationAPIHelpers.СформироватьОтветОшибки(ОписаниеОшибки()); КонецПопытки; КонецФункции // GET /v1/project_register?modified_since= // Для MVP-3, на старте можно не использовать. // Функция ProjectRegisterGet(Запрос) Экспорт Попытка МодифицированоПосле = bfd_IntegrationAPIHelpers.ПарсДатуISO(Запрос.ПараметрыЗапроса.Получить("modified_since")); Запрос1С = Новый Запрос; Запрос1С.УстановитьПараметр("МодифицированоПосле", МодифицированоПосле); Запрос1С.Текст = "ВЫБРАТЬ | Регистр.Период КАК Период, | Регистр.Регистратор КАК Регистратор, | Регистр.Сценарий КАК Сценарий, | Регистр.Проект КАК Проект, | Регистр.ЭтапПроекта КАК ЭтапПроекта, | Регистр.ВидАналитики КАК ВидАналитики, | Регистр.Исполнитель КАК Исполнитель, | Регистр.Сумма КАК Сумма, | Регистр.СуммаАкт КАК СуммаАкт, | Регистр.СуммаРасход КАК СуммаРасход |ИЗ | РегистрНакопления.ОборотыПроектныхПоказателей_v2 КАК Регистр |ГДЕ | Регистр.Период >= &МодифицированоПосле"; Выборка = Запрос1С.Выполнить().Выбрать(); Результат = Новый Массив; Пока Выборка.Следующий() Цикл Запись = Новый Структура; Запись.Вставить("period", Формат(Выборка.Период, "ДФ=yyyy-MM-ddTHH:mm:ss")); Запись.Вставить("registrator_id", bfd_IntegrationAPIHelpers.UUID(Выборка.Регистратор)); Запись.Вставить("scenario", Строка(Выборка.Сценарий)); Запись.Вставить("project_id", bfd_IntegrationAPIHelpers.UUID(Выборка.Проект)); Запись.Вставить("stage_id", bfd_IntegrationAPIHelpers.UUID(Выборка.ЭтапПроекта)); Запись.Вставить("analytics_type", Строка(Выборка.ВидАналитики)); Запись.Вставить("employee_id", bfd_IntegrationAPIHelpers.UUID(Выборка.Исполнитель)); Запись.Вставить("sum_total", Выборка.Сумма); Запись.Вставить("sum_acted", Выборка.СуммаАкт); Запись.Вставить("sum_expense", Выборка.СуммаРасход); Результат.Добавить(Запись); КонецЦикла; Возврат bfd_IntegrationAPIHelpers.СформироватьОтветJSON(Результат); Исключение Возврат bfd_IntegrationAPIHelpers.СформироватьОтветОшибки(ОписаниеОшибки()); КонецПопытки; КонецФункции // GET /v1/eva_mapping/projects // Функция EvaMappingProjectsGet(Запрос) Экспорт Возврат ОтдатьРегистрМаппинга("СоответствиеПроектовEVA_РА"); КонецФункции // GET /v1/eva_mapping/clients // Функция EvaMappingClientsGet(Запрос) Экспорт Возврат ОтдатьРегистрМаппинга("СоответствиеКонтрагентовEVA_РА"); КонецФункции #КонецОбласти #Область СлужебныеПроцедурыИФункции // Возвращает массив строк ТЧ "Работы" документа. // Функция ПолучитьСтрокиРаботы(Знач ДокументСсылка) Объект = ДокументСсылка.ПолучитьОбъект(); Если Объект = Неопределено Тогда Возврат Новый Массив; КонецЕсли; Строки = Новый Массив; Для Каждого Стр Из Объект.Работы Цикл Запись = Новый Структура; Запись.Вставить("row_index", Стр.НомерСтроки); Запись.Вставить("description", Стр.СодержаниеРабот); Запись.Вставить("hours", Стр.КоличествоЧасов); Запись.Вставить("work_type", Строка(Стр.ВидРаботы)); Запись.Вставить("work_type_code", ?(ЗначениеЗаполнено(Стр.ВидРаботы), XMLСтрока(Стр.ВидРаботы), "")); Запись.Вставить("client_id", bfd_IntegrationAPIHelpers.UUID(Стр.Клиент)); Запись.Вставить("client_name", Строка(Стр.Клиент)); Запись.Вставить("manager_id", bfd_IntegrationAPIHelpers.UUID(Стр.Менеджер)); Запись.Вставить("project_id", bfd_IntegrationAPIHelpers.UUID(Стр.Проект)); Запись.Вставить("stage_id", bfd_IntegrationAPIHelpers.UUID(Стр.Этап)); Запись.Вставить("request_number", Стр.НомерЗаявки); Запись.Вставить("lt_id", bfd_IntegrationAPIHelpers.UUID(Стр.ЛТ)); Запись.Вставить("work_done", Стр.РаботаВыполнена); Строки.Добавить(Запись); КонецЦикла; Возврат Строки; КонецФункции // Возвращает простой плоский справочник как массив объектов {id, code, name}. // Функция ПростойСправочник(Знач ИмяСправочника) Запрос1С = Новый Запрос; Запрос1С.Текст = "ВЫБРАТЬ | Спр.Ссылка КАК Ссылка, | Спр.Код КАК Код, | Спр.Наименование КАК Наименование |ИЗ | Справочник." + ИмяСправочника + " КАК Спр |ГДЕ | НЕ Спр.ПометкаУдаления"; Выборка = Запрос1С.Выполнить().Выбрать(); Результат = Новый Массив; Пока Выборка.Следующий() Цикл Запись = Новый Структура; Запись.Вставить("id", bfd_IntegrationAPIHelpers.UUID(Выборка.Ссылка)); Запись.Вставить("code", Выборка.Код); Запись.Вставить("name", Выборка.Наименование); Результат.Добавить(Запись); КонецЦикла; Возврат Результат; КонецФункции // Универсальный helper для регистров маппинга EVA_РА. // Перебирает колонки регистра, ссылки сериализует UUID, даты ISO. // Функция ОтдатьРегистрМаппинга(Знач ИмяРегистра) Попытка Запрос1С = Новый Запрос; Запрос1С.Текст = "ВЫБРАТЬ * ИЗ РегистрСведений." + ИмяРегистра; ТЗ = Запрос1С.Выполнить().Выгрузить(); Результат = Новый Массив; Для Каждого Стр Из ТЗ Цикл Запись = Новый Структура; Для Каждого Колонка Из ТЗ.Колонки Цикл Значение = Стр[Колонка.Имя]; Если ТипЗнч(Значение) = Тип("Дата") Тогда Запись.Вставить(Колонка.Имя, Формат(Значение, "ДФ=yyyy-MM-ddTHH:mm:ss")); ИначеЕсли ТипЗнч(Значение) = Тип("Булево") ИЛИ ТипЗнч(Значение) = Тип("Число") ИЛИ ТипЗнч(Значение) = Тип("Строка") Тогда Запись.Вставить(Колонка.Имя, Значение); Иначе Запись.Вставить(Колонка.Имя, ?(ЗначениеЗаполнено(Значение), bfd_IntegrationAPIHelpers.UUID(Значение), "")); КонецЕсли; КонецЦикла; Результат.Добавить(Запись); КонецЦикла; Возврат bfd_IntegrationAPIHelpers.СформироватьОтветJSON(Результат); Исключение Возврат bfd_IntegrationAPIHelpers.СформироватьОтветОшибки(ОписаниеОшибки()); КонецПопытки; КонецФункции #КонецОбласти