# Эндпоинты, с которыми взаимодействует pm-frontend

Документ описывает все HTTP-эндпоинты внешних сервисов, к которым обращается модуль (микрофронтенд `pm-frontend`).

## Как устроено взаимодействие

Все REST-запросы идут через единый `httpService` (`src/services/api/http-service.ts`, поверх `@sarex-team/sdk-js` + axios). API-модули объявлены декларативно в `src/store/api/*` и `src/services/api/*` и вызывают `httpService.<method>Request({ service, url, data?, axiosConfig?, errorMessage? })`, где:

- `service` — логическое имя сервиса (см. таблицу хостов ниже);
- `url` — путь запроса (обычно уже включает свой префикс, напр. `/api/pm/msp/...`);
- `data` — тело запроса; `errorMessage` — сообщение при ошибке.

Базовый хост подставляется SDK-функцией `resolveHost(service)` по значению `hosts[ENDPOINT].hosts[service]` из `src/services/api/hosts.ts`. Итоговый URL = `<базовый хост сервиса>` + `url`. Прямых вызовов `axios.*`/`fetch()` в `src/` нет.

Выбор окружения — сборочная переменная `process.env.ENDPOINT` (инъектируется webpack через `DefinePlugin`). Допустимые значения: `local`, `stage`, `prod`, `preprod`, `contour`; значение по умолчанию — `prod`. Для `local`/`stage` dev-сервер webpack (`configWebpack/buildDevServer.ts`) проксирует относительные префиксы (`/sarex-backend`, `/pm`, `/sarex-eav-v1`, `/sarex-gateway`, `/sarex-api` …) на stage-бэкенды.

## Базовые хосты по сервисам и окружениям

Значения из `src/services/api/hosts.ts`. Для сервиса `sarex` в удалённых окружениях хост пустой (`""`) — запросы идут относительно текущего origin (маршрутизируются ingress/gateway перед SPA).

| Сервис (`service`) | Назначение | `stage` | `prod` |
| --- | --- | --- | --- |
| `sarex` | Монолит / PM REST (`/api/pm/...`, `/api/core/...`) | `""` (same-origin) | `""` (same-origin) |
| `pm` | PM-микросервис (`/api/v1/...`: интегрированные задачи, комментарии) | `https://stage-api.sarex.io/pm` | `https://api.sarex.io/pm` |
| `sarexApi` | API-шлюз для flows (reviews, документы, процессы) | `https://stage-api.sarex.io` | `https://api.sarex.io` |
| `eavV1` | Сервис атрибутов EAV (`/api/v2`, `/api/v4`) | `https://stage-api.sarex.io/eav` | `https://api.sarex.io/eav` |
| `gateway` | Шлюз ресурсов (`/api/v1/resources`) | `https://stage-api.sarex.io/gateway` | `https://api.sarex.io/gateway` |
| `notifications` | Лямбда уведомлений | `https://stage-api.sarex.io/lambdas/notification` | `https://api.sarex.io/lambdas/notification` |
| `bimv2` | BIM v2 | `https://stage-api.sarex.io/bimv2` | `https://api.sarex.io/bimv2` |
| `bim` | BIM v1 | `https://stage-api.sarex.io/bim` | `https://api.sarex.io/bim` |
| `analyticsV2` | Аналитика v2 | `https://stage-api.sarex.io/analytics-v2` | `https://api.sarex.io/analytics-v2` |
| `workspaces` | Сервис рабочих областей | `https://stage-api.sarex.io/workspaces` | `https://api.sarex.io/workspaces` |
| `documentations` | Сервис документаций | `https://stage-api.sarex.io/documentations` | `https://api.sarex.io/documentations` |
| `workflows` | Сервис обработки документов | `https://stage-api.sarex.io/workflows` | `https://api.sarex.io/workflows` |
| `comparisons` | Сервис сравнений | `https://stage-api.sarex.io/comparisons` | `https://api.sarex.io/comparisons` |
| `remarks` | Сервис замечаний | `https://stage-api.sarex.io/remarks` | `https://api.sarex.io/remarks` |
| `projects` | Сервис проектов | `https://stage-api.sarex.io/projects` | `https://api.sarex.io/projects` |
| `zitadel` | IdP (аутентификация) | `https://idp.dev.stage.sarex.io` | `https://login.sarex.io` |
| `google` | Временное хранилище (GCS) | `https://storage.googleapis.com/srx-tmp` | `https://storage.googleapis.com/srx-tmp` |

> Также определены окружения `local` (относительные прокси-префиксы) и `preprod`/`contour`. Реально используются в коде только `sarex`, `pm`, `sarexApi`, `eavV1`, `gateway`; остальные сервисы объявлены в hosts, но REST-вызовов к ним в этом модуле нет. Кроме REST есть WebSocket (`src/store/stores/gantt/ganttWebsocket.ts`): `io(`${url}/project`, { path: "/message-hub/socket.io" })`, где `url` — `https://stage-api.sarex.io` (stage) / `https://api.sarex.io` (prod).

## Эндпоинты по модулям

### `store/api/api.ts` — ProjectsAPI (сервис `sarex`, если не указано иное)

| Ключ | Метод | Путь | Назначение |
| --- | --- | --- | --- |
| `getFolderById` | GET | `/api/pm/msp/folders/{folderId}` | Папка по id |
| `getProjectsAndFolders` | GET | `/api/pm/msp/projects/?{query}` | Список проектов и папок |
| `getProjectTemplates` | GET | `/api/pm/msp/projects/?{query}` | Список шаблонов проектов |
| `getAllProjects` | GET | `/api/pm/msp/projects/` | Все проекты |
| `getAllProjectsWithNotFolders` | GET | `/api/pm/msp/projects/?schema=tiny&is_folder=false&company_id={companyId}` | Проекты (без папок) по компании |
| `getProject` | GET | `/api/pm/msp/projects/{projectId}/?extend=true` | Проект (расширенный) |
| `getKeyMilestones` | GET | `/api/pm/msp/projects/{projectId}/key_milestones/` | Ключевые вехи проекта |
| `getResourcePlanning` | GET | `/api/pm/msp/resources/resource_planning/?projects={projects}&start={start}&end={end}&resource_type=human&scale={scale}` | Ресурсное планирование |
| `changeResourceForTask` | PATCH | `/api/pm/msp/resources-tasks/assign/` | Назначить ресурс на задачу |
| `getIntegratedProjects` | GET | `/api/v1/projects/{projectId}/integrated-tasks/` (сервис `pm`) | Интегрированные задачи проекта |
| `createProject` | POST | `/api/pm/msp/projects/` | Создать проект |
| `importProject` / `importProjectV2` | POST | `/api/pm/msp/projects/import/` | Импорт проекта |
| `updateProjectV2` | PATCH | `/api/pm/msp/projects/{projectId}/` | Обновить проект |
| `updateFolders` | GET | `/api/pm/msp/projects/?{idsQuery}` | Папки по id |
| `deleteProject` | DELETE | `/api/pm/msp/projects/{id}` | Удалить проект |
| `createProjectTemplate` | POST | `/api/pm/msp/projects/{projectId}/create_template/` | Создать шаблон из проекта |
| `getProjectStates` | GET | `/api/pm/msp/projects/{id}/states/` | Базовые планы проекта |
| `createProjectState` | POST | `/api/pm/msp/project-states/` | Создать базовый план |
| `updateProjectState` | PUT | `/api/pm/msp/project-states/{id}/` | Обновить базовый план |
| `deleteProjectState` | DELETE | `/api/pm/msp/project-states/{id}/` | Удалить базовый план |
| `patchProjectStateDifferenceData` | PATCH | `/api/pm/msp/project-states/{stateId}/edit_state/` | Изменить данные базового плана |
| `getProjectState` | GET | `/api/pm/msp/project-states/{id}/` | Базовый план по id |
| `getProjectStateData` | GET | `/api/pm/msp/project-states/{id}/data/` | Данные базового плана |
| `addTasksToBasicPlan` | POST | `/api/pm/msp/project-states/{planId}/data/` | Добавить задачи в базовый план |
| `getStatusImport` | GET | `/api/pm/msp/external-task-info/?task_id={uuid}` | Статус фоновой задачи импорта |
| `getTasks` | GET | `/api/pm/msp/projects/{id}/tasks/` | Задачи проекта |
| `taskIndex` | PATCH | `/api/pm/msp/tasks/task_index/` | Переиндексация задач |
| `bulkCreateTasks` | POST | `/api/pm/msp/projects/{project}/create_tasks/` | Массовое создание задач |
| `bulkUpdateTasks` | PATCH | `/api/pm/msp/projects/{project}/update_tasks/` | Массовое обновление задач |
| `bulkDeleteTasks` | DELETE | `/api/pm/msp/projects/{project}/delete_tasks/` | Массовое удаление задач |
| `copyPasteTasks` | POST | `/api/pm/msp/tasks/copy/` | Копирование задач |
| `getTaskDescription` | GET | `/api/pm/msp/tasks/{taskId}/descriptions/` | Описание задачи |
| `updateTaskDescription` | PATCH | `/api/pm/msp/tasks/{taskId}/descriptions/` | Обновить описание задачи |
| `createComment` | POST | `/api/v1/comments/` (сервис `pm`) | Создать комментарий к задаче |
| `getActualValues` | GET | `/api/pm/msp/values/?task={task}` | Фактические значения по задаче |
| `createActualValue` | POST | `/api/pm/msp/values/` | Создать фактическое значение |
| `updateActualValue` | PUT | `/api/pm/msp/values/{id}/` | Обновить фактическое значение |
| `deleteActualValues` | DELETE | `/api/pm/msp/values/{id}/` | Удалить фактическое значение |
| `getAllGanttLinks` | GET | `/api/pm/msp/task-relations/{params}` | Связи задач (Ганта) |
| `createGanttLinks` | POST | `/api/pm/msp/task-relations/` | Создать связи задач |
| `updateGanttLink` | PUT | `/api/pm/msp/task-relations/{id}/` | Обновить связь задач |
| `bulkDeleteRelation` | DELETE | `/api/pm/msp/task-relations/bulk_delete/` | Массовое удаление связей |
| `getResourcesTable` | GET | `/api/pm/msp/resources/?{query}` | Таблица ресурсов |
| `updateResources` | PUT | `/api/pm/msp/resources/{id}/` | Обновить ресурс |
| `deleteResource` | DELETE | `/api/pm/msp/resources/{id}/` | Удалить ресурс |
| `createVisualProfile` | POST | `/api/pm/msp/visual-profiles/` | Создать визуальный профиль |
| `editVisualProfile` | PATCH | `/api/pm/msp/visual-profiles/{id}` | Изменить визуальный профиль |
| `getVisualProfiles` | GET | `/api/pm/msp/projects/{projectId}/profiles/` | Визуальные профили проекта |
| `getMyTasks` | GET | `/api/pm/msp/tasks/?responsible=true&executors=true&{query}` | Мои задачи |
| `copyProject` | POST | `/api/pm/msp/projects/{projectId}/copy_project/` | Копировать проект |
| `createProjectDocument` | POST | `/api/pm/msp/projects/{projectId}/ksg_docs_sync/` | Синхронизация КСГ-документов |
| `getUsersByCompanyId` | GET | `/api/core/v2/users/?company={companyId}&{query}` | Пользователи компании |
| `getDepartmentsV2` | GET | `/api/core/admin/departments/?company={companyId}` | Отделы компании |
| `getPositionsV2` | GET | `/api/core/admin/positions/?company={companyId}` | Должности компании |
| `getDocumentStatus` | GET | `/flows/api/v1/documents/?full=true&document_ids={ids}` (сервис `sarexApi`) | Статус документов |
| `exportTasksPDF` | POST | `/api/pm/msp/projects/{id}/export_project_to_pdf/` | Экспорт проекта в PDF (+опрос `external-task-info`) |
| `projectExport` | POST | `/api/pm/msp/projects/{id}/project_export/` | Экспорт проекта (xlsx/xml) |

### `store/api/attributes-api-v2.ts` — AttributesApiV2

| Ключ | Метод | Путь | Назначение |
| --- | --- | --- | --- |
| `getProjectAttributes` | GET | `/api/pm/msp/project-attribute/?project={projectId}` (сервис `sarex`) | Атрибуты проекта |
| `updateProjectAttribute` | PUT | `/api/pm/msp/project-attribute/{id}/` (сервис `sarex`) | Обновить атрибут проекта |
| `deleteProjectAttribute` | DELETE | `/api/pm/msp/project-attribute/{id}/` (сервис `sarex`) | Удалить атрибут проекта |
| `addAttributesToProject` | POST | `/api/pm/msp/project-attribute/` (сервис `sarex`) | Привязать атрибуты к проекту |
| `getTimeMarkersData` | GET | `/api/pm/msp/projects/{projectID}/time_markers_data/?attributes={ids}&with_hierarchy={flag}` (сервис `sarex`) | Данные временных маркеров |
| `getAttributesList` | GET | `/api/v4/attribute/?model_name=gantt-task&company_id={companyId}` (сервис `eavV1`) | Список атрибутов (EAV) |
| `getAssetsByAttribute` | GET | `/api/v4/assets/?path_contains={assetsId}` (сервис `eavV1`) | Ассеты по атрибуту |
| `getAttributesByAssetsParent` | GET | `/api/v4/assets/?tenant_id={companyId}&depth=0` (сервис `eavV1`) | Корневые ассеты компании |
| `createNewAttribute` | POST | `/api/v2/attribute/` (сервис `eavV1`) | Создать атрибут (EAV) |
| `updateAttribute` | PATCH | `/api/v2/attribute/{id}/` (сервис `eavV1`) | Обновить атрибут (EAV) |

### `store/api/calculate-api.ts` — CalculatesAPI (сервис `sarex`)

| Ключ | Метод | Путь | Назначение |
| --- | --- | --- | --- |
| `postFormula` | POST | `/api/pm/msp/projects/{id}/formula/` | Пересчёт по формуле |

### `store/api/calendarsApi.ts` — CalendarsApi (сервис `sarex`)

| Ключ | Метод | Путь | Назначение |
| --- | --- | --- | --- |
| `getAllCalendars` | GET | `/api/pm/msp/calendars/` | Все календари |
| `getCalendarById` | GET | `/api/pm/msp/calendars/{id}/` | Календарь по id |
| `createCalendar` | POST | `/api/pm/msp/calendars/` | Создать календарь |
| `editCalendar` | PATCH | `/api/pm/msp/calendars/{id}/` | Изменить календарь |
| `deleteCalendar` | DELETE | `/api/pm/msp/calendars/{id}/` | Удалить календарь |

### `store/api/issuesApi.ts` — IssuesApi (сервис `sarex`)

| Ключ | Метод | Путь | Назначение |
| --- | --- | --- | --- |
| `getIssueTypes` | GET | `/api/pm/msp/entity-relations/?project_id={projectId}` | Типы связей/проблем проекта |
| `patchIssueType` | PATCH | `/api/pm/msp/entity-relations/{issueTypeId}/` | Обновить тип связи |
| `getIssueData` | GET | `/api/pm/msp/projects/{projectId}/issues_data/` | Данные проблем проекта |

### `store/api/ksgStatesApi.ts` — KsgStatesApi (сервис `sarex`)

| Ключ | Метод | Путь | Назначение |
| --- | --- | --- | --- |
| `getProjestStates` | GET | `/api/pm/msp/project-settings/?{query}` | Настройки/состояния КСГ |
| `createProjectState` | POST | `/api/pm/msp/project-settings/` | Создать состояние КСГ |
| `editProjectState` | PATCH | `/api/pm/msp/project-settings/{id}/` | Изменить состояние КСГ |
| `deleteProjectAttribute` | DELETE | `/api/pm/msp/project-settings/{id}/` | Удалить состояние КСГ |
| `checkApplyState` | POST | `/api/pm/msp/project-settings/{id}/apply/` | Применить состояние КСГ |

### `store/api/permissionsApi.ts` — PermissionsApi (сервис `sarex`)

| Ключ | Метод | Путь | Назначение |
| --- | --- | --- | --- |
| `getPermissions` | GET | `/api/pm/msp/projects/{projectId}/permissions/` | Права проекта |
| `getTaskPermissions` | GET | `/api/pm/msp/tasks/{taskId}/permissions/` | Права задачи |
| `getAllTaskPermissions` | GET | `/api/pm/msp/projects/{projectId}/all_permissions/` | Все права задач проекта |
| `savePermission` | POST | `/api/pm/msp/projects/{projectId}/permissions/` | Сохранить права проекта |
| `saveTaskPermission` | POST | `/api/pm/msp/tasks/{taskId}/permissions/` | Сохранить права задачи |

### `store/api/relationApi.ts` — RelationsApi (сервис `sarex`)

| Ключ | Метод | Путь | Назначение |
| --- | --- | --- | --- |
| `getProjectRelations` | GET | `/api/pm/msp/projects/{projectId}/relations/` | Связи/интеграции проекта |
| `postProjectIntegrations` | POST | `/api/pm/msp/projects/{id}/bulk_integration/` | Массовое создание интеграций |
| `updateProjectIntegration` | PATCH | `/api/pm/msp/project-relations/{id}/` | Обновить интеграцию |
| `deleteProjectIntegration` | DELETE | `/api/pm/msp/project-relations/{id}/` | Удалить интеграцию |

### `store/api/reviewsApi.ts` — ReviewAPI (сервис `sarexApi`)

| Ключ | Метод | Путь | Назначение |
| --- | --- | --- | --- |
| `createReview` | POST | `/flows/api/v1/reviews/` | Создать ревью/согласование |
| `getProcesses` | GET | `/flows/api/v1/flows/?{query}` | Процессы/потоки согласования |

### `store/api/systemLogApi.ts` — SystemLogApi (сервис `sarex`)

| Ключ | Метод | Путь | Назначение |
| --- | --- | --- | --- |
| `getNewSystemLogs` | GET | `/api/pm/msp/projects/{projectId}/system-logs/?{query}` | Системные логи проекта |
| `getDetailsSystemLog` | GET | `/api/pm/msp/projects/{projectId}/system-log-detail/?log_id={logId}` | Детали записи лога |
| `rollBack` | POST | `/api/pm/msp/projects/{projectId}/rollback-to-record/` | Откат к записи лога |

### `store/api/taskDetailingApi.ts` — TaskDetailingApi (сервис `sarex`)

| Ключ | Метод | Путь | Назначение |
| --- | --- | --- | --- |
| `getRole` | GET | `/api/pm/msp/projects/{projectId}/rule/` | Правило детализации проекта |
| `createRule` | POST | `/api/pm/msp/projects/{projectId}/rule/` | Создать правило детализации |
| `getDetailTasks` | GET | `/api/pm/msp/detailed-tasks/?task={taskId}` | Детализированные задачи |
| `patchDetailTasks` | PATCH | `/api/pm/msp/detailed-tasks/{detailingTaskId}/` | Обновить детализированную задачу |

### `store/api/workspaceApi.ts` — WorkspaceAPI (сервис `sarex`)

| Ключ | Метод | Путь | Назначение |
| --- | --- | --- | --- |
| `getResourcesByTaskId` | GET | `/api/pm/msp/resources-tasks/?tasks={task}` | Ресурсы по задаче |
| `getResourcesByIds` | GET | `/api/pm/msp/resources/?ids={resourcesIds}` | Ресурсы по id |
| `loadElementsByResourceIds` | GET | `/api/pm/msp/resources-elements/?resources={ids}` | Элементы ресурсов |
| `connectResourcesTasks` | POST | `/api/pm/msp/resources-tasks/` | Привязать ресурс к задаче |
| `editResourcesTasks` | PATCH | `/api/pm/msp/resources-tasks/bulk_update/` | Массово изменить связи ресурс-задача |
| `deleteResource` | DELETE | `/api/pm/msp/resources-tasks/bulk_delete/` | Массово удалить связи ресурс-задача |

### `services/api/fetch/gateway.ts` — GatewayAPI (сервис `gateway`)

| Ключ | Метод | Путь | Назначение |
| --- | --- | --- | --- |
| `fetchResources` | GET | `/api/v1/resources` | Ресурсы шлюза (доступы/фичи) |

### Gantt-репозитории (`src/pages/TasksNew/GanttWorkspace/repositories/*`, сервис `sarex`)

| Ключ | Метод | Путь | Назначение |
| --- | --- | --- | --- |
| `WorkspaceSelectedKSGProjectRepository` | GET | `/api/pm/msp/projects/?bundle_id={bundleID}&schema=tiny` | Проекты выбранного бандла КСГ |
| `TaskResourceConnectionBaseRepository` | GET | `/api/pm/msp/projects/{id}/profiles/` | Профили ресурсов проекта |
| `TaskResourcesConnectionsRepository` | GET | `/api/pm/msp/resources-tasks/?projects={project}` | Связи ресурс-задача по проекту |
| `TasksRepository` (список) | GET | `/api/pm/msp/tasks/?project={project}&{query}` | Задачи проекта |
| `TasksRepository` (одна) | GET | `/api/pm/msp/tasks/{id}/` | Одна задача |
| `uploadFileToServer` | POST (multipart) | `/api/pm/msp/descriptions/upload_file/` | Загрузка файла/изображения в описание |

## Обработка ошибок

Централизованного middleware (RTK Query `createApi`/`fetchBaseQuery` не используется) нет — API-модули оборачивают axios-based `httpService`. Типичные паттерны: большинство вызовов `.then(r => r.data)` и пробрасывают ошибку выше; часть — `try/catch` с `isAxiosError(error)`, где `403` даёт «Нет доступа»/«Доступ запрещён», а прочие ошибки — общее сообщение (напр. «Не удалось сохранить данные, попробуйте ещё раз»), нередко показываемое через `createToast(...)` и повторно выбрасываемое как `new Error(...)`. Некоторые читают `error.response.data.detail`. `getStatusImport` при ошибке возвращает `{ request_failed: true }`; `exportTasksPDF` опрашивает `external-task-info` каждые 2 с до `is_ready`. Часть вызовов передаёт в SDK опцию `errorMessage` (напр. «Некорректные данные»).
