964 lines
33 KiB
YAML
964 lines
33 KiB
YAML
openapi: 3.0.3
|
||
|
||
info:
|
||
title: Checklists
|
||
version: "0.1.0"
|
||
description: |
|
||
REST API сервиса **checklists-backend** — управление чек-листами
|
||
(`Checklist`) и их результатами (`ChecklistResult`).
|
||
|
||
Сервис написан на Python (**FastAPI** + ORM **Piccolo**). Приложение
|
||
собирается фабрикой `create_app` в `src/app/http.py`. Роутинг состоит из
|
||
двух групп:
|
||
|
||
- публичный API — префикс `/api/v1` (`controller/http/api`);
|
||
- внутренний API — префикс `/internal/v1` (`controller/http/internal_api`),
|
||
предназначен для вызовов внутри кластера (через ingress не публикуется).
|
||
|
||
Интерактивная документация (ReDoc) доступна по `/docs/`, схема —
|
||
по `/openapi.json/` (с учётом `root_path`). Админ-панель Piccolo монтируется
|
||
по `/admin/` при `HTTP_APP_ADMIN_ENABLE=true`.
|
||
|
||
### Аутентификация
|
||
Аутентификация включается флагом `JWT_AUTH_ENABLE`. При включённом
|
||
`JWTAuthMiddleware` (`controller/http/middlewares.py`) публичные эндпоинты
|
||
требуют заголовок `Authorization: Bearer <jwt>`. Поддерживаются два режима:
|
||
|
||
1. **Zitadel** — если передан дополнительный заголовок `identity`
|
||
(`Identity <jwt>`), полезная нагрузка (`user_id`, `company_ids`) берётся
|
||
из этого токена (`urn:zitadel:iam:user:metadata`).
|
||
2. **sarex-backend** — если заголовка `identity` нет, разбирается основной
|
||
токен (алгоритм `RS512`, ключ `JWT_AUTH_PUBLIC_KEY`).
|
||
|
||
В обоих режимах разбор выполняется с `verify_signature=False` — подпись на
|
||
уровне приложения не проверяется, доверие обеспечивается сетевым слоем.
|
||
Внутренние эндпоинты (`/internal/*`) и пути `/docs/`, `/openapi.json/`,
|
||
`/admin/*` аутентификацию пропускают. При `JWT_AUTH_ENABLE=false` middleware
|
||
не подключается и используется дефолтный пользователь.
|
||
|
||
### Пагинация
|
||
Списочные ответы используют пагинацию limit/offset и оборачиваются в
|
||
`PaginatedResponse` — `{ count, result }`, где `count` — число объектов в
|
||
текущем ответе, `result` — сами объекты. Параметры: `limit` (по умолчанию
|
||
`100`), `offset` (по умолчанию `0`), сортировка — `order_by`/`ascending`.
|
||
|
||
### Обработка ошибок
|
||
Доменные ошибки (`controller/http/errors.py`) возвращаются как
|
||
`application/json` с телом `{ "detail": "<текст>" }`. Маппинг:
|
||
|
||
- `ResourceNotPermittedError` → **403**;
|
||
- `ResourceNotFoundError` → **404**;
|
||
- `StateConflictError` → **409**;
|
||
- `ChecklistResultValidationError` → **422**;
|
||
- прочее → **500**.
|
||
|
||
Ошибки валидации тела/параметров запроса (Pydantic) отдаются FastAPI в
|
||
стандартном формате `422` (`HTTPValidationError`). Все публичные эндпоинты
|
||
(`/api/*`) при невалидном/отсутствующем токене возвращают `401`.
|
||
|
||
contact:
|
||
name: checklists-backend
|
||
url: https://gitlab/proc/checklists-backend
|
||
|
||
servers:
|
||
- url: https://api.sarex.io/checklists
|
||
description: Production (ingress, root_path=/checklists)
|
||
- url: https://stage-api.sarex.io/checklists
|
||
description: Stage (ingress, root_path=/checklists)
|
||
- url: http://checklists-backend-service.proc.svc.cluster.local
|
||
description: Внутрикластерный адрес (ClusterIP, порт 80 → 8000). Единственный способ достучаться до /internal/v1
|
||
- url: http://localhost:8000
|
||
description: Локальный запуск (Uvicorn, порт по умолчанию 8000)
|
||
|
||
tags:
|
||
- name: Checklists
|
||
description: Чек-листы — создание, просмотр, поиск, удаление
|
||
- name: Checklist results
|
||
description: Результаты чек-листов — создание, просмотр, обновление, удаление
|
||
- name: internal
|
||
description: Внутренние эндпоинты (только внутри кластера)
|
||
|
||
security:
|
||
- bearerAuth: []
|
||
|
||
paths:
|
||
# ==========================================================================
|
||
# Checklists
|
||
# ==========================================================================
|
||
/api/v1/checklists/:
|
||
post:
|
||
tags: [Checklists]
|
||
summary: Создать чек-лист
|
||
operationId: createChecklist
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ChecklistCreate'
|
||
responses:
|
||
'201':
|
||
description: Созданный чек-лист
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ChecklistReadFull'
|
||
'401': { $ref: '#/components/responses/Unauthorized' }
|
||
'403': { $ref: '#/components/responses/Forbidden' }
|
||
'422': { $ref: '#/components/responses/ValidationError' }
|
||
get:
|
||
tags: [Checklists]
|
||
summary: Список чек-листов
|
||
operationId: listChecklists
|
||
parameters:
|
||
- { $ref: '#/components/parameters/OrderByChecklist' }
|
||
- { $ref: '#/components/parameters/Ascending' }
|
||
- { $ref: '#/components/parameters/Limit' }
|
||
- { $ref: '#/components/parameters/Offset' }
|
||
- name: company_id
|
||
in: query
|
||
required: false
|
||
description: Фильтр по ID компаний
|
||
schema:
|
||
type: array
|
||
nullable: true
|
||
items:
|
||
type: integer
|
||
minimum: 1
|
||
responses:
|
||
'200':
|
||
description: Страница чек-листов (компактное представление)
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/PaginatedResponse_ChecklistReadCompact'
|
||
'401': { $ref: '#/components/responses/Unauthorized' }
|
||
'422': { $ref: '#/components/responses/ValidationError' }
|
||
|
||
/api/v1/checklists/filter/:
|
||
post:
|
||
tags: [Checklists]
|
||
summary: Список чек-листов (фильтры в теле)
|
||
description: Аналог `GET /api/v1/checklists/`, но фильтры и пагинация передаются в теле запроса.
|
||
operationId: filterChecklists
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ChecklistFiltersWithPagination'
|
||
responses:
|
||
'200':
|
||
description: Страница чек-листов (компактное представление)
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/PaginatedResponse_ChecklistReadCompact'
|
||
'401': { $ref: '#/components/responses/Unauthorized' }
|
||
'422': { $ref: '#/components/responses/ValidationError' }
|
||
|
||
/api/v1/checklists/{instance_id}/:
|
||
get:
|
||
tags: [Checklists]
|
||
summary: Чек-лист по id
|
||
operationId: getChecklist
|
||
parameters:
|
||
- { $ref: '#/components/parameters/InstanceId' }
|
||
responses:
|
||
'200':
|
||
description: Чек-лист (полное представление)
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ChecklistReadFull'
|
||
'401': { $ref: '#/components/responses/Unauthorized' }
|
||
'403': { $ref: '#/components/responses/Forbidden' }
|
||
'404': { $ref: '#/components/responses/NotFound' }
|
||
'422': { $ref: '#/components/responses/ValidationError' }
|
||
delete:
|
||
tags: [Checklists]
|
||
summary: Удалить чек-лист
|
||
operationId: deleteChecklist
|
||
parameters:
|
||
- { $ref: '#/components/parameters/InstanceId' }
|
||
responses:
|
||
'204':
|
||
description: Чек-лист удалён
|
||
'401': { $ref: '#/components/responses/Unauthorized' }
|
||
'403': { $ref: '#/components/responses/Forbidden' }
|
||
'404': { $ref: '#/components/responses/NotFound' }
|
||
'422': { $ref: '#/components/responses/ValidationError' }
|
||
|
||
# ==========================================================================
|
||
# Checklist results
|
||
# ==========================================================================
|
||
/api/v1/results/:
|
||
post:
|
||
tags: [Checklist results]
|
||
summary: Создать результат чек-листа
|
||
description: |
|
||
Создаёт результат по `checklist_id`. Данные чек-листа переносятся бэком
|
||
автоматически; в теле передаются метаданные и список значений инпутов
|
||
(`input_values`).
|
||
operationId: createChecklistResult
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ChecklistResultCreate'
|
||
responses:
|
||
'201':
|
||
description: Созданный результат
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ChecklistResultRead'
|
||
'401': { $ref: '#/components/responses/Unauthorized' }
|
||
'403': { $ref: '#/components/responses/Forbidden' }
|
||
'422': { $ref: '#/components/responses/ValidationError' }
|
||
get:
|
||
tags: [Checklist results]
|
||
summary: Список результатов чек-листов
|
||
operationId: listChecklistResults
|
||
parameters:
|
||
- { $ref: '#/components/parameters/OrderByChecklistResult' }
|
||
- { $ref: '#/components/parameters/Ascending' }
|
||
- { $ref: '#/components/parameters/Limit' }
|
||
- { $ref: '#/components/parameters/Offset' }
|
||
- { $ref: '#/components/parameters/FilterResultId' }
|
||
- { $ref: '#/components/parameters/FilterChecklistId' }
|
||
- { $ref: '#/components/parameters/FilterCreatorId' }
|
||
- { $ref: '#/components/parameters/FilterIsDraft' }
|
||
- { $ref: '#/components/parameters/FilterIsLocked' }
|
||
responses:
|
||
'200':
|
||
description: Страница результатов
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/PaginatedResponse_ChecklistResultRead'
|
||
'401': { $ref: '#/components/responses/Unauthorized' }
|
||
'422': { $ref: '#/components/responses/ValidationError' }
|
||
|
||
/api/v1/results/{instance_id}/:
|
||
get:
|
||
tags: [Checklist results]
|
||
summary: Результат чек-листа по id
|
||
operationId: getChecklistResult
|
||
parameters:
|
||
- { $ref: '#/components/parameters/InstanceId' }
|
||
responses:
|
||
'200':
|
||
description: Результат чек-листа
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ChecklistResultRead'
|
||
'401': { $ref: '#/components/responses/Unauthorized' }
|
||
'403': { $ref: '#/components/responses/Forbidden' }
|
||
'404': { $ref: '#/components/responses/NotFound' }
|
||
'422': { $ref: '#/components/responses/ValidationError' }
|
||
patch:
|
||
tags: [Checklist results]
|
||
summary: Обновить результат чек-листа
|
||
description: Частичное обновление значений инпутов и флага черновика.
|
||
operationId: updateChecklistResult
|
||
parameters:
|
||
- { $ref: '#/components/parameters/InstanceId' }
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ChecklistResultPartialUpdate'
|
||
responses:
|
||
'200':
|
||
description: Обновлённый результат
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ChecklistResultRead'
|
||
'401': { $ref: '#/components/responses/Unauthorized' }
|
||
'403': { $ref: '#/components/responses/Forbidden' }
|
||
'404': { $ref: '#/components/responses/NotFound' }
|
||
'422': { $ref: '#/components/responses/ValidationError' }
|
||
delete:
|
||
tags: [Checklist results]
|
||
summary: Удалить результат чек-листа
|
||
operationId: deleteChecklistResult
|
||
parameters:
|
||
- { $ref: '#/components/parameters/InstanceId' }
|
||
responses:
|
||
'204':
|
||
description: Результат удалён
|
||
'401': { $ref: '#/components/responses/Unauthorized' }
|
||
'403': { $ref: '#/components/responses/Forbidden' }
|
||
'404': { $ref: '#/components/responses/NotFound' }
|
||
'422': { $ref: '#/components/responses/ValidationError' }
|
||
|
||
# ==========================================================================
|
||
# Internal
|
||
# ==========================================================================
|
||
/internal/v1/results/:
|
||
get:
|
||
tags: [internal]
|
||
summary: Список результатов (внутренний)
|
||
description: Внутрикластерный эндпоинт. Аутентификация на уровне приложения не выполняется.
|
||
operationId: internalListChecklistResults
|
||
security: []
|
||
parameters:
|
||
- { $ref: '#/components/parameters/OrderByChecklistResult' }
|
||
- { $ref: '#/components/parameters/Ascending' }
|
||
- { $ref: '#/components/parameters/Limit' }
|
||
- { $ref: '#/components/parameters/Offset' }
|
||
- { $ref: '#/components/parameters/FilterResultId' }
|
||
- { $ref: '#/components/parameters/FilterChecklistId' }
|
||
- { $ref: '#/components/parameters/FilterCreatorId' }
|
||
- { $ref: '#/components/parameters/FilterIsDraft' }
|
||
- { $ref: '#/components/parameters/FilterIsLocked' }
|
||
responses:
|
||
'200':
|
||
description: Страница результатов
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/PaginatedResponse_ChecklistResultRead'
|
||
'422': { $ref: '#/components/responses/ValidationError' }
|
||
|
||
/internal/v1/results/lock:
|
||
patch:
|
||
tags: [internal]
|
||
summary: Массовое обновление блокировки результатов
|
||
description: Устанавливает флаг `is_locked` для списка результатов по их id. Внутрикластерный эндпоинт.
|
||
operationId: internalBulkUpdateLock
|
||
security: []
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ChecklistResultBulkLockingPartialUpdate'
|
||
responses:
|
||
'204':
|
||
description: Флаги блокировки обновлены
|
||
'422': { $ref: '#/components/responses/ValidationError' }
|
||
|
||
components:
|
||
securitySchemes:
|
||
bearerAuth:
|
||
type: http
|
||
scheme: bearer
|
||
bearerFormat: JWT
|
||
description: |
|
||
JWT в заголовке `Authorization: Bearer <token>`. Алгоритм `RS512`,
|
||
ключ `JWT_AUTH_PUBLIC_KEY`. Разбор выполняется без проверки подписи
|
||
(`verify_signature=False`).
|
||
identityToken:
|
||
type: apiKey
|
||
in: header
|
||
name: identity
|
||
description: |
|
||
Опциональный заголовок `identity` (`Identity <jwt>`) для режима Zitadel.
|
||
При его наличии полезная нагрузка (`user_id`, `company_ids`) берётся из
|
||
этого токена.
|
||
|
||
parameters:
|
||
InstanceId:
|
||
name: instance_id
|
||
in: path
|
||
required: true
|
||
schema:
|
||
type: integer
|
||
Limit:
|
||
name: limit
|
||
in: query
|
||
required: false
|
||
description: Максимальное количество объектов
|
||
schema:
|
||
type: integer
|
||
default: 100
|
||
Offset:
|
||
name: offset
|
||
in: query
|
||
required: false
|
||
description: Количество пропущенных объектов
|
||
schema:
|
||
type: integer
|
||
default: 0
|
||
Ascending:
|
||
name: ascending
|
||
in: query
|
||
required: false
|
||
description: Сортировка по возрастанию
|
||
schema:
|
||
type: boolean
|
||
default: true
|
||
OrderByChecklist:
|
||
name: order_by
|
||
in: query
|
||
required: false
|
||
description: Поле для сортировки
|
||
schema:
|
||
type: string
|
||
enum: [id]
|
||
default: id
|
||
OrderByChecklistResult:
|
||
name: order_by
|
||
in: query
|
||
required: false
|
||
description: Поле для сортировки
|
||
schema:
|
||
type: string
|
||
enum: [id]
|
||
default: id
|
||
FilterResultId:
|
||
name: id
|
||
in: query
|
||
required: false
|
||
description: Фильтр по ID результата
|
||
schema:
|
||
type: array
|
||
nullable: true
|
||
items:
|
||
type: integer
|
||
minimum: 1
|
||
FilterChecklistId:
|
||
name: checklist_id
|
||
in: query
|
||
required: false
|
||
description: Фильтр по ID чек-листа
|
||
schema:
|
||
type: array
|
||
nullable: true
|
||
items:
|
||
type: integer
|
||
minimum: 1
|
||
FilterCreatorId:
|
||
name: creator_id
|
||
in: query
|
||
required: false
|
||
description: Фильтр по ID создателя результата
|
||
schema:
|
||
type: array
|
||
nullable: true
|
||
items:
|
||
type: integer
|
||
minimum: 1
|
||
FilterIsDraft:
|
||
name: is_draft
|
||
in: query
|
||
required: false
|
||
description: Признак «чернового» результата
|
||
schema:
|
||
type: boolean
|
||
nullable: true
|
||
FilterIsLocked:
|
||
name: is_locked
|
||
in: query
|
||
required: false
|
||
description: Признак блокировки результата
|
||
schema:
|
||
type: boolean
|
||
nullable: true
|
||
|
||
responses:
|
||
Unauthorized:
|
||
description: Токен не предоставлен или невалиден
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/HTTPError'
|
||
Forbidden:
|
||
description: Недостаточно прав
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/HTTPError'
|
||
NotFound:
|
||
description: Запрошенный ресурс не найден
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/HTTPError'
|
||
Conflict:
|
||
description: Конфликт состояния
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/HTTPError'
|
||
ValidationError:
|
||
description: |
|
||
Ошибка валидации тела/параметров запроса (FastAPI/Pydantic) либо
|
||
доменная ошибка валидации результата (`{ detail }`).
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/HTTPValidationError'
|
||
|
||
schemas:
|
||
# ---- Общие ----
|
||
HTTPError:
|
||
type: object
|
||
properties:
|
||
detail:
|
||
type: string
|
||
description: Описание ошибки
|
||
required: [detail]
|
||
|
||
HTTPValidationError:
|
||
type: object
|
||
properties:
|
||
detail:
|
||
type: array
|
||
items:
|
||
$ref: '#/components/schemas/ValidationError'
|
||
|
||
ValidationError:
|
||
type: object
|
||
properties:
|
||
loc:
|
||
type: array
|
||
items:
|
||
anyOf:
|
||
- type: string
|
||
- type: integer
|
||
msg:
|
||
type: string
|
||
type:
|
||
type: string
|
||
required: [loc, msg, type]
|
||
|
||
# ---- Ограничения инпутов ----
|
||
InputChoiceOption:
|
||
type: object
|
||
properties:
|
||
id:
|
||
type: string
|
||
format: uuid
|
||
description: Уникальный идентификатор опции
|
||
name:
|
||
type: string
|
||
description: Название опции
|
||
example: "Да"
|
||
order:
|
||
type: integer
|
||
description: Порядковый номер опции
|
||
example: 1
|
||
color:
|
||
type: string
|
||
nullable: true
|
||
description: Цвет опции (hex или именованный html-цвет)
|
||
example: "#00aa00"
|
||
selected_tip:
|
||
type: string
|
||
nullable: true
|
||
description: Заметка при выборе опции
|
||
example: 'Рекомендуется добавить комментарий при ответе "Нет"'
|
||
alt_name:
|
||
type: string
|
||
nullable: true
|
||
description: Название опции для записи в историю
|
||
example: "Одобрено"
|
||
required: [id, name, order, selected_tip]
|
||
|
||
InputChoiceConstraints:
|
||
type: object
|
||
properties:
|
||
type:
|
||
type: string
|
||
enum: [choice]
|
||
options:
|
||
type: array
|
||
nullable: true
|
||
description: Список опций для выбора
|
||
items:
|
||
$ref: '#/components/schemas/InputChoiceOption'
|
||
required: [type, options]
|
||
|
||
InputStringConstraints:
|
||
type: object
|
||
properties:
|
||
type:
|
||
type: string
|
||
enum: [string]
|
||
min_length:
|
||
type: integer
|
||
minimum: 0
|
||
default: 0
|
||
description: Минимально допустимое количество символов
|
||
max_length:
|
||
type: integer
|
||
minimum: 1
|
||
default: 1000
|
||
description: Максимально допустимое количество символов
|
||
required: [type]
|
||
|
||
InputConstraints:
|
||
oneOf:
|
||
- $ref: '#/components/schemas/InputChoiceConstraints'
|
||
- $ref: '#/components/schemas/InputStringConstraints'
|
||
discriminator:
|
||
propertyName: type
|
||
mapping:
|
||
choice: '#/components/schemas/InputChoiceConstraints'
|
||
string: '#/components/schemas/InputStringConstraints'
|
||
|
||
# ---- Чек-лист (создание) ----
|
||
ChecklistInputCreate:
|
||
type: object
|
||
properties:
|
||
name:
|
||
type: string
|
||
maxLength: 1024
|
||
description: Название
|
||
example: "Комментарий"
|
||
order:
|
||
type: integer
|
||
description: Порядковый номер
|
||
is_required:
|
||
type: boolean
|
||
description: Обязательное ли поле для заполнения
|
||
constraints:
|
||
$ref: '#/components/schemas/InputConstraints'
|
||
required: [name, order, is_required, constraints]
|
||
|
||
ChecklistItemCreate:
|
||
type: object
|
||
properties:
|
||
description:
|
||
type: string
|
||
maxLength: 8192
|
||
description: Описание шага
|
||
order:
|
||
type: integer
|
||
description: Порядковый номер
|
||
inputs:
|
||
type: array
|
||
description: Список элементов ввода
|
||
items:
|
||
$ref: '#/components/schemas/ChecklistInputCreate'
|
||
required: [description, order, inputs]
|
||
|
||
ChecklistCreate:
|
||
type: object
|
||
properties:
|
||
name:
|
||
type: string
|
||
maxLength: 250
|
||
description: Название
|
||
example: "Чек-лист проверки документов"
|
||
description:
|
||
type: string
|
||
maxLength: 8192
|
||
description: Описание чек-листа
|
||
company_id:
|
||
type: integer
|
||
minimum: 1
|
||
description: ID компании
|
||
example: 1
|
||
items:
|
||
type: array
|
||
description: Список шагов чек-листа
|
||
items:
|
||
$ref: '#/components/schemas/ChecklistItemCreate'
|
||
required: [name, description, company_id, items]
|
||
|
||
# ---- Чек-лист (чтение) ----
|
||
ChecklistInputRead:
|
||
type: object
|
||
properties:
|
||
id:
|
||
type: integer
|
||
example: 1
|
||
created_at:
|
||
type: string
|
||
format: date-time
|
||
updated_at:
|
||
type: string
|
||
format: date-time
|
||
name:
|
||
type: string
|
||
maxLength: 1024
|
||
order:
|
||
type: integer
|
||
is_required:
|
||
type: boolean
|
||
constraints:
|
||
$ref: '#/components/schemas/InputConstraints'
|
||
required: [id, created_at, updated_at, name, order, is_required, constraints]
|
||
|
||
ChecklistItemRead:
|
||
type: object
|
||
properties:
|
||
id:
|
||
type: integer
|
||
created_at:
|
||
type: string
|
||
format: date-time
|
||
updated_at:
|
||
type: string
|
||
format: date-time
|
||
description:
|
||
type: string
|
||
maxLength: 8192
|
||
order:
|
||
type: integer
|
||
inputs:
|
||
type: array
|
||
description: Список элементов ввода
|
||
items:
|
||
$ref: '#/components/schemas/ChecklistInputRead'
|
||
required: [id, created_at, updated_at, description, order, inputs]
|
||
|
||
ChecklistReadCompact:
|
||
type: object
|
||
properties:
|
||
id:
|
||
type: integer
|
||
example: 1
|
||
created_at:
|
||
type: string
|
||
format: date-time
|
||
updated_at:
|
||
type: string
|
||
format: date-time
|
||
name:
|
||
type: string
|
||
description:
|
||
type: string
|
||
company_id:
|
||
type: integer
|
||
minimum: 1
|
||
required: [id, created_at, updated_at, name, description, company_id]
|
||
|
||
ChecklistReadFull:
|
||
allOf:
|
||
- $ref: '#/components/schemas/ChecklistReadCompact'
|
||
- type: object
|
||
properties:
|
||
items:
|
||
type: array
|
||
description: Список шагов чек-листа
|
||
items:
|
||
$ref: '#/components/schemas/ChecklistItemRead'
|
||
required: [items]
|
||
|
||
ChecklistFiltersWithPagination:
|
||
type: object
|
||
properties:
|
||
order_by:
|
||
type: string
|
||
enum: [id]
|
||
default: id
|
||
ascending:
|
||
type: boolean
|
||
default: true
|
||
limit:
|
||
type: integer
|
||
default: 100
|
||
offset:
|
||
type: integer
|
||
default: 0
|
||
company_id:
|
||
type: array
|
||
nullable: true
|
||
description: Фильтр по ID компаний
|
||
items:
|
||
type: integer
|
||
minimum: 1
|
||
|
||
# ---- Результаты чек-листов ----
|
||
ChecklistResultInputCreate:
|
||
type: object
|
||
properties:
|
||
input_id:
|
||
type: integer
|
||
description: ID инпута, для которого устанавливается значение
|
||
example: 1
|
||
value:
|
||
description: 'Значение (тип зависит от инпута: id опции для choice, строка для string)'
|
||
nullable: true
|
||
example: "Да"
|
||
required: [input_id, value]
|
||
|
||
ChecklistResultCreate:
|
||
type: object
|
||
properties:
|
||
entity_type:
|
||
type: string
|
||
description: Сущность, для которой создан результат
|
||
example: "review"
|
||
entity_id:
|
||
type: string
|
||
description: ID сущности, для которой создан результат
|
||
example: "1"
|
||
checklist_id:
|
||
type: integer
|
||
description: ID чек-листа
|
||
example: 1
|
||
accessible_by:
|
||
type: array
|
||
description: SA ID роли/места/пользователя, которым доступен результат
|
||
items:
|
||
type: string
|
||
format: uuid
|
||
is_draft:
|
||
type: boolean
|
||
description: Является ли результат черновым
|
||
input_values:
|
||
type: array
|
||
description: Список устанавливаемых значений
|
||
items:
|
||
$ref: '#/components/schemas/ChecklistResultInputCreate'
|
||
required: [entity_type, entity_id, checklist_id, accessible_by, is_draft, input_values]
|
||
|
||
ChecklistResultPartialUpdate:
|
||
type: object
|
||
properties:
|
||
input_values:
|
||
type: array
|
||
description: Список устанавливаемых значений
|
||
items:
|
||
$ref: '#/components/schemas/ChecklistResultInputCreate'
|
||
is_draft:
|
||
type: boolean
|
||
description: Является ли результат черновым
|
||
required: [input_values, is_draft]
|
||
|
||
ChecklistResultInput:
|
||
type: object
|
||
properties:
|
||
input_id:
|
||
type: integer
|
||
description: ID инпута, для которого создан результат
|
||
name:
|
||
type: string
|
||
description: Название
|
||
order:
|
||
type: integer
|
||
description: Порядковый номер
|
||
value:
|
||
type: string
|
||
nullable: true
|
||
description: Введённое значение (строка или UUID выбранной опции)
|
||
value_text:
|
||
type: string
|
||
nullable: true
|
||
description: Текстовое представление введённого значения
|
||
color:
|
||
type: string
|
||
nullable: true
|
||
description: Цвет значения
|
||
required: [input_id, name, order, value, value_text, color]
|
||
|
||
ChecklistResultItem:
|
||
type: object
|
||
properties:
|
||
description:
|
||
type: string
|
||
description: Описание шага
|
||
order:
|
||
type: integer
|
||
description: Порядковый номер
|
||
inputs:
|
||
type: array
|
||
description: Список введённых значений
|
||
items:
|
||
$ref: '#/components/schemas/ChecklistResultInput'
|
||
required: [description, order, inputs]
|
||
|
||
ChecklistResultRead:
|
||
type: object
|
||
properties:
|
||
id:
|
||
type: integer
|
||
example: 1
|
||
created_at:
|
||
type: string
|
||
format: date-time
|
||
updated_at:
|
||
type: string
|
||
format: date-time
|
||
entity_type:
|
||
type: string
|
||
example: "review"
|
||
entity_id:
|
||
type: string
|
||
example: "1"
|
||
checklist_id:
|
||
type: integer
|
||
accessible_by:
|
||
type: array
|
||
items:
|
||
type: string
|
||
format: uuid
|
||
is_draft:
|
||
type: boolean
|
||
company_id:
|
||
type: integer
|
||
description: ID компании
|
||
is_locked:
|
||
type: boolean
|
||
description: Заблокирован ли результат для изменений
|
||
items:
|
||
type: array
|
||
description: Список шагов чек-листа
|
||
items:
|
||
$ref: '#/components/schemas/ChecklistResultItem'
|
||
required:
|
||
- id
|
||
- created_at
|
||
- updated_at
|
||
- entity_type
|
||
- entity_id
|
||
- checklist_id
|
||
- accessible_by
|
||
- is_draft
|
||
- company_id
|
||
- is_locked
|
||
- items
|
||
|
||
ChecklistResultBulkLockingPartialUpdate:
|
||
type: object
|
||
properties:
|
||
ids:
|
||
type: array
|
||
description: Список id результатов, которым нужно обновить флаг
|
||
items:
|
||
type: integer
|
||
example: [1, 2, 3]
|
||
is_locked:
|
||
type: boolean
|
||
description: Заблокирован ли результат для изменений
|
||
required: [ids, is_locked]
|
||
|
||
# ---- Пагинация ----
|
||
PaginatedResponse_ChecklistReadCompact:
|
||
type: object
|
||
properties:
|
||
count:
|
||
type: integer
|
||
description: Количество объектов
|
||
example: 1
|
||
result:
|
||
type: array
|
||
description: Объекты
|
||
items:
|
||
$ref: '#/components/schemas/ChecklistReadCompact'
|
||
required: [count, result]
|
||
|
||
PaginatedResponse_ChecklistResultRead:
|
||
type: object
|
||
properties:
|
||
count:
|
||
type: integer
|
||
description: Количество объектов
|
||
example: 1
|
||
result:
|
||
type: array
|
||
description: Объекты
|
||
items:
|
||
$ref: '#/components/schemas/ChecklistResultRead'
|
||
required: [count, result]
|