1244 lines
44 KiB
YAML
1244 lines
44 KiB
YAML
openapi: 3.0.3
|
||
|
||
info:
|
||
title: Inspections
|
||
version: "0.1.0"
|
||
description: |
|
||
REST API сервиса **inspections-backend** (`proc/inspections-backend`) — управление
|
||
событиями/инспекциями (создание, редактирование, поиск, экспорт), их типами,
|
||
статусами, атрибутами, историей изменений и расчётом доступности исполнителей.
|
||
|
||
Сервис написан на Python (**FastAPI** + **Piccolo ORM**, PostgreSQL). Приложение
|
||
собирается фабрикой `create_app` в `src/app/http.py`. Помимо HTTP-приложения есть
|
||
отдельный процесс-консьюмер Kafka (`src/app/kafka.py`), который слушает события
|
||
EAV-ассетов; в OpenAPI он не отражён.
|
||
|
||
Роутинг: корневой роутер имеет префикс `/api` (`controller/http/api/router.py`),
|
||
вложенный — `/v1` (`controller/http/api/v1/router.py`), ресурс инспекций —
|
||
`/inspections` (`controller/http/api/v1/inspection.py`). За реверс-прокси
|
||
добавляется `root_path` (в k8s — `/inspections`, задаётся `HTTP_APP_ROOT_PATH`).
|
||
|
||
Схема OpenAPI отдаётся по `/openapi.json/`, документация ReDoc — по `/docs/`
|
||
(Swagger UI отключён). Админ-панель Piccolo монтируется по `/admin/`
|
||
(если `HTTP_APP_ADMIN_ENABLE=true`).
|
||
|
||
### Аутентификация
|
||
Если включён middleware (`JWT_AUTH_ENABLE=true`), все запросы, кроме `/docs/`,
|
||
`/openapi.json/`, `/admin/`, `/internal/`, требуют заголовок
|
||
`Authorization: Bearer <jwt>`. Поддерживается дополнительный заголовок
|
||
`identity` (метаданные Zitadel): при его наличии полезная нагрузка берётся из
|
||
него, иначе — из `Authorization`. Токен декодируется **без проверки подписи**
|
||
(`verify_signature=False`) — доверие обеспечивается сетевым слоем/ingress.
|
||
При отсутствии заголовка `Authorization` middleware возвращает `401`.
|
||
|
||
При `JWT_AUTH_ENABLE=false` middleware не подключается и используется
|
||
захардкоженный дефолтный пользователь (`entity/context.py`) — режим локальной
|
||
разработки.
|
||
|
||
### Права доступа
|
||
Операции защищены правами (`InspectionPermission`): `core.can_view_inspections`,
|
||
`core.can_create_inspection`, `core.can_edit_inspection`,
|
||
`core.can_delete_inspection`, `core.can_view_all_inspections`. Права берутся из
|
||
токена; при их отсутствии проверяются права по сервисным аккаунтам на конкретный
|
||
тип события. Недостаток прав — ответ `403`.
|
||
|
||
### Пагинация
|
||
Списочные ответы используют limit/offset-пагинацию и оборачиваются в `Page`
|
||
(`{ count, result }`). Сортировка задаётся параметрами `order_by` и `ascending`.
|
||
|
||
### Обработка ошибок
|
||
Доменные ошибки маппятся на HTTP-статусы (`controller/http/errors.py`) и
|
||
возвращаются как `{ "detail": "<текст>" }`. Ошибки валидации тела/параметров
|
||
(Pydantic) отдаются FastAPI в стандартном формате `422`.
|
||
|
||
servers:
|
||
- url: https://api.sarex.io/inspections
|
||
description: production
|
||
- url: https://api.preprod.sarex.io/inspections
|
||
description: preprod
|
||
- url: https://stage-api.sarex.io/inspections
|
||
description: stage
|
||
- url: http://localhost:8000
|
||
description: local (без root_path)
|
||
|
||
tags:
|
||
- name: Inspections
|
||
description: События / инспекции
|
||
- name: Mobile app
|
||
description: Версии мобильного приложения
|
||
|
||
security:
|
||
- bearerAuth: []
|
||
|
||
paths:
|
||
/api/v1/mobile-app/version/:
|
||
get:
|
||
tags: [Mobile app]
|
||
summary: Версии мобильного приложения
|
||
operationId: get_mobile_app_version
|
||
responses:
|
||
"200":
|
||
description: Текущая, рекомендуемая и минимально требуемая версии
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: "#/components/schemas/MobileAppVersion"
|
||
"401":
|
||
$ref: "#/components/responses/Unauthorized"
|
||
|
||
/api/v1/inspections/:
|
||
get:
|
||
tags: [Inspections]
|
||
summary: Список событий
|
||
description: Требует право `core.can_view_inspections`.
|
||
operationId: get_all
|
||
parameters:
|
||
- $ref: "#/components/parameters/OrderByInspection"
|
||
- $ref: "#/components/parameters/Ascending"
|
||
- $ref: "#/components/parameters/Limit"
|
||
- $ref: "#/components/parameters/Offset"
|
||
- $ref: "#/components/parameters/Search"
|
||
- $ref: "#/components/parameters/CompanyIdList"
|
||
- $ref: "#/components/parameters/ResourceIdList"
|
||
- $ref: "#/components/parameters/TypeIdList"
|
||
- $ref: "#/components/parameters/StatusIdList"
|
||
responses:
|
||
"200":
|
||
description: Страница событий
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: "#/components/schemas/PageInspectionRead"
|
||
"401":
|
||
$ref: "#/components/responses/Unauthorized"
|
||
"403":
|
||
$ref: "#/components/responses/Forbidden"
|
||
post:
|
||
tags: [Inspections]
|
||
summary: Создать событие
|
||
description: Требует право `core.can_create_inspection`.
|
||
operationId: create
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: "#/components/schemas/InspectionCreate"
|
||
responses:
|
||
"201":
|
||
description: Созданное событие
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: "#/components/schemas/InspectionRead"
|
||
"400":
|
||
$ref: "#/components/responses/BadRequest"
|
||
"401":
|
||
$ref: "#/components/responses/Unauthorized"
|
||
"403":
|
||
$ref: "#/components/responses/Forbidden"
|
||
"422":
|
||
$ref: "#/components/responses/ValidationError"
|
||
|
||
/api/v1/inspections/filter/:
|
||
post:
|
||
tags: [Inspections]
|
||
summary: Список событий (фильтры в теле)
|
||
description: |
|
||
Аналог `GET /api/v1/inspections/` с передачей фильтров и пагинации в теле
|
||
запроса. Требует право `core.can_view_inspections`.
|
||
operationId: post_filter_all
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: "#/components/schemas/InspectionFiltersWithPagination"
|
||
responses:
|
||
"200":
|
||
description: Страница событий
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: "#/components/schemas/PageInspectionRead"
|
||
"401":
|
||
$ref: "#/components/responses/Unauthorized"
|
||
"403":
|
||
$ref: "#/components/responses/Forbidden"
|
||
"422":
|
||
$ref: "#/components/responses/ValidationError"
|
||
|
||
/api/v1/inspections/light/:
|
||
get:
|
||
tags: [Inspections]
|
||
summary: Список событий (облегчённое представление)
|
||
description: Требует право `core.can_view_inspections`.
|
||
operationId: get_all_light
|
||
parameters:
|
||
- $ref: "#/components/parameters/OrderByInspection"
|
||
- $ref: "#/components/parameters/Ascending"
|
||
- $ref: "#/components/parameters/Limit"
|
||
- $ref: "#/components/parameters/Offset"
|
||
- $ref: "#/components/parameters/Search"
|
||
- $ref: "#/components/parameters/CompanyIdList"
|
||
- $ref: "#/components/parameters/ResourceIdList"
|
||
responses:
|
||
"200":
|
||
description: Страница облегчённых событий
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: "#/components/schemas/PageInspectionLightRead"
|
||
"401":
|
||
$ref: "#/components/responses/Unauthorized"
|
||
"403":
|
||
$ref: "#/components/responses/Forbidden"
|
||
|
||
/api/v1/inspections/export/:
|
||
get:
|
||
tags: [Inspections]
|
||
summary: Экспорт событий (xlsx)
|
||
description: |
|
||
Возвращает файл экспорта. Поддерживается единственный тип — `xlsx`.
|
||
Требует право `core.can_view_inspections`.
|
||
operationId: export
|
||
parameters:
|
||
- name: type
|
||
in: query
|
||
required: false
|
||
schema:
|
||
$ref: "#/components/schemas/InspectionExportType"
|
||
- $ref: "#/components/parameters/Search"
|
||
- $ref: "#/components/parameters/CompanyIdList"
|
||
- $ref: "#/components/parameters/ResourceIdList"
|
||
- $ref: "#/components/parameters/TypeIdList"
|
||
- $ref: "#/components/parameters/StatusIdList"
|
||
responses:
|
||
"200":
|
||
description: Файл экспорта
|
||
headers:
|
||
Content-Disposition:
|
||
schema:
|
||
type: string
|
||
example: attachment; filename=inspections_export.xlsx
|
||
content:
|
||
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet:
|
||
schema:
|
||
type: string
|
||
format: binary
|
||
"401":
|
||
$ref: "#/components/responses/Unauthorized"
|
||
"403":
|
||
$ref: "#/components/responses/Forbidden"
|
||
|
||
/api/v1/inspections/types/:
|
||
get:
|
||
tags: [Inspections]
|
||
summary: Типы событий компании
|
||
description: Требует право `core.can_view_inspections`.
|
||
operationId: get_types
|
||
parameters:
|
||
- name: company_id
|
||
in: query
|
||
required: true
|
||
description: ID компании
|
||
schema:
|
||
type: integer
|
||
example: 1
|
||
responses:
|
||
"200":
|
||
description: Список типов событий (полное представление)
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: array
|
||
items:
|
||
$ref: "#/components/schemas/InspectionTypeFullRead"
|
||
"401":
|
||
$ref: "#/components/responses/Unauthorized"
|
||
"403":
|
||
$ref: "#/components/responses/Forbidden"
|
||
|
||
/api/v1/inspections/status-count/:
|
||
get:
|
||
tags: [Inspections]
|
||
summary: Счётчики по статусам (фильтры в query)
|
||
description: Требует право `core.can_view_inspections`.
|
||
operationId: get_status_count
|
||
parameters:
|
||
- $ref: "#/components/parameters/Search"
|
||
- $ref: "#/components/parameters/CompanyIdList"
|
||
- $ref: "#/components/parameters/ResourceIdList"
|
||
- $ref: "#/components/parameters/TypeIdList"
|
||
- $ref: "#/components/parameters/StatusIdList"
|
||
responses:
|
||
"200":
|
||
description: Счётчики по статусам, сгруппированные по ресурсам
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: array
|
||
items:
|
||
$ref: "#/components/schemas/InspectionStatusCountRead"
|
||
"401":
|
||
$ref: "#/components/responses/Unauthorized"
|
||
"403":
|
||
$ref: "#/components/responses/Forbidden"
|
||
post:
|
||
tags: [Inspections]
|
||
summary: Счётчики по статусам (фильтры в теле)
|
||
description: Требует право `core.can_view_inspections`.
|
||
operationId: post_filter_status_count
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: "#/components/schemas/InspectionFilters"
|
||
responses:
|
||
"200":
|
||
description: Счётчики по статусам, сгруппированные по ресурсам
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: array
|
||
items:
|
||
$ref: "#/components/schemas/InspectionStatusCountRead"
|
||
"401":
|
||
$ref: "#/components/responses/Unauthorized"
|
||
"403":
|
||
$ref: "#/components/responses/Forbidden"
|
||
"422":
|
||
$ref: "#/components/responses/ValidationError"
|
||
|
||
/api/v1/inspections/unavailable-dates/:
|
||
post:
|
||
tags: [Inspections]
|
||
summary: Недоступные даты для исполнителей
|
||
description: Требует право `core.can_view_inspections`.
|
||
operationId: get_unavailable_dates
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: "#/components/schemas/InspectionUnavailableDatesRequest"
|
||
responses:
|
||
"200":
|
||
description: Список отрезков недоступных дат
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: array
|
||
items:
|
||
$ref: "#/components/schemas/InspectionUnavailableDatesRead"
|
||
"401":
|
||
$ref: "#/components/responses/Unauthorized"
|
||
"403":
|
||
$ref: "#/components/responses/Forbidden"
|
||
"422":
|
||
$ref: "#/components/responses/ValidationError"
|
||
|
||
/api/v1/inspections/unavailable-users/:
|
||
post:
|
||
tags: [Inspections]
|
||
summary: Недоступные исполнители на интервал
|
||
description: Требует право `core.can_view_inspections`.
|
||
operationId: get_unavailable_users
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: "#/components/schemas/InspectionUnavailableUsersRequest"
|
||
responses:
|
||
"200":
|
||
description: Список недоступных пользователей
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: "#/components/schemas/InspectionUnavailableUsersRead"
|
||
"401":
|
||
$ref: "#/components/responses/Unauthorized"
|
||
"403":
|
||
$ref: "#/components/responses/Forbidden"
|
||
"422":
|
||
$ref: "#/components/responses/ValidationError"
|
||
|
||
/api/v1/inspections/change-history/:
|
||
get:
|
||
tags: [Inspections]
|
||
summary: История изменений событий
|
||
description: Требует право `core.can_view_inspections`.
|
||
operationId: get_change_history
|
||
parameters:
|
||
- $ref: "#/components/parameters/OrderByChangeHistory"
|
||
- $ref: "#/components/parameters/Ascending"
|
||
- $ref: "#/components/parameters/Limit"
|
||
- $ref: "#/components/parameters/Offset"
|
||
- name: created_at_after
|
||
in: query
|
||
schema: { type: string, format: date-time, nullable: true }
|
||
- name: created_at_before
|
||
in: query
|
||
schema: { type: string, format: date-time, nullable: true }
|
||
- name: updated_at_after
|
||
in: query
|
||
schema: { type: string, format: date-time, nullable: true }
|
||
- name: updated_at_before
|
||
in: query
|
||
schema: { type: string, format: date-time, nullable: true }
|
||
- name: inspection_public_id
|
||
in: query
|
||
schema:
|
||
type: array
|
||
nullable: true
|
||
items: { type: string, format: uuid }
|
||
- $ref: "#/components/parameters/CompanyIdList"
|
||
- $ref: "#/components/parameters/ResourceIdList"
|
||
responses:
|
||
"200":
|
||
description: Страница записей истории изменений
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: "#/components/schemas/PageInspectionChangeRecordRead"
|
||
"401":
|
||
$ref: "#/components/responses/Unauthorized"
|
||
"403":
|
||
$ref: "#/components/responses/Forbidden"
|
||
|
||
/api/v1/inspections/filter-options/:
|
||
post:
|
||
tags: [Inspections]
|
||
summary: Доступные значения фильтров
|
||
description: |
|
||
Возвращает возможные значения для перечисленных полей фильтра.
|
||
Требует право `core.can_view_inspections`.
|
||
operationId: get_filter_options
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: "#/components/schemas/InspectionFilterOptionsRequest"
|
||
responses:
|
||
"200":
|
||
description: Маппинг «поле фильтра → список значений»
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: "#/components/schemas/InspectionFilterOptionsRead"
|
||
"401":
|
||
$ref: "#/components/responses/Unauthorized"
|
||
"403":
|
||
$ref: "#/components/responses/Forbidden"
|
||
"422":
|
||
$ref: "#/components/responses/ValidationError"
|
||
|
||
/api/v1/inspections/aggregate/{field_name}/{aggregate_func}/:
|
||
get:
|
||
tags: [Inspections]
|
||
summary: Агрегация по полю события
|
||
description: Требует право `core.can_view_inspections`.
|
||
operationId: aggregate
|
||
parameters:
|
||
- name: field_name
|
||
in: path
|
||
required: true
|
||
schema:
|
||
$ref: "#/components/schemas/InspectionAggregateField"
|
||
- name: aggregate_func
|
||
in: path
|
||
required: true
|
||
schema:
|
||
$ref: "#/components/schemas/AggregateFunc"
|
||
- $ref: "#/components/parameters/Search"
|
||
- $ref: "#/components/parameters/CompanyIdList"
|
||
- $ref: "#/components/parameters/ResourceIdList"
|
||
responses:
|
||
"200":
|
||
description: Результат агрегации
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: "#/components/schemas/AggregateResponse"
|
||
"401":
|
||
$ref: "#/components/responses/Unauthorized"
|
||
"403":
|
||
$ref: "#/components/responses/Forbidden"
|
||
|
||
/api/v1/inspections/{instance_id}/:
|
||
get:
|
||
tags: [Inspections]
|
||
summary: Событие по id
|
||
description: Требует право `core.can_view_inspections`.
|
||
operationId: retrieve
|
||
parameters:
|
||
- $ref: "#/components/parameters/InstanceId"
|
||
responses:
|
||
"200":
|
||
description: Событие
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: "#/components/schemas/InspectionRead"
|
||
"401":
|
||
$ref: "#/components/responses/Unauthorized"
|
||
"403":
|
||
$ref: "#/components/responses/Forbidden"
|
||
"404":
|
||
$ref: "#/components/responses/NotFound"
|
||
patch:
|
||
tags: [Inspections]
|
||
summary: Частичное обновление события
|
||
description: Требует право `core.can_edit_inspection`.
|
||
operationId: partial_update
|
||
parameters:
|
||
- $ref: "#/components/parameters/InstanceId"
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: "#/components/schemas/InspectionPartialUpdate"
|
||
responses:
|
||
"200":
|
||
description: Обновлённое событие
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: "#/components/schemas/InspectionRead"
|
||
"400":
|
||
$ref: "#/components/responses/BadRequest"
|
||
"401":
|
||
$ref: "#/components/responses/Unauthorized"
|
||
"403":
|
||
$ref: "#/components/responses/Forbidden"
|
||
"404":
|
||
$ref: "#/components/responses/NotFound"
|
||
"422":
|
||
$ref: "#/components/responses/ValidationError"
|
||
delete:
|
||
tags: [Inspections]
|
||
summary: Удалить событие
|
||
description: Требует право `core.can_delete_inspection`.
|
||
operationId: delete
|
||
parameters:
|
||
- $ref: "#/components/parameters/InstanceId"
|
||
responses:
|
||
"204":
|
||
description: Удалено
|
||
"401":
|
||
$ref: "#/components/responses/Unauthorized"
|
||
"403":
|
||
$ref: "#/components/responses/Forbidden"
|
||
"404":
|
||
$ref: "#/components/responses/NotFound"
|
||
|
||
components:
|
||
securitySchemes:
|
||
bearerAuth:
|
||
type: http
|
||
scheme: bearer
|
||
bearerFormat: JWT
|
||
description: |
|
||
JWT в заголовке `Authorization: Bearer <jwt>`. Опционально —
|
||
дополнительный заголовок `identity: Bearer <jwt>` (метаданные Zitadel).
|
||
Подпись токена не проверяется.
|
||
|
||
parameters:
|
||
InstanceId:
|
||
name: instance_id
|
||
in: path
|
||
required: true
|
||
description: Публичный ID (UUID) события
|
||
schema:
|
||
type: string
|
||
format: uuid
|
||
Limit:
|
||
name: limit
|
||
in: query
|
||
description: Максимальное количество объектов
|
||
schema: { type: integer, default: 100 }
|
||
Offset:
|
||
name: offset
|
||
in: query
|
||
description: Количество пропущенных объектов
|
||
schema: { type: integer, default: 0 }
|
||
Ascending:
|
||
name: ascending
|
||
in: query
|
||
description: Сортировка по возрастанию
|
||
schema: { type: boolean, default: true }
|
||
OrderByInspection:
|
||
name: order_by
|
||
in: query
|
||
description: Поле сортировки
|
||
schema:
|
||
type: string
|
||
enum: [id, inspection_dt]
|
||
default: id
|
||
OrderByChangeHistory:
|
||
name: order_by
|
||
in: query
|
||
description: Поле сортировки
|
||
schema:
|
||
type: string
|
||
enum: [id, created_at]
|
||
default: id
|
||
Search:
|
||
name: search
|
||
in: query
|
||
description: Поиск по названию, локации и описанию
|
||
schema: { type: string, nullable: true }
|
||
CompanyIdList:
|
||
name: company_id
|
||
in: query
|
||
description: ID компании
|
||
schema:
|
||
type: array
|
||
nullable: true
|
||
items: { type: integer }
|
||
ResourceIdList:
|
||
name: resource_id
|
||
in: query
|
||
description: ID ресурса (проекта)
|
||
schema:
|
||
type: array
|
||
nullable: true
|
||
items: { type: string, format: uuid }
|
||
TypeIdList:
|
||
name: type_id
|
||
in: query
|
||
description: ID типа
|
||
schema:
|
||
type: array
|
||
nullable: true
|
||
items: { type: integer }
|
||
StatusIdList:
|
||
name: status_id
|
||
in: query
|
||
description: ID статуса
|
||
schema:
|
||
type: array
|
||
nullable: true
|
||
items: { type: integer }
|
||
|
||
responses:
|
||
BadRequest:
|
||
description: Некорректный запрос
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: "#/components/schemas/HTTPError"
|
||
example: { detail: "Bad Request" }
|
||
Unauthorized:
|
||
description: Не аутентифицирован
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: "#/components/schemas/HTTPError"
|
||
example: { detail: "Authorization header is required" }
|
||
Forbidden:
|
||
description: Недостаточно прав
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: "#/components/schemas/HTTPError"
|
||
example: { detail: "Forbidden" }
|
||
NotFound:
|
||
description: Ресурс не найден
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: "#/components/schemas/HTTPError"
|
||
example: { detail: "Not Found" }
|
||
ValidationError:
|
||
description: Ошибка валидации (Pydantic / FastAPI)
|
||
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:
|
||
type: object
|
||
properties:
|
||
loc:
|
||
type: array
|
||
items:
|
||
anyOf:
|
||
- { type: string }
|
||
- { type: integer }
|
||
msg: { type: string }
|
||
type: { type: string }
|
||
|
||
MobileAppVersion:
|
||
type: object
|
||
properties:
|
||
current_version: { type: string, example: "1.0.0" }
|
||
recommended_version: { type: string, example: "1.0.0" }
|
||
required_version: { type: string, example: "1.0.0" }
|
||
required: [current_version, recommended_version, required_version]
|
||
|
||
AttributeValueType:
|
||
description: Значение атрибута (одиночное)
|
||
nullable: true
|
||
anyOf:
|
||
- { type: boolean }
|
||
- { type: integer }
|
||
- { type: number }
|
||
- { type: string }
|
||
- { type: array, items: { type: integer } }
|
||
|
||
AttributeMultivalueType:
|
||
description: Мультизначение атрибута
|
||
type: array
|
||
items:
|
||
nullable: true
|
||
anyOf:
|
||
- { type: boolean }
|
||
- { type: integer }
|
||
- { type: number }
|
||
- { type: string }
|
||
|
||
InspectionExportType:
|
||
type: string
|
||
enum: [xlsx]
|
||
default: xlsx
|
||
|
||
InspectionAggregateField:
|
||
type: string
|
||
enum: [created_at, inspection_dt]
|
||
|
||
AggregateFunc:
|
||
type: string
|
||
enum: [minmax]
|
||
|
||
AggregateResponse:
|
||
type: object
|
||
properties:
|
||
min:
|
||
nullable: true
|
||
description: Минимальное значение
|
||
example: 0
|
||
max:
|
||
nullable: true
|
||
description: Максимальное значение
|
||
example: 1
|
||
|
||
AllowedToSetRole:
|
||
type: string
|
||
enum: [author, responsible_user, author_or_responsible_user]
|
||
|
||
SetRole:
|
||
type: string
|
||
enum: [author, responsible_user]
|
||
|
||
InspectionFilters:
|
||
type: object
|
||
description: Фильтры выборки событий
|
||
properties:
|
||
search: { type: string, nullable: true, description: Поиск по названию, локации и описанию }
|
||
created_at_after: { type: string, format: date-time, nullable: true }
|
||
created_at_before: { type: string, format: date-time, nullable: true }
|
||
updated_at_after: { type: string, format: date-time, nullable: true }
|
||
updated_at_before: { type: string, format: date-time, nullable: true }
|
||
public_id:
|
||
type: array
|
||
nullable: true
|
||
items: { type: string, format: uuid }
|
||
company_id:
|
||
type: array
|
||
nullable: true
|
||
items: { type: integer, minimum: 1 }
|
||
resource_id:
|
||
type: array
|
||
nullable: true
|
||
items: { type: string, format: uuid }
|
||
premise_id:
|
||
type: array
|
||
nullable: true
|
||
items: { type: string, format: uuid }
|
||
author_id:
|
||
type: array
|
||
nullable: true
|
||
items: { type: integer, minimum: 1 }
|
||
inspection_dt_after: { type: string, format: date-time, nullable: true }
|
||
inspection_dt_before: { type: string, format: date-time, nullable: true }
|
||
inspection_dt_end_after: { type: string, format: date-time, nullable: true }
|
||
inspection_dt_end_before: { type: string, format: date-time, nullable: true }
|
||
responsible_user_id:
|
||
type: array
|
||
nullable: true
|
||
items: { type: integer, minimum: 1 }
|
||
type_id:
|
||
type: array
|
||
nullable: true
|
||
items: { type: integer }
|
||
status_id:
|
||
type: array
|
||
nullable: true
|
||
items: { type: integer }
|
||
attributes:
|
||
type: object
|
||
nullable: true
|
||
description: >-
|
||
Маппинг id атрибута → значение. Может передаваться JSON-строкой.
|
||
additionalProperties:
|
||
oneOf:
|
||
- $ref: "#/components/schemas/AttributeValueType"
|
||
- $ref: "#/components/schemas/AttributeMultivalueType"
|
||
|
||
InspectionFiltersWithPagination:
|
||
allOf:
|
||
- $ref: "#/components/schemas/InspectionFilters"
|
||
- type: object
|
||
properties:
|
||
order_by:
|
||
type: string
|
||
enum: [id, inspection_dt]
|
||
default: id
|
||
ascending: { type: boolean, default: true }
|
||
limit: { type: integer, default: 100 }
|
||
offset: { type: integer, default: 0 }
|
||
|
||
InspectionExportFilters:
|
||
allOf:
|
||
- $ref: "#/components/schemas/InspectionFilters"
|
||
- type: object
|
||
properties:
|
||
type:
|
||
$ref: "#/components/schemas/InspectionExportType"
|
||
|
||
InspectionFilterOptionsRequest:
|
||
type: object
|
||
properties:
|
||
filters:
|
||
$ref: "#/components/schemas/InspectionFilters"
|
||
fields:
|
||
type: array
|
||
description: Список полей, для которых нужно получить значения
|
||
items: { type: string }
|
||
example: [author_id, company_id]
|
||
required: [fields]
|
||
|
||
InspectionFilterOptionsRead:
|
||
type: object
|
||
properties:
|
||
options:
|
||
type: object
|
||
description: Маппинг «поле фильтра» → «список значений»
|
||
additionalProperties: true
|
||
example: { company_id: [1, 2, 3, null] }
|
||
required: [options]
|
||
|
||
AssetAttributeCreate:
|
||
type: object
|
||
properties:
|
||
attribute_id: { type: integer, example: 1 }
|
||
asset_id: { type: string, example: "1" }
|
||
order: { type: integer, example: 1 }
|
||
required: [attribute_id, asset_id, order]
|
||
|
||
AssetAttributeRead:
|
||
allOf:
|
||
- $ref: "#/components/schemas/AssetAttributeCreate"
|
||
- type: object
|
||
properties:
|
||
value:
|
||
$ref: "#/components/schemas/AttributeValueType"
|
||
required: [value]
|
||
|
||
AttributeRead:
|
||
type: object
|
||
properties:
|
||
id: { type: integer, example: 1 }
|
||
created_at: { type: string, format: date-time }
|
||
updated_at: { type: string, format: date-time }
|
||
attribute_id: { type: integer, example: 1 }
|
||
attribute_name: { type: string, example: "Название атрибута" }
|
||
asset_id: { type: string, nullable: true, example: "1" }
|
||
asset_name: { type: string, nullable: true, example: "Название ассета" }
|
||
root_asset_id: { type: string, nullable: true, example: "1" }
|
||
required: { type: boolean, example: false }
|
||
resource_id: { type: string, format: uuid, nullable: true }
|
||
required: [id, created_at, updated_at, attribute_id, attribute_name, required]
|
||
|
||
AttachmentsChange:
|
||
type: object
|
||
description: Состояние вложений до и после изменения
|
||
properties:
|
||
before:
|
||
type: array
|
||
items: { type: string }
|
||
after:
|
||
type: array
|
||
items: { type: string }
|
||
example: { before: ["report.pdf"], after: ["report.pdf", "photo.jpg"] }
|
||
|
||
StatusSettingRead:
|
||
type: object
|
||
properties:
|
||
id: { type: integer, example: 1 }
|
||
created_at: { type: string, format: date-time }
|
||
updated_at: { type: string, format: date-time }
|
||
inspection_status_id: { type: integer, example: 1 }
|
||
set_service_account_id: { type: string, format: uuid, nullable: true }
|
||
set_role:
|
||
nullable: true
|
||
allOf: [{ $ref: "#/components/schemas/SetRole" }]
|
||
comment_required: { type: boolean, example: false }
|
||
required: [id, created_at, updated_at, inspection_status_id, comment_required]
|
||
|
||
StatusRead:
|
||
type: object
|
||
properties:
|
||
id: { type: integer, example: 1 }
|
||
created_at: { type: string, format: date-time }
|
||
updated_at: { type: string, format: date-time }
|
||
inspection_status_model_id: { type: integer, example: 1 }
|
||
name: { type: string, example: "Название статуса" }
|
||
color: { type: string, example: "#000000" }
|
||
is_final: { type: boolean, example: false }
|
||
allowed_to_set:
|
||
nullable: true
|
||
deprecated: true
|
||
allOf: [{ $ref: "#/components/schemas/AllowedToSetRole" }]
|
||
comment_required: { type: boolean, deprecated: true, example: false }
|
||
set_status_ids:
|
||
type: array
|
||
items: { type: integer }
|
||
example: [1, 2, 3]
|
||
settings:
|
||
type: array
|
||
items: { $ref: "#/components/schemas/StatusSettingRead" }
|
||
required: [id, created_at, updated_at, inspection_status_model_id, name, color, is_final, comment_required]
|
||
|
||
StatusWithCountRead:
|
||
allOf:
|
||
- $ref: "#/components/schemas/StatusRead"
|
||
- type: object
|
||
properties:
|
||
count: { type: integer, example: 1 }
|
||
required: [count]
|
||
|
||
StatusModelRead:
|
||
type: object
|
||
properties:
|
||
id: { type: integer, example: 1 }
|
||
created_at: { type: string, format: date-time }
|
||
updated_at: { type: string, format: date-time }
|
||
inspection_type_id: { type: integer, example: 1 }
|
||
resource_id: { type: string, format: uuid, nullable: true }
|
||
statuses:
|
||
type: array
|
||
items: { $ref: "#/components/schemas/StatusRead" }
|
||
required: [id, created_at, updated_at, inspection_type_id]
|
||
|
||
InspectionTypePermissionsRead:
|
||
type: object
|
||
properties:
|
||
id: { type: integer, example: 1 }
|
||
created_at: { type: string, format: date-time }
|
||
updated_at: { type: string, format: date-time }
|
||
inspection_type_id: { type: integer, example: 1 }
|
||
service_account_id: { type: string, format: uuid }
|
||
permissions:
|
||
type: array
|
||
items: { $ref: "#/components/schemas/InspectionPermission" }
|
||
required: [id, created_at, updated_at, inspection_type_id, service_account_id]
|
||
|
||
InspectionPermission:
|
||
type: string
|
||
enum:
|
||
- core.can_create_inspection
|
||
- core.can_view_inspections
|
||
- core.can_edit_inspection
|
||
- core.can_delete_inspection
|
||
- core.can_view_all_inspections
|
||
|
||
InspectionTypeLightRead:
|
||
type: object
|
||
properties:
|
||
id: { type: integer, example: 1 }
|
||
issue_types:
|
||
type: array
|
||
items: { type: integer }
|
||
example: [1, 2]
|
||
required: [id]
|
||
|
||
InspectionTypeRead:
|
||
type: object
|
||
properties:
|
||
id: { type: integer, example: 1 }
|
||
created_at: { type: string, format: date-time }
|
||
updated_at: { type: string, format: date-time }
|
||
company_id: { type: integer, example: 1 }
|
||
name: { type: string, example: "Название типа события" }
|
||
event_duration:
|
||
type: integer
|
||
description: Длительность события в минутах
|
||
example: 30
|
||
columns_order:
|
||
type: array
|
||
items: { type: string }
|
||
example: [name, description, "attribute[1]"]
|
||
issue_types:
|
||
type: array
|
||
items: { type: integer }
|
||
example: [1, 2]
|
||
required: [id, created_at, updated_at, company_id, name, event_duration]
|
||
|
||
InspectionTypeFullRead:
|
||
allOf:
|
||
- $ref: "#/components/schemas/InspectionTypeRead"
|
||
- type: object
|
||
properties:
|
||
permissions:
|
||
type: array
|
||
items: { $ref: "#/components/schemas/InspectionTypePermissionsRead" }
|
||
status_models:
|
||
type: array
|
||
items: { $ref: "#/components/schemas/StatusModelRead" }
|
||
attributes:
|
||
type: array
|
||
items: { $ref: "#/components/schemas/AttributeRead" }
|
||
inspection_dt_overlap_allowed: { type: boolean, example: false }
|
||
inspection_dt_current_day_allowed: { type: boolean, example: false }
|
||
required: [inspection_dt_overlap_allowed, inspection_dt_current_day_allowed]
|
||
|
||
InspectionCreate:
|
||
type: object
|
||
properties:
|
||
company_id: { type: integer, minimum: 1, example: 1 }
|
||
resource_id: { type: string, format: uuid }
|
||
name: { type: string, minLength: 1, maxLength: 255, example: "Название события" }
|
||
inspection_dt:
|
||
type: string
|
||
format: date-time
|
||
description: Дата/время проведения (обнуляются секунды; не в прошлом)
|
||
inspection_dt_end: { type: string, format: date-time, nullable: true }
|
||
responsible_users:
|
||
type: array
|
||
minItems: 1
|
||
items: { type: integer, minimum: 1 }
|
||
example: [1, 2]
|
||
location: { type: string, nullable: true }
|
||
description: { type: string, nullable: true }
|
||
type_id: { type: integer, minimum: 1, example: 1 }
|
||
status_id: { type: integer, nullable: true, example: 1 }
|
||
attributes:
|
||
type: object
|
||
additionalProperties:
|
||
$ref: "#/components/schemas/AttributeMultivalueType"
|
||
example: { "1": [null], "2": [true, false], "3": [1, 2] }
|
||
asset_attributes:
|
||
type: array
|
||
items: { $ref: "#/components/schemas/AssetAttributeCreate" }
|
||
premise_id: { type: string, format: uuid, nullable: true }
|
||
required: [company_id, resource_id, name, inspection_dt, responsible_users, type_id]
|
||
|
||
InspectionPartialUpdate:
|
||
type: object
|
||
description: Все поля опциональны
|
||
properties:
|
||
name: { type: string, minLength: 1, maxLength: 255, nullable: true }
|
||
inspection_dt: { type: string, format: date-time, nullable: true }
|
||
inspection_dt_end: { type: string, format: date-time, nullable: true }
|
||
responsible_users:
|
||
type: array
|
||
minItems: 1
|
||
nullable: true
|
||
items: { type: integer, minimum: 1 }
|
||
location: { type: string, nullable: true }
|
||
description: { type: string, nullable: true }
|
||
type_id: { type: integer, nullable: true }
|
||
status_id: { type: integer, nullable: true }
|
||
attributes:
|
||
type: object
|
||
nullable: true
|
||
additionalProperties:
|
||
$ref: "#/components/schemas/AttributeMultivalueType"
|
||
asset_attributes:
|
||
type: array
|
||
nullable: true
|
||
items: { $ref: "#/components/schemas/AssetAttributeCreate" }
|
||
status_comment: { type: string, nullable: true }
|
||
attachments:
|
||
nullable: true
|
||
allOf: [{ $ref: "#/components/schemas/AttachmentsChange" }]
|
||
premise_id: { type: string, format: uuid, nullable: true }
|
||
|
||
InspectionLightRead:
|
||
type: object
|
||
properties:
|
||
public_id: { type: string, format: uuid }
|
||
name: { type: string, example: "Название события" }
|
||
type:
|
||
$ref: "#/components/schemas/InspectionTypeLightRead"
|
||
required: [public_id, name, type]
|
||
|
||
InspectionRead:
|
||
type: object
|
||
properties:
|
||
id: { type: integer, example: 1 }
|
||
created_at: { type: string, format: date-time }
|
||
updated_at: { type: string, format: date-time }
|
||
public_id: { type: string, format: uuid }
|
||
company_id: { type: integer, example: 1 }
|
||
resource_id: { type: string, format: uuid }
|
||
author_id: { type: integer, example: 1 }
|
||
name: { type: string, example: "Название события" }
|
||
inspection_dt: { type: string, format: date-time }
|
||
inspection_dt_end: { type: string, format: date-time }
|
||
responsible_users:
|
||
type: array
|
||
items: { type: integer }
|
||
example: [1, 2]
|
||
location: { type: string, nullable: true }
|
||
description: { type: string, nullable: true }
|
||
type:
|
||
$ref: "#/components/schemas/InspectionTypeRead"
|
||
status:
|
||
$ref: "#/components/schemas/StatusRead"
|
||
attributes:
|
||
type: object
|
||
additionalProperties:
|
||
$ref: "#/components/schemas/AttributeMultivalueType"
|
||
asset_attributes:
|
||
type: array
|
||
items: { $ref: "#/components/schemas/AssetAttributeRead" }
|
||
premise_id: { type: string, format: uuid, nullable: true }
|
||
required:
|
||
- id
|
||
- created_at
|
||
- updated_at
|
||
- public_id
|
||
- company_id
|
||
- resource_id
|
||
- author_id
|
||
- name
|
||
- inspection_dt
|
||
- inspection_dt_end
|
||
- responsible_users
|
||
- type
|
||
- status
|
||
- attributes
|
||
- premise_id
|
||
|
||
InspectionStatusCountRead:
|
||
type: object
|
||
properties:
|
||
resource_id: { type: string, format: uuid }
|
||
statuses:
|
||
type: array
|
||
items: { $ref: "#/components/schemas/StatusWithCountRead" }
|
||
required: [resource_id, statuses]
|
||
|
||
InspectionUnavailableDatesRequest:
|
||
type: object
|
||
properties:
|
||
company_id: { type: integer, minimum: 1, nullable: true, example: 1 }
|
||
responsible_users:
|
||
type: array
|
||
minItems: 1
|
||
items: { type: integer, minimum: 1 }
|
||
example: [1, 2]
|
||
excluded_inspection_ids:
|
||
type: array
|
||
items: { type: integer }
|
||
example: [1, 2]
|
||
required: [responsible_users]
|
||
|
||
InspectionUnavailableDatesRead:
|
||
type: object
|
||
properties:
|
||
unavailable_from: { type: string, format: date-time }
|
||
unavailable_to: { type: string, format: date-time }
|
||
required: [unavailable_from, unavailable_to]
|
||
|
||
InspectionUnavailableUsersRequest:
|
||
type: object
|
||
properties:
|
||
company_id: { type: integer, minimum: 1, nullable: true, example: 1 }
|
||
inspection_dt: { type: string, format: date-time }
|
||
inspection_dt_end: { type: string, format: date-time, nullable: true }
|
||
users:
|
||
type: array
|
||
minItems: 1
|
||
items: { type: integer, minimum: 1 }
|
||
example: [1, 2]
|
||
required: [inspection_dt, users]
|
||
|
||
InspectionUnavailableUsersRead:
|
||
type: object
|
||
properties:
|
||
unavailable_users:
|
||
type: array
|
||
items: { type: integer }
|
||
example: [1, 2]
|
||
required: [unavailable_users]
|
||
|
||
InspectionChangeRecordRead:
|
||
type: object
|
||
properties:
|
||
id: { type: integer, example: 1 }
|
||
created_at: { type: string, format: date-time }
|
||
inspection_id: { type: integer, example: 1 }
|
||
created_by: { type: integer, example: 1023 }
|
||
field_name: { type: string, example: "name" }
|
||
attribute_name: { type: string, nullable: true, example: "Локация" }
|
||
was:
|
||
oneOf:
|
||
- $ref: "#/components/schemas/AttributeValueType"
|
||
- $ref: "#/components/schemas/AttributeMultivalueType"
|
||
became:
|
||
oneOf:
|
||
- $ref: "#/components/schemas/AttributeValueType"
|
||
- $ref: "#/components/schemas/AttributeMultivalueType"
|
||
was_text: { type: string, nullable: true }
|
||
became_text: { type: string, nullable: true }
|
||
required: [id, created_at, inspection_id, created_by, field_name, attribute_name, was, became, was_text, became_text]
|
||
|
||
PageInspectionRead:
|
||
type: object
|
||
properties:
|
||
count: { type: integer, example: 1 }
|
||
result:
|
||
type: array
|
||
items: { $ref: "#/components/schemas/InspectionRead" }
|
||
required: [count, result]
|
||
|
||
PageInspectionLightRead:
|
||
type: object
|
||
properties:
|
||
count: { type: integer, example: 1 }
|
||
result:
|
||
type: array
|
||
items: { $ref: "#/components/schemas/InspectionLightRead" }
|
||
required: [count, result]
|
||
|
||
PageInspectionChangeRecordRead:
|
||
type: object
|
||
properties:
|
||
count: { type: integer, example: 1 }
|
||
result:
|
||
type: array
|
||
items: { $ref: "#/components/schemas/InspectionChangeRecordRead" }
|
||
required: [count, result]
|