iac/apps/flows/openapi.yaml

1737 lines
65 KiB
YAML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

openapi: 3.0.3
info:
title: Flows Service API
version: "1.0.0"
description: |
REST API сервиса **flows-backend** (`proc/flows-backend`) — управление
процессами согласования документации: маршрутами (`flows`), их шагами
(`steps`) и статусами (`statuses`), запусками согласования (`reviews`),
документами в согласовании (`documents`), действиями пользователей
(`user-actions`) и очередью задач согласующих (`tasks`).
Сервис написан на Python (**FastAPI**). Приложение собирается фабрикой
`get_app` в `src/flow/main.py`. Роутинг состоит из двух зеркальных групп
(`src/flow/routers/__init__.py`):
- публичный API — префикс `/api/v1` (`API_PREFIX`);
- внутренний API — префикс `/internal/v1` (`API_INTERNAL_PREFIX`),
предназначен для вызовов внутри кластера. Набор роутеров идентичен
публичному, но внутренний префикс исключён из проверки аутентификации.
Оба префикса могут дополнительно предваряться `PROXY_PATH_PREFIX`
(в кластере — `/flows`). Админ-панель (`sqladmin`) смонтирована по
`/api/admin/`. Интерактивная документация Swagger доступна по `/docs`,
схема — по `/openapi.json` (с учётом `root_path`).
Ниже описан публичный API (`/api/v1`). Внутренний API (`/internal/v1/*`)
имеет те же пути и тела, но не требует аутентификации на уровне приложения.
### Аутентификация
Публичные эндпоинты требуют заголовок `Authorization: Bearer <jwt>`
(`src/flow/middleware.py`, `TokenUserMiddleware`). Поддерживаются два режима:
1. **Zitadel** — если передан заголовок `identity` (`Bearer <jwt>`),
полезная нагрузка берётся из этого токена
(`urn:zitadel:iam:user:metadata`).
2. **sarex-backend** — если заголовка `identity` нет, данные берутся из
основного токена (подпись проверяется публичным RSA-ключом
`JWT_PUBLIC_KEY`).
Проверка отключается флагом `JWT_AUTH_ENABLE=False` (тогда все запросы идут
от дефолтного администратора). Пути `/docs/`, `/openapi.json/` и весь
`/internal/*` из проверки исключены.
### Авторизация (права)
Доступ к группам проверяется в `PermissionManager` (`src/flow/dependencies.py`)
по правам пользователя (`src/flow/utils/permissions.py`): напр. `flows`/`steps`/
`statuses` требуют `base.can_view_flow`/`base.can_add_flow`/… , `reviews`/
`documents` — `base.can_view_review`/`base.can_add_review`/… Пользователь с
признаком администратора проверки прав пропускает.
### Пагинация
Списочные эндпоинты используют limit/offset (`LimitOffsetParams`,
по умолчанию `limit=1000`, `offset=0`). Часть «тяжёлых» списков (`reviews`,
подсчёты) возвращается как готовый JSON (`Response(media_type=application/json)`),
поэтому их тело в схеме описано обобщённо.
### Обработка ошибок
Ошибки бизнес-логики возвращаются как `{"detail": "..."}` с
соответствующим статусом (`400`/`403`/`404`). Ошибки валидации тела/query
(Pydantic) отдаются FastAPI в стандартном формате `422`.
servers:
- url: https://api.sarex.io/flows/api/v1
description: production
- url: https://api.preprod.sarex.io/flows/api/v1
description: preprod
- url: https://stage-api.sarex.io/flows/api/v1
description: stage
security:
- bearerAuth: []
tags:
- name: flows
description: Маршруты согласования
- name: reviews
description: Запуски согласования
- name: steps
description: Шаги маршрута
- name: statuses
description: Статусы согласования
- name: documents
description: Документы в согласовании
- name: user_actions
description: Действия пользователей
- name: tasks
description: Очередь задач согласующих
paths:
/flows/:
get:
tags: [flows]
summary: Список маршрутов
description: Фильтры передаются query-параметрами (`MainFilters`). При `full=true` возвращаются вложенные шаги/статусы.
parameters:
- { $ref: '#/components/parameters/Limit' }
- { $ref: '#/components/parameters/Offset' }
- { in: query, name: full, schema: { type: boolean, default: false } }
- { in: query, name: resource_id, schema: { type: string }, description: "CSV UUID ресурсов" }
- { in: query, name: company_id, schema: { type: string } }
- { in: query, name: is_active, schema: { type: boolean } }
- { in: query, name: flow_type, schema: { $ref: '#/components/schemas/FlowType' } }
- { in: query, name: name, schema: { type: string } }
responses:
'200':
description: OK
content:
application/json:
schema:
type: array
items:
oneOf: [ { $ref: '#/components/schemas/Flow' }, { $ref: '#/components/schemas/FullFlow' } ]
post:
tags: [flows]
summary: Создать маршрут
parameters:
- { in: query, name: full, schema: { type: boolean, default: false } }
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/FlowCreate' }
responses:
'201':
description: Создан
content:
application/json:
schema:
oneOf: [ { $ref: '#/components/schemas/Flow' }, { $ref: '#/components/schemas/FullFlow' } ]
'400': { $ref: '#/components/responses/BadRequest' }
/flows/filter/:
post:
tags: [flows]
summary: Список маршрутов по фильтру (тело)
parameters:
- { $ref: '#/components/parameters/Limit' }
- { $ref: '#/components/parameters/Offset' }
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/MainFilterPostRequest' }
responses:
'200':
description: OK
content:
application/json:
schema: { type: array, items: { $ref: '#/components/schemas/Flow' } }
/flows/light/:
get:
tags: [flows]
summary: Облегчённый список маршрутов (id, name)
parameters:
- { $ref: '#/components/parameters/Limit' }
- { $ref: '#/components/parameters/Offset' }
responses:
'200':
description: OK
content:
application/json:
schema: { type: array, items: { $ref: '#/components/schemas/FlowLight' } }
/flows/count_flows_by_resource/:
get:
tags: [flows]
summary: Количество маршрутов, сгруппированное по resource_id
responses:
'200': { $ref: '#/components/responses/JsonObject' }
post:
tags: [flows]
summary: То же по фильтру (тело)
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/MainFilterPostRequest' }
responses:
'200': { $ref: '#/components/responses/JsonObject' }
/flows/bulk-update/:
patch:
tags: [flows]
summary: Массовое обновление маршрутов (watchers/approvers)
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/FlowBulkUpdate' }
responses:
'200':
description: OK
content:
application/json:
schema: { type: array, items: { $ref: '#/components/schemas/Flow' } }
'404': { $ref: '#/components/responses/NotFound' }
/flows/{instance_id}/:
parameters:
- { $ref: '#/components/parameters/InstanceId' }
get:
tags: [flows]
summary: Маршрут по id
parameters:
- { in: query, name: full, schema: { type: boolean, default: false } }
responses:
'200':
description: OK
content:
application/json:
schema:
oneOf: [ { $ref: '#/components/schemas/Flow' }, { $ref: '#/components/schemas/FullFlow' } ]
'404': { $ref: '#/components/responses/NotFound' }
put:
tags: [flows]
summary: Обновить маршрут
parameters:
- { in: query, name: full, schema: { type: boolean, default: false } }
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/FlowCreate' }
responses:
'200':
description: OK
content:
application/json:
schema:
oneOf: [ { $ref: '#/components/schemas/Flow' }, { $ref: '#/components/schemas/FullFlow' } ]
'400': { $ref: '#/components/responses/BadRequest' }
'404': { $ref: '#/components/responses/NotFound' }
delete:
tags: [flows]
summary: Удалить маршрут
responses:
'200':
description: OK
content:
application/json:
schema: { $ref: '#/components/schemas/Flow' }
'404': { $ref: '#/components/responses/NotFound' }
/flows/{instance_id}/copy/:
parameters:
- { $ref: '#/components/parameters/InstanceId' }
post:
tags: [flows]
summary: Копировать маршрут
parameters:
- { in: query, name: full, schema: { type: boolean, default: false } }
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/CopyFlow' }
responses:
'201':
description: Создан
content:
application/json:
schema:
oneOf: [ { $ref: '#/components/schemas/Flow' }, { $ref: '#/components/schemas/FullFlow' } ]
'400': { $ref: '#/components/responses/BadRequest' }
'404': { $ref: '#/components/responses/NotFound' }
/reviews/:
get:
tags: [reviews]
summary: Список review (готовый JSON)
parameters:
- { $ref: '#/components/parameters/Limit' }
- { $ref: '#/components/parameters/Offset' }
- { in: query, name: join_user_actions, schema: { type: boolean, default: false } }
- { in: query, name: resource_id, schema: { type: string } }
- { in: query, name: flow_id, schema: { type: string } }
- { in: query, name: company_id, schema: { type: string } }
- { in: query, name: status, schema: { type: string }, description: "CSV значений StateReview" }
responses:
'200': { $ref: '#/components/responses/JsonArray' }
post:
tags: [reviews]
summary: Создать review
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/BaseReview' }
responses:
'201':
description: Создан
content:
application/json:
schema: { $ref: '#/components/schemas/Review' }
'400': { $ref: '#/components/responses/BadRequest' }
/reviews/filter/:
post:
tags: [reviews]
summary: Список review по фильтру (тело)
parameters:
- { $ref: '#/components/parameters/Limit' }
- { $ref: '#/components/parameters/Offset' }
- { in: query, name: join_user_actions, schema: { type: boolean, default: false } }
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/MainFilterPostRequest' }
responses:
'200': { $ref: '#/components/responses/JsonArray' }
/reviews/light/:
get:
tags: [reviews]
summary: Облегчённый список review
parameters:
- { $ref: '#/components/parameters/Limit' }
- { $ref: '#/components/parameters/Offset' }
- { in: query, name: resource_id, schema: { type: string } }
- { in: query, name: flow_id, schema: { type: string } }
- { in: query, name: company_id, schema: { type: string } }
responses:
'200': { $ref: '#/components/responses/JsonArray' }
/reviews/tasks-count/:
get:
tags: [reviews]
summary: Количество задач текущего пользователя
responses:
'200':
description: OK
content:
application/json:
schema: { $ref: '#/components/schemas/TasksCount' }
/reviews/count_by_resource_id/:
get:
tags: [reviews]
summary: Количество review по resource_id
responses:
'200': { $ref: '#/components/responses/JsonObject' }
post:
tags: [reviews]
summary: То же по фильтру (тело)
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/MainFilterPostRequest' }
responses:
'200': { $ref: '#/components/responses/JsonObject' }
/reviews/count_by_reviewer_id/:
get:
tags: [reviews]
summary: Количество review по reviewer_id
responses:
'200': { $ref: '#/components/responses/JsonObject' }
post:
tags: [reviews]
summary: То же по фильтру (тело)
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/MainFilterPostRequest' }
responses:
'200': { $ref: '#/components/responses/JsonObject' }
/reviews/bulk-reviewers-update/:
patch:
tags: [reviews]
summary: Массовое обновление согласующих в review
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/BulkReviewersUpdate' }
responses:
'200':
description: OK
content:
application/json:
schema: { type: array, items: { $ref: '#/components/schemas/Review' } }
/reviews/{instance_id}/:
parameters:
- { $ref: '#/components/parameters/InstanceId' }
get:
tags: [reviews]
summary: Review по id
responses:
'200': { $ref: '#/components/responses/ReviewOk' }
'404': { $ref: '#/components/responses/NotFound' }
put:
tags: [reviews]
summary: Обновить review
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/UpdateBaseReview' }
responses:
'200': { $ref: '#/components/responses/ReviewOk' }
'404': { $ref: '#/components/responses/NotFound' }
patch:
tags: [reviews]
summary: Частичное обновление review
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/PatchBaseReview' }
responses:
'200': { $ref: '#/components/responses/ReviewOk' }
'404': { $ref: '#/components/responses/NotFound' }
delete:
tags: [reviews]
summary: Удалить review
responses:
'200': { $ref: '#/components/responses/ReviewOk' }
'404': { $ref: '#/components/responses/NotFound' }
/reviews/{instance_id}/restart/:
parameters:
- { $ref: '#/components/parameters/InstanceId' }
post:
tags: [reviews]
summary: Пересчитать динамические поля review
responses:
'200': { $ref: '#/components/responses/ReviewOk' }
'404': { $ref: '#/components/responses/NotFound' }
/reviews/{instance_id}/documents/:
parameters:
- { $ref: '#/components/parameters/InstanceId' }
get:
tags: [reviews]
summary: Документы review
parameters:
- { $ref: '#/components/parameters/Limit' }
- { $ref: '#/components/parameters/Offset' }
- { in: query, name: document_type, schema: { type: string }, description: "CSV" }
- { in: query, name: bundle_id, schema: { type: string }, description: "CSV" }
responses:
'200':
description: OK
content:
application/json:
schema: { type: array, items: { $ref: '#/components/schemas/Document' } }
'404': { $ref: '#/components/responses/NotFound' }
put:
tags: [reviews]
summary: Обновить статус документов review
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/BaseUpdateDocument' }
responses:
'200':
description: OK
content:
application/json:
schema: { type: array, items: { $ref: '#/components/schemas/Document' } }
'400': { $ref: '#/components/responses/BadRequest' }
'404': { $ref: '#/components/responses/NotFound' }
/reviews/{instance_id}/start/:
parameters:
- { $ref: '#/components/parameters/InstanceId' }
patch:
tags: [reviews]
summary: Начать проверку (таймтрекинг)
responses:
'200': { $ref: '#/components/responses/JsonObject' }
'400': { $ref: '#/components/responses/BadRequest' }
'404': { $ref: '#/components/responses/NotFound' }
/reviews/{instance_id}/approve/:
parameters:
- { $ref: '#/components/parameters/InstanceId' }
patch:
tags: [reviews]
summary: Пройти review согласующим (принять/отклонить/подписать/аннулировать)
requestBody:
required: false
content:
application/json:
schema: { $ref: '#/components/schemas/StatusForReview' }
responses:
'200': { $ref: '#/components/responses/ReviewOk' }
'400': { $ref: '#/components/responses/BadRequest' }
'404': { $ref: '#/components/responses/NotFound' }
/reviews/{instance_id}/update-bundles/:
parameters:
- { $ref: '#/components/parameters/InstanceId' }
patch:
tags: [reviews]
summary: Обновить bundle_id подписанных документов
requestBody:
required: true
content:
application/json:
schema: { type: object, additionalProperties: true }
responses:
'200':
description: OK
content:
application/json:
schema: { type: array, items: { $ref: '#/components/schemas/Document' } }
'404': { $ref: '#/components/responses/NotFound' }
/reviews/{instance_id}/update-documents/:
parameters:
- { $ref: '#/components/parameters/InstanceId' }
patch:
tags: [reviews]
summary: Обновить copied-id документов
requestBody:
required: true
content:
application/json:
schema: { type: array, items: { $ref: '#/components/schemas/UpdateDocumentCopiedIds' } }
responses:
'200':
description: OK
content:
application/json:
schema: { type: array, items: { $ref: '#/components/schemas/Document' } }
'404': { $ref: '#/components/responses/NotFound' }
/reviews/{instance_id}/change_reviewers/:
parameters:
- { $ref: '#/components/parameters/InstanceId' }
patch:
tags: [reviews]
summary: Заменить согласующих на текущем шаге
requestBody:
required: true
content:
application/json:
schema: { type: array, items: { $ref: '#/components/schemas/PatchCurrentReviewers' } }
responses:
'200': { $ref: '#/components/responses/ReviewOk' }
'404': { $ref: '#/components/responses/NotFound' }
/reviews/{instance_id}/change-min-reviewers/:
parameters:
- { $ref: '#/components/parameters/InstanceId' }
patch:
tags: [reviews]
summary: Изменить минимальное число согласующих на шаге
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/PatchMinReviewersOnStep' }
responses:
'200': { $ref: '#/components/responses/ReviewOk' }
'404': { $ref: '#/components/responses/NotFound' }
/reviews/{instance_id}/set-step/{step_id}/:
parameters:
- { $ref: '#/components/parameters/InstanceId' }
- { in: path, name: step_id, required: true, schema: { type: integer } }
patch:
tags: [reviews]
summary: Принудительно установить шаг review (только админ)
responses:
'200': { $ref: '#/components/responses/ReviewOk' }
'400': { $ref: '#/components/responses/BadRequest' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
/reviews/{instance_id}/switch_to_next_step/:
parameters:
- { $ref: '#/components/parameters/InstanceId' }
patch:
tags: [reviews]
summary: Перевести review на следующий шаг (только superuser)
responses:
'200': { $ref: '#/components/responses/ReviewOk' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
/reviews/{instance_id}/time-tracking/:
parameters:
- { $ref: '#/components/parameters/InstanceId' }
get:
tags: [reviews]
summary: Таймтрекинг review
responses:
'200': { $ref: '#/components/responses/JsonObject' }
'404': { $ref: '#/components/responses/NotFound' }
/reviews/{review_id}/checklist-results/:
parameters:
- { in: path, name: review_id, required: true, schema: { type: integer } }
patch:
tags: [reviews]
summary: Обновить результаты чек-листов review
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/ChecklistResultsUpdateRequest' }
responses:
'200': { $ref: '#/components/responses/ReviewOk' }
'400': { $ref: '#/components/responses/BadRequest' }
'404': { $ref: '#/components/responses/NotFound' }
/reviews/{review_id}/transmittal-created/:
parameters:
- { in: path, name: review_id, required: true, schema: { type: integer } }
post:
tags: [reviews]
summary: Зафиксировать созданную по review передачу (transmittal)
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/TransmittalForReviewCreated' }
responses:
'200': { $ref: '#/components/responses/ReviewOk' }
'400': { $ref: '#/components/responses/BadRequest' }
'404': { $ref: '#/components/responses/NotFound' }
/steps/:
get:
tags: [steps]
summary: Список шагов
parameters:
- { $ref: '#/components/parameters/Limit' }
- { $ref: '#/components/parameters/Offset' }
- { in: query, name: full, schema: { type: boolean, default: false } }
responses:
'200':
description: OK
content:
application/json:
schema: { type: array, items: { $ref: '#/components/schemas/Step' } }
post:
tags: [steps]
summary: Создать шаг
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/BaseStep' }
responses:
'201':
description: Создан
content:
application/json:
schema: { $ref: '#/components/schemas/Step' }
'400': { $ref: '#/components/responses/BadRequest' }
/steps/{instance_id}/:
parameters:
- { $ref: '#/components/parameters/InstanceId' }
get:
tags: [steps]
summary: Шаг по id
parameters:
- { in: query, name: full, schema: { type: boolean, default: false } }
responses:
'200':
description: OK
content:
application/json:
schema: { $ref: '#/components/schemas/Step' }
'404': { $ref: '#/components/responses/NotFound' }
put:
tags: [steps]
summary: Обновить шаг
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/BaseStep' }
responses:
'200':
description: OK
content:
application/json:
schema: { $ref: '#/components/schemas/Step' }
'404': { $ref: '#/components/responses/NotFound' }
delete:
tags: [steps]
summary: Удалить шаг
responses:
'200':
description: OK
content:
application/json:
schema: { $ref: '#/components/schemas/Step' }
'404': { $ref: '#/components/responses/NotFound' }
/steps/{instance_id}/active_reviews/:
parameters:
- { $ref: '#/components/parameters/InstanceId' }
get:
tags: [steps]
summary: Активные review на шаге
responses:
'200':
description: OK
content:
application/json:
schema: { type: array, items: { $ref: '#/components/schemas/ActiveReview' } }
'404': { $ref: '#/components/responses/NotFound' }
/steps/{instance_id}/update_reviewers/:
parameters:
- { $ref: '#/components/parameters/InstanceId' }
patch:
tags: [steps]
summary: Обновить согласующих шага
requestBody:
required: true
content:
application/json:
schema: { type: array, items: { $ref: '#/components/schemas/UpdatedReviewer' } }
responses:
'200':
description: OK
content:
application/json:
schema: { $ref: '#/components/schemas/Step' }
'404': { $ref: '#/components/responses/NotFound' }
/steps/{instance_id}/get_reviewers/:
parameters:
- { $ref: '#/components/parameters/InstanceId' }
get:
tags: [steps]
summary: Допустимые согласующие для шага
parameters:
- { in: query, name: review_id, schema: { type: integer } }
responses:
'200':
description: OK
content:
application/json:
schema: { type: array, items: { type: object, additionalProperties: true } }
'404': { $ref: '#/components/responses/NotFound' }
/statuses/:
get:
tags: [statuses]
summary: Список статусов
parameters:
- { $ref: '#/components/parameters/Limit' }
- { $ref: '#/components/parameters/Offset' }
responses:
'200':
description: OK
content:
application/json:
schema: { type: array, items: { $ref: '#/components/schemas/Status' } }
post:
tags: [statuses]
summary: Создать статус
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/BaseStatus' }
responses:
'201':
description: Создан
content:
application/json:
schema: { $ref: '#/components/schemas/Status' }
'400': { $ref: '#/components/responses/BadRequest' }
/statuses/{instance_id}/:
parameters:
- { $ref: '#/components/parameters/InstanceId' }
get:
tags: [statuses]
summary: Статус по id
responses:
'200':
description: OK
content:
application/json:
schema: { $ref: '#/components/schemas/Status' }
'404': { $ref: '#/components/responses/NotFound' }
put:
tags: [statuses]
summary: Обновить статус
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/BaseStatus' }
responses:
'200':
description: OK
content:
application/json:
schema: { $ref: '#/components/schemas/Status' }
'404': { $ref: '#/components/responses/NotFound' }
delete:
tags: [statuses]
summary: Удалить статус
responses:
'200':
description: OK
content:
application/json:
schema: { $ref: '#/components/schemas/Status' }
'404': { $ref: '#/components/responses/NotFound' }
/documents/:
get:
tags: [documents]
summary: Список документов
description: При `full=true` возвращаются расширенные записи (`ExtendDocument`) с данными review.
parameters:
- { $ref: '#/components/parameters/Limit' }
- { $ref: '#/components/parameters/Offset' }
- { in: query, name: full, schema: { type: boolean, default: false } }
- { in: query, name: flow_ids, schema: { type: string }, description: "CSV" }
- { in: query, name: review_ids, schema: { type: string }, description: "CSV" }
- { in: query, name: document_ids, schema: { type: string }, description: "CSV" }
- { in: query, name: bundle_ids, schema: { type: string }, description: "CSV" }
- { in: query, name: review_status, schema: { type: string }, description: "CSV" }
- { in: query, name: document_types, schema: { type: string }, description: "CSV" }
- { in: query, name: document_copied_ids, schema: { type: string }, description: "CSV" }
- { in: query, name: bundle_copied_ids, schema: { type: string }, description: "CSV" }
responses:
'200':
description: OK
content:
application/json:
schema:
type: array
items:
oneOf: [ { $ref: '#/components/schemas/Document' }, { $ref: '#/components/schemas/ExtendDocument' } ]
post:
tags: [documents]
summary: Создать документы (пакетно)
requestBody:
required: true
content:
application/json:
schema: { type: array, items: { $ref: '#/components/schemas/BaseDocument' } }
responses:
'201':
description: Создано
content:
application/json:
schema: { type: array, items: { $ref: '#/components/schemas/Document' } }
'400': { $ref: '#/components/responses/BadRequest' }
/documents/filter/:
post:
tags: [documents]
summary: Список документов по фильтру (тело)
parameters:
- { $ref: '#/components/parameters/Limit' }
- { $ref: '#/components/parameters/Offset' }
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/DocumentFilterRequest' }
responses:
'200':
description: OK
content:
application/json:
schema:
type: array
items:
oneOf: [ { $ref: '#/components/schemas/Document' }, { $ref: '#/components/schemas/ExtendDocument' } ]
/documents/change-copy-paths/:
patch:
tags: [documents]
summary: Изменить пути копирования документов
requestBody:
required: true
content:
application/json:
schema: { type: array, items: { $ref: '#/components/schemas/ChangeDocumentCopyPath' } }
responses:
'200':
description: OK
content:
application/json:
schema: { type: array, items: { $ref: '#/components/schemas/Document' } }
/documents/set-status/:
patch:
tags: [documents]
summary: Установить статус документам
parameters:
- { in: query, name: document_ids, required: true, schema: { type: string }, description: "CSV id документов" }
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/SetDocumentStatusUpdate' }
responses:
'200':
description: OK
content:
application/json:
schema: { type: array, items: { $ref: '#/components/schemas/SetDocumentStatusRead' } }
'400': { $ref: '#/components/responses/BadRequest' }
/documents/{instance_id}/:
parameters:
- { $ref: '#/components/parameters/InstanceId' }
get:
tags: [documents]
summary: Документ по id
responses:
'200': { $ref: '#/components/responses/DocumentOk' }
'404': { $ref: '#/components/responses/NotFound' }
put:
tags: [documents]
summary: Обновить статус документа
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/BaseUpdateDocument' }
responses:
'200': { $ref: '#/components/responses/DocumentOk' }
'400': { $ref: '#/components/responses/BadRequest' }
'404': { $ref: '#/components/responses/NotFound' }
patch:
tags: [documents]
summary: Установить bundle_id и статус документа
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/SetDocumentBundleIdAndStatus' }
responses:
'200': { $ref: '#/components/responses/DocumentOk' }
'404': { $ref: '#/components/responses/NotFound' }
delete:
tags: [documents]
summary: Удалить документ
responses:
'200': { $ref: '#/components/responses/DocumentOk' }
'404': { $ref: '#/components/responses/NotFound' }
/user-actions/:
post:
tags: [user_actions]
summary: Создать действие пользователя
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/BaseUserAction' }
responses:
'201':
description: Создано
content:
application/json:
schema: { type: object, properties: { detail: { type: string } } }
'400': { $ref: '#/components/responses/BadRequest' }
/user-actions/bulk-delete-user-action/:
delete:
tags: [user_actions]
summary: Массовое удаление действий
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/ListUserActionsForDelete' }
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
properties:
deleted_ids: { type: array, items: { type: integer } }
/user-actions/{instance_id}/:
parameters:
- { $ref: '#/components/parameters/InstanceId' }
patch:
tags: [user_actions]
summary: Обновить key/value действия
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/UpdateUserAction' }
responses:
'200':
description: OK
content:
application/json:
schema: { $ref: '#/components/schemas/UserActions' }
'404': { $ref: '#/components/responses/NotFound' }
/tasks/:
get:
tags: [tasks]
summary: Список задач очереди
parameters:
- { $ref: '#/components/parameters/Limit' }
- { $ref: '#/components/parameters/Offset' }
- { in: query, name: review_id, schema: { type: integer } }
- { in: query, name: reviewer_id, schema: { type: integer } }
- { in: query, name: is_active, schema: { type: boolean } }
- { in: query, name: resource_id, schema: { type: string } }
responses:
'200':
description: OK
content:
application/json:
schema: { type: array, items: { $ref: '#/components/schemas/Task' } }
/tasks/reviewers-max-end-dates/:
get:
tags: [tasks]
summary: Максимальные даты окончания задач по согласующим
parameters:
- { in: query, name: reviewers_ids, required: true, schema: { type: string }, description: "CSV id" }
- { in: query, name: duration, required: true, schema: { type: integer } }
responses:
'200':
description: OK
content:
application/json:
schema: { type: array, items: { $ref: '#/components/schemas/ReviewerMaxTaskEndDate' } }
/tasks/{instance_id}/change-priority/:
parameters:
- { $ref: '#/components/parameters/InstanceId' }
patch:
tags: [tasks]
summary: Изменить приоритет задачи
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/TaskUpdatePriority' }
responses:
'200':
description: OK
content:
application/json:
schema: { $ref: '#/components/schemas/Task' }
'404': { $ref: '#/components/responses/NotFound' }
/tasks/{instance_id}/change-duration/:
parameters:
- { $ref: '#/components/parameters/InstanceId' }
patch:
tags: [tasks]
summary: Изменить длительность задачи
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/TaskUpdateDuration' }
responses:
'200':
description: OK
content:
application/json:
schema: { $ref: '#/components/schemas/Task' }
'404': { $ref: '#/components/responses/NotFound' }
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
description: "Основной токен. Дополнительно может передаваться заголовок `identity: Bearer <jwt>` для режима Zitadel."
parameters:
Limit:
in: query
name: limit
schema: { type: integer, minimum: 0, default: 1000 }
Offset:
in: query
name: offset
schema: { type: integer, minimum: 0, default: 0 }
InstanceId:
in: path
name: instance_id
required: true
schema: { type: integer }
responses:
BadRequest:
description: Ошибка запроса
content:
application/json:
schema: { $ref: '#/components/schemas/ApiError' }
Forbidden:
description: Недостаточно прав
content:
application/json:
schema: { $ref: '#/components/schemas/ApiError' }
NotFound:
description: Не найдено
content:
application/json:
schema: { $ref: '#/components/schemas/ApiError' }
JsonObject:
description: Готовый JSON-объект (структура зависит от группировки)
content:
application/json:
schema: { type: object, additionalProperties: true }
JsonArray:
description: Готовый JSON-массив review (сериализуется на стороне сервиса)
content:
application/json:
schema: { type: array, items: { type: object, additionalProperties: true } }
ReviewOk:
description: OK
content:
application/json:
schema: { $ref: '#/components/schemas/Review' }
DocumentOk:
description: OK
content:
application/json:
schema: { $ref: '#/components/schemas/Document' }
schemas:
ApiError:
type: object
properties:
detail:
oneOf: [ { type: string }, { type: array, items: { type: object } } ]
FlowType:
type: string
enum: [document, schedule]
Action:
type: string
enum: ['Отсутствует', 'Скопировать в папку']
StatusKey:
type: string
enum: ['Согласовано', 'Не согласовано']
StateReview:
type: string
nullable: true
enum: ['Начато', 'Открыто', 'Копирование документов', 'На подписании', 'Закрыто', 'Завершено', 'Аннулировано']
StepType:
type: string
enum: ['Инициализирующий', 'Обычный', 'Финальный']
ChangeCopyPathRole:
type: string
enum: ['Инициатор при запуске', 'Утверждающий при завершении', 'Инициатор и утверждающий', 'Возможность отсутствует']
AcceptanceByReviewer:
type: string
enum: [accepted, rejected, partly_rejected]
TimeTrackingMode:
type: string
enum: [auto, manual]
CompletionNotificationsMode:
type: string
enum: [disabled, positive_documents_only, all_documents]
TransmittalDocumentsStatus:
type: string
enum: [accepted_only, all_documents]
TransmittalDocumentsType:
type: string
enum: [copy_only, original_only]
BulkListUpdateType:
type: string
enum: [replace, add]
FlowActonAdditions:
type: object
properties:
enable_stamp: { type: boolean }
enable_signature: { type: boolean }
enable_qr_code: { type: boolean }
enable_base_plan: { type: boolean }
required: [enable_stamp, enable_signature, enable_qr_code, enable_base_plan]
StepChecklistAssignment:
type: object
properties:
required: { type: boolean }
reviewers: { type: array, items: { type: string, format: uuid } }
required: [required, reviewers]
BaseFlow:
type: object
properties:
name: { type: string }
description: { type: string, nullable: true }
action: { $ref: '#/components/schemas/Action' }
additions: { $ref: '#/components/schemas/FlowActonAdditions' }
meta_data: { type: object, additionalProperties: true }
folder_dst: { type: string, nullable: true }
folder_dst_relative: { type: string, nullable: true }
folder_label: { type: string, nullable: true }
is_active: { type: boolean, nullable: true }
count_of_step: { type: integer, minimum: 0 }
launchers: { type: array, items: { type: string, format: uuid } }
approvers: { type: array, nullable: true, items: { type: string, format: uuid } }
company_id: { type: integer }
creator_id: { type: integer, nullable: true }
changer_id: { type: integer, nullable: true }
signatories: { type: array, nullable: true, items: { type: integer } }
resource_id: { type: string, format: uuid, nullable: true }
steps: { type: array, items: { type: integer } }
statuses: { type: array, items: { type: integer } }
change_copy_path_role: { $ref: '#/components/schemas/ChangeCopyPathRole' }
final_step_duration: { type: integer, nullable: true }
step_watchers: { type: object, additionalProperties: { type: array, items: { type: string } } }
flow_type: { $ref: '#/components/schemas/FlowType' }
finish_step_after_review: { type: boolean }
skip_empty_steps: { type: boolean }
time_tracking_mode: { $ref: '#/components/schemas/TimeTrackingMode' }
attributes: { type: object, additionalProperties: true }
unset_attributes: { type: array, items: { type: integer } }
completion_notifications_mode: { $ref: '#/components/schemas/CompletionNotificationsMode' }
completion_notifications_receivers: { type: array, items: { type: string, format: uuid } }
checklists: { type: object, additionalProperties: { $ref: '#/components/schemas/StepChecklistAssignment' } }
transmittal_after_review: { type: boolean }
transmittal_templates: { type: array, items: { type: string, format: uuid } }
transmittal_doc_statuses: { $ref: '#/components/schemas/TransmittalDocumentsStatus' }
transmittal_doc_types: { $ref: '#/components/schemas/TransmittalDocumentsType' }
folder_dst_ai_assist_enabled: { type: boolean }
required: [name, additions, meta_data, count_of_step, launchers, company_id]
FlowCreate:
allOf:
- { $ref: '#/components/schemas/BaseFlow' }
Flow:
allOf:
- { $ref: '#/components/schemas/BaseFlow' }
- type: object
properties:
id: { type: integer }
created_at: { type: string, format: date-time }
updated_at: { type: string, format: date-time }
required: [id, created_at, updated_at]
FullFlow:
allOf:
- { $ref: '#/components/schemas/BaseFlow' }
- type: object
properties:
id: { type: integer }
created_at: { type: string, format: date-time }
updated_at: { type: string, format: date-time }
steps: { type: array, items: { $ref: '#/components/schemas/FullStep' } }
statuses: { type: array, items: { $ref: '#/components/schemas/Status' } }
required: [id, created_at, updated_at]
FlowLight:
type: object
properties:
id: { type: integer }
name: { type: string }
required: [id, name]
CopyFlow:
type: object
properties:
name: { type: string }
required: [name]
BulkUpdateListUUID4FieldAction:
type: object
properties:
action: { $ref: '#/components/schemas/BulkListUpdateType' }
value: { type: array, items: { type: string, format: uuid } }
required: [action, value]
FlowBulkUpdate:
type: object
properties:
ids: { type: array, items: { type: integer } }
watchers: { $ref: '#/components/schemas/BulkUpdateListUUID4FieldAction' }
approvers: { $ref: '#/components/schemas/BulkUpdateListUUID4FieldAction' }
required: [ids]
BaseStep:
type: object
properties:
name: { type: string }
duration: { type: integer, minimum: 0 }
min_reviewers: { type: integer, nullable: true }
all_verify: { type: boolean, default: true }
force_close: { type: boolean, default: false }
force_close_block_status: { type: boolean, default: false }
setup_next_step: { type: boolean, default: false }
task_queue: { type: boolean, default: false }
set_status: { type: boolean, default: false }
blocking_step: { type: boolean, default: false }
flow_id: { type: integer }
reviewers: { type: array, items: { type: string, format: uuid } }
blocking_reviewers: { type: array, items: { type: string, format: uuid } }
only_final_step_blocking: { type: boolean, default: false }
min_reviewers_by_sa: { type: object, additionalProperties: { type: integer } }
close_on_rejection: { type: boolean, default: false }
complete_on_rejection: { type: boolean, default: false }
complete_on_rejection_reviewers: { type: array, items: { type: string, format: uuid } }
checklists: { type: object, additionalProperties: { $ref: '#/components/schemas/StepChecklistAssignment' } }
force_next_step_reviewers: { type: array, items: { type: string, format: uuid } }
pinned_reviewers: { type: array, items: { type: string, format: uuid } }
required: [name, duration, flow_id]
Step:
allOf:
- { $ref: '#/components/schemas/BaseStep' }
- type: object
properties:
id: { type: integer }
type: { $ref: '#/components/schemas/StepType' }
required: [id, type]
FullStep:
allOf:
- { $ref: '#/components/schemas/Step' }
ActiveReview:
type: object
properties:
id: { type: integer }
name: { type: string }
required: [id, name]
UpdatedReviewer:
type: object
properties:
new_account: { type: string, format: uuid }
old_account: { type: string, format: uuid, nullable: true }
skip: { type: boolean }
required: [new_account, skip]
BaseStatus:
type: object
properties:
key: { $ref: '#/components/schemas/StatusKey' }
value: { type: string }
flow_id: { type: integer }
required: [value, flow_id]
Status:
allOf:
- { $ref: '#/components/schemas/BaseStatus' }
- type: object
properties:
id: { type: integer }
required: [id]
StatusForDocument:
type: object
properties:
key: { type: string }
value: { type: string }
id: { type: integer, nullable: true }
is_copied: { type: boolean, nullable: true }
bundles_history: { type: array, nullable: true, items: {} }
required: [key, value]
BaseDocument:
type: object
properties:
document_id: { type: integer, minimum: 1 }
bundle_id: { type: string, format: uuid }
review_id: { type: integer, minimum: 1 }
instance_id: { type: integer, nullable: true }
document_type: { type: string, nullable: true }
document_copied_id: { type: integer, nullable: true }
bundle_copied_id: { type: string, format: uuid, nullable: true }
required: [document_id, bundle_id, review_id]
Document:
allOf:
- { $ref: '#/components/schemas/BaseDocument' }
- type: object
properties:
id: { type: integer }
status: { $ref: '#/components/schemas/StatusForDocument' }
copy_to_folder_dst: { type: string, nullable: true }
copy_to_folder_label: { type: string, nullable: true }
is_accepted: { type: boolean, nullable: true }
statuses: { type: array, nullable: true, items: { $ref: '#/components/schemas/SetDocumentStatusRead' } }
acceptance_by_reviewer: { $ref: '#/components/schemas/AcceptanceByReviewer' }
required: [id]
ExtendDocument:
allOf:
- { $ref: '#/components/schemas/Document' }
- type: object
properties:
review: { type: string }
review_status: { type: string }
review_completed_at: { type: string, format: date-time, nullable: true }
flow_id: { type: integer }
review_comments: { type: array, items: { $ref: '#/components/schemas/ReviewComment' } }
required: [review, review_status, flow_id]
BaseUpdateDocument:
type: object
properties:
status: { $ref: '#/components/schemas/StatusForDocument' }
required: [status]
ChangeDocumentCopyPath:
type: object
properties:
id: { type: integer }
copy_to_folder_dst: { type: string }
copy_to_folder_label: { type: string }
required: [id, copy_to_folder_dst, copy_to_folder_label]
SetDocumentStatusUpdate:
type: object
properties:
status_id: { type: integer }
required: [status_id]
SetDocumentStatusRead:
type: object
properties:
id: { type: integer }
document_id: { type: integer }
user_id: { type: integer }
step: { $ref: '#/components/schemas/Step' }
status: { $ref: '#/components/schemas/Status' }
required: [id, document_id, user_id, step, status]
SetDocumentBundleIdAndStatus:
type: object
properties:
bundle_id: { type: string, format: uuid, nullable: true }
status: { $ref: '#/components/schemas/StatusForDocument' }
UpdateDocumentCopiedIds:
type: object
properties:
document_id: { type: integer }
document_copied_id: { type: integer }
bundle_copied_id: { type: string, format: uuid }
required: [document_id, document_copied_id, bundle_copied_id]
DocumentFilterRequest:
type: object
properties:
flow_ids: { type: string, nullable: true }
review_ids: { type: string, nullable: true }
document_ids: { type: string, nullable: true }
bundle_ids: { type: string, nullable: true }
review_status: { type: string, nullable: true }
document_types: { type: string, nullable: true }
document_copied_ids: { type: string, nullable: true }
bundle_copied_ids: { type: string, nullable: true }
full: { type: boolean, default: false }
ReviewComment:
type: object
properties:
comment: { type: string }
creator_id: { type: integer }
created_at: { type: string, format: date-time }
step_name: { type: string }
required: [comment, creator_id, created_at, step_name]
BaseCreateDocument:
type: object
properties:
document_id: { type: integer, minimum: 1 }
bundle_id: { type: string, format: uuid, nullable: true }
is_folder: { type: boolean, default: false }
instance_id: { type: integer, nullable: true }
required: [document_id]
BaseReview:
type: object
properties:
name: { type: string }
flow_id: { type: integer, minimum: 1 }
folder_dst: { type: string, nullable: true }
folder_label: { type: string, nullable: true }
resource_id: { type: string, format: uuid, nullable: true }
meta_data: { type: object, additionalProperties: true }
documents: { type: array, items: { $ref: '#/components/schemas/BaseCreateDocument' } }
comment: { type: string, nullable: true }
attributes: { type: object, additionalProperties: true }
checklist_results: { type: object, additionalProperties: { type: array, items: { type: integer } } }
required: [name, flow_id]
UpdateBaseReview:
type: object
properties:
name: { type: string }
flow_id: { type: integer, minimum: 1 }
folder_dst: { type: string, nullable: true }
folder_label: { type: string, nullable: true }
resource_id: { type: string, format: uuid, nullable: true }
meta_data: { type: object, additionalProperties: true }
attributes: { type: object, additionalProperties: true }
required: [name, flow_id]
PatchBaseReview:
type: object
properties:
name: { type: string, nullable: true }
resource_id: { type: string, format: uuid, nullable: true }
status: { $ref: '#/components/schemas/StateReview' }
attributes: { type: object, nullable: true, additionalProperties: true }
PatchCurrentReviewers:
type: object
properties:
was: { type: string, format: uuid, nullable: true }
became: { type: string, format: uuid, nullable: true }
required: { type: boolean, default: false }
force_next_step_reviewer: { type: boolean, default: false }
PatchMinReviewersOnStep:
type: object
properties:
new_value: { type: integer, minimum: 1 }
required: [new_value]
StatusForReview:
type: object
properties:
status: { $ref: '#/components/schemas/StateReview' }
comment: { type: string, nullable: true }
duration: { type: integer, minimum: 0, nullable: true }
reviewers: { type: array, nullable: true, items: { $ref: '#/components/schemas/PatchCurrentReviewers' } }
ReviewersUpdate:
type: object
properties:
id: { type: integer }
current_reviewers: { type: array, nullable: true, items: { type: string, format: uuid } }
completed_reviewers: { type: array, nullable: true, items: { type: string, format: uuid } }
current_signatories: { type: array, nullable: true, items: { type: integer } }
completed_signatories: { type: array, nullable: true, items: { type: integer } }
required: [id]
BulkReviewersUpdate:
type: object
properties:
reviews: { type: array, items: { $ref: '#/components/schemas/ReviewersUpdate' } }
required: [reviews]
Review:
type: object
description: |
Итоговая структура review. Сериализатор дополнительно раскладывает
user_actions по шагам flow и добавляет агрегаты `count_of_document`,
`Согласовано`, `Не согласовано`.
properties:
id: { type: integer }
name: { type: string }
status: { $ref: '#/components/schemas/StateReview' }
folder_dst: { type: string, nullable: true }
folder_label: { type: string, nullable: true }
current_step: { type: integer, nullable: true }
current_step_id: { type: integer }
current_step_expired_at: { type: string, format: date-time, nullable: true }
created_at: { type: string, format: date-time }
updated_at: { type: string, format: date-time }
expired_at: { type: string, format: date-time, nullable: true }
completed_at: { type: string, format: date-time, nullable: true }
min_reviewers: { type: integer, nullable: true }
creator_id: { type: integer }
resource_id: { type: string, format: uuid, nullable: true }
current_reviewers: { type: array, items: { type: string, format: uuid } }
completed_reviewers: { type: array, items: { type: string, format: uuid } }
current_signatories: { type: array, nullable: true, items: { type: integer } }
completed_signatories: { type: array, nullable: true, items: { type: integer } }
flow: { $ref: '#/components/schemas/FullFlow' }
meta_data: { type: object, additionalProperties: true }
current_reviewers_by_sa: { type: object, additionalProperties: { type: integer } }
current_reviewers_changes: { type: array, items: { type: string, format: uuid } }
time_tracking_mode: { $ref: '#/components/schemas/TimeTrackingMode' }
attributes: { type: object, additionalProperties: true }
checklist_results: { type: object, additionalProperties: { type: array, items: { type: integer } } }
force_next_step_reviewers: { type: array, items: { type: string, format: uuid } }
transmittal_ids: { type: array, items: { type: string, format: uuid } }
count_of_document: { type: integer }
required: [id, name, status, current_step_id, created_at, updated_at, creator_id]
ChecklistResultsUpdateRequest:
type: object
properties:
step_id: { type: integer }
add_results: { type: array, items: { type: integer } }
remove_results: { type: array, items: { type: integer } }
required: [step_id]
TransmittalForReviewCreated:
type: object
properties:
review_id: { type: integer }
transmittal_id: { type: string, format: uuid }
required: [review_id, transmittal_id]
BaseUserAction:
type: object
properties:
action: { type: string }
key: { type: string, nullable: true }
value: { type: string }
creator_id: { type: integer }
step_id: { type: integer }
document_id: { type: integer, nullable: true }
review_id: { type: integer }
required: [action, value, creator_id, step_id, review_id]
UserActions:
type: object
properties:
id: { type: integer }
action: { type: string }
key: { type: string, nullable: true }
value: { type: string }
creator_id: { type: integer }
created_at: { type: string, format: date-time }
step_id: { type: integer }
document_id: { type: integer, nullable: true }
review_id: { type: integer }
required: [id, action, value, creator_id, created_at, step_id, review_id]
ListUserActionsForDelete:
type: object
properties:
ids: { type: array, items: { type: integer } }
required: [ids]
UpdateUserAction:
type: object
properties:
key: { type: string, nullable: true }
value: { type: string, nullable: true }
Task:
type: object
properties:
id: { type: integer }
priority: { type: integer, minimum: 1, nullable: true }
start_date: { type: string, format: date-time }
duration: { type: integer, minimum: 0 }
end_date: { type: string, format: date-time }
review: { type: object, additionalProperties: true }
reviewer_id: { type: integer }
is_active: { type: boolean }
step_id: { type: integer, nullable: true }
review_expired_at: { type: string, format: date-time, nullable: true }
current_reviewers: { type: array, items: { type: integer } }
completed_reviewers: { type: array, items: { type: integer } }
required: [id, start_date, duration, end_date, reviewer_id, is_active]
TaskUpdatePriority:
type: object
properties:
priority: { type: integer, minimum: 1 }
required: [priority]
TaskUpdateDuration:
type: object
properties:
duration: { type: integer, minimum: 1 }
required: [duration]
TasksCount:
type: object
properties:
tasks_count: { type: integer }
required: [tasks_count]
ReviewerMaxTaskEndDate:
type: object
properties:
reviewer_id: { type: integer }
max_task_end_date: { type: string, format: date-time }
required: [reviewer_id, max_task_end_date]
MainFilterPostRequest:
type: object
description: Схема фильтрации для POST /flows/filter/, /reviews/filter/ и подсчётов.
properties:
created_at_after: { type: string, nullable: true }
created_at_before: { type: string, nullable: true }
updated_at_after: { type: string, nullable: true }
updated_at_before: { type: string, nullable: true }
expired_before: { type: string, nullable: true }
current_step_expired_before: { type: string, nullable: true }
resource_id: { type: array, nullable: true, items: { type: string } }
flow_id: { type: array, nullable: true, items: { type: string } }
launcher_id: { type: array, nullable: true, items: { type: string } }
reviewers_ids: { type: array, nullable: true, items: { type: string } }
reviewers_sa: { type: array, nullable: true, items: { type: string } }
launcher_sa: { type: array, nullable: true, items: { type: string } }
action: { type: array, nullable: true, items: { type: string } }
approvers: { type: array, nullable: true, items: { type: string } }
step_watchers: { type: array, nullable: true, items: { type: string } }
reviewers: { type: array, nullable: true, items: { type: string } }
current_reviewers: { type: array, nullable: true, items: { type: string } }
completed_reviewers: { type: array, nullable: true, items: { type: string } }
signatories: { type: array, nullable: true, items: { type: string } }
current_signatories: { type: array, nullable: true, items: { type: string } }
completed_signatories: { type: array, nullable: true, items: { type: string } }
company_id: { type: string, nullable: true }
creator_id: { type: string, nullable: true }
changer_id: { type: string, nullable: true }
name: { type: string, nullable: true }
status: { type: array, nullable: true, items: { $ref: '#/components/schemas/StateReview' } }
flow_type: { $ref: '#/components/schemas/FlowType' }
full: { type: boolean, default: false }
is_active: { type: boolean, nullable: true }
enable_stamp: { type: boolean, nullable: true }
enable_signature: { type: boolean, nullable: true }
enable_qr_code: { type: boolean, nullable: true }
has_reviewers: { type: boolean, nullable: true }
attributes: { type: object, nullable: true, additionalProperties: true }