openapi: 3.0.3
info:
  title: API заявок pcp-request-service
  description: |
    Целевой API сервиса pcp-request-service.

    Сервис является владельцем заявок на съемку. API построен вокруг ресурса Request.

    Основные решения:
    - заявка создается через POST /v1/requests;
    - чтение одной заявки выполняется через GET /v1/requests/{id};
    - чтение списка заявок выполняется через GET /v1/requests;
    - чтение списка заявок с geometry выполняется через GET /v1/requests/map;
    - удаление заявки выполняется через DELETE /v1/requests/{id};
    - удаление является мягким: заявка получает status = DELETED и deletedAt;
    - заявка должна содержать хотя бы один payload-блок: optics или rsa;
    - заявка может содержать одновременно optics и rsa;
    - surveyType не принимается от клиента, а вычисляется сервисом по наличию optics/rsa;
    - deleted-заявки не возвращаются в списке по умолчанию.
  version: 1.0.0
servers:
  - url: http://localhost:8080
    description: Локальный сервер разработки
tags:
  - name: Requests
    description: Операции с заявками
  - name: Cells
    description: Операции с ячейками сетки
  - name: Grid
    description: Операции с настройками и перестроением сетки
paths:
  /v1/cells:
    get:
      tags:
        - Cells
      summary: Получить ячейки сетки
      description: |
        Возвращает постраничный список ячеек сетки, отсортированных и отфильтрованных по важности.
      operationId: listCells
      parameters:
        - name: minImportance
          in: query
          required: false
          description: Минимальная важность ячейки
          schema:
            type: number
            format: double
            minimum: 0
        - name: countLat
          in: query
          required: false
          description: Размер агрегации ячеек по широте
          schema:
            type: integer
            minimum: 1
        - name: countLong
          in: query
          required: false
          description: Размер агрегации ячеек по долготе
          schema:
            type: integer
            minimum: 1
        - name: page
          in: query
          required: false
          description: Номер страницы, начиная с 0
          schema:
            type: integer
            minimum: 0
            default: 0
        - name: size
          in: query
          required: false
          description: Размер страницы
          schema:
            type: integer
            minimum: 1
            maximum: 500
            default: 50
        - name: sort
          in: query
          required: false
          description: Сортировка в формате field,direction. Разрешенные поля зависят от реализации.
          schema:
            type: string
          examples:
            importanceDesc:
              value: importance,desc
            cellNumAsc:
              value: cellNum,asc
      responses:
        '200':
          description: Список ячеек сетки
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CellsListResponse'
        '400':
          description: Некорректные query parameters
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Внутренняя ошибка сервера
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /v1/cells/priority-map:
    get:
      tags:
        - Cells
      summary: Получить ячейки сетки с фрагментами заявок
      description: |
        Возвращает список ячеек сетки вместе с фрагментами заявок, пересекающими каждую ячейку.
        Используется для построения тепловой карты приоритетов.
      operationId: listCellsPriorityMap
      parameters:
        - name: minImportance
          in: query
          required: false
          description: Минимальная важность ячейки
          schema:
            type: number
            format: double
            minimum: 0
        - name: countLat
          in: query
          required: false
          description: Размер агрегации ячеек по широте
          schema:
            type: integer
            minimum: 1
        - name: countLong
          in: query
          required: false
          description: Размер агрегации ячеек по долготе
          schema:
            type: integer
            minimum: 1
      responses:
        '200':
          description: Ячейки сетки с фрагментами заявок
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CellPriorityMapResponse'
        '400':
          description: Некорректные query parameters
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Внутренняя ошибка сервера
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /v1/requests:
    post:
      tags:
        - Requests
      summary: Создать заявку
      description: |
        Создает заявку в каноническом формате pcp-request-service.

        Правила:
        - id обязателен и должен быть уникальным;
        - geometry обязателен и передается в WKT;
        - beginDateTime и endDateTime обязательны;
        - beginDateTime должен быть раньше endDateTime;
        - должен быть указан хотя бы один блок: optics или rsa;
        - если указан только optics, surveyType = OPTICS;
        - если указан только rsa, surveyType = RSA;
        - если указаны optics и rsa, surveyType = COMBINED;
        - surveyType не передается клиентом.
      operationId: createRequest
      requestBody:
        required: true
        description: Данные создаваемой заявки
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateRequestRequest'
            examples:
              opticsRequest:
                summary: Заявка только на оптическую съемку
                value:
                  id: 3fa85f64-5717-4562-b3fc-2c963f66afa6
                  name: Тест1
                  geometry: POLYGON ((37.5 55.5, 37.7 55.5, 37.7 55.7, 37.5 55.7, 37.5 55.5))
                  importance: 10.0
                  beginDateTime: '2026-01-01T00:00:00Z'
                  endDateTime: '2026-01-31T23:59:59Z'
                  kpp: [1, 2, 3]
                  highPriorityTransmit: false
                  optics:
                    resultType: PANCHROMATIC
                    resolution: 1.0
                    sunAngleMin: 10.0
                    sunAngleMax: 45.0
                    clouds: 90.0
              rsaRequest:
                summary: Заявка только на РСА-съемку
                value:
                  id: 550e8400-e29b-41d4-a716-446655440000
                  name: Тест1
                  geometry: POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0))
                  importance: 5.0
                  beginDateTime: '2026-02-01T00:00:00Z'
                  endDateTime: '2026-02-28T23:59:59Z'
                  kpp: [1]
                  highPriorityTransmit: true
                  rsa:
                    resultType: SPOTLIGHT
                    interferometry: false
                    polarisation: HH
                    resolution: 3.0
              combinedRequest:
                summary: Заявка с оптической и РСА-съемкой
                value:
                  id: 7c9e6679-7425-40de-944b-e07fc1f90ae7
                  name: Тест1
                  geometry: POLYGON ((30 50, 40 50, 40 60, 30 60, 30 50))
                  importance: 7.5
                  beginDateTime: '2026-03-01T00:00:00Z'
                  endDateTime: '2026-03-31T23:59:59Z'
                  kpp: [1, 2]
                  highPriorityTransmit: false
                  optics:
                    resultType: PANCHROMATIC
                    resolution: 0.5
                  rsa:
                    resultType: SPOTLIGHT
                    polarisation: HH
                    resolution: 1.0
      responses:
        '201':
          description: Заявка создана
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateRequestResponse'
              example:
                id: 3fa85f64-5717-4562-b3fc-2c963f66afa6
                name: Тест1
                status: ACCEPTED
                surveyType: OPTICS
                importance: 10.0
                message: Заявка успешно создана
        '200':
          description: Идемпотентный повтор создания с тем же id и идентичным payload
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateRequestResponse'
              example:
                id: 3fa85f64-5717-4562-b3fc-2c963f66afa6
                name: Тест1
                status: ACCEPTED
                surveyType: OPTICS
                importance: 10.0
                message: Заявка уже существует, payload идентичен
        '400':
          description: Ошибка валидации запроса
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                missingSurveyPayload:
                  summary: Не указан тип съемки
                  value:
                    code: VALIDATION_ERROR
                    message: 'Должен быть указан хотя бы один блок съемки: optics или rsa'
                invalidTimeWindow:
                  summary: Некорректное временное окно
                  value:
                    code: VALIDATION_ERROR
                    message: beginDateTime должен быть раньше endDateTime
        '409':
          description: Заявка с таким id уже существует, но payload отличается
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                code: REQUEST_ALREADY_EXISTS
                message: Заявка с таким id уже существует с другим payload
        '500':
          description: Внутренняя ошибка сервера
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                code: INTERNAL_ERROR
                message: Внутренняя ошибка при создании заявки
    get:
      tags:
        - Requests
      summary: Получить список заявок
      description: |
        Возвращает постраничный список заявок.

        По умолчанию удаленные заявки не возвращаются. Для технического поиска можно передать includeDeleted=true.
        Полная geometry не возвращается в списке по умолчанию; для списка с geometry используйте GET /v1/requests/map,
        для полной заявки используйте GET /v1/requests/{id}.
      operationId: listRequests
      parameters:
        - name: status
          in: query
          required: false
          description: Фильтр по статусу заявки
          schema:
            $ref: '#/components/schemas/RequestStatus'
        - name: surveyType
          in: query
          required: false
          description: Фильтр по вычисленному типу заявки
          schema:
            $ref: '#/components/schemas/SurveyType'
        - name: kpp
          in: query
          required: false
          description: Фильтр по номеру КПП. Возвращает заявки, содержащие указанный КПП.
          schema:
            type: integer
          example: 1
        - name: highPriorityTransmit
          in: query
          required: false
          description: Фильтр по признаку высокоприоритетной передачи
          schema:
            type: boolean
        - name: beginFrom
          in: query
          required: false
          description: Нижняя граница beginDateTime, включительно
          schema:
            type: string
            format: date-time
        - name: beginTo
          in: query
          required: false
          description: Верхняя граница beginDateTime, включительно
          schema:
            type: string
            format: date-time
        - name: endFrom
          in: query
          required: false
          description: Нижняя граница endDateTime, включительно
          schema:
            type: string
            format: date-time
        - name: endTo
          in: query
          required: false
          description: Верхняя граница endDateTime, включительно
          schema:
            type: string
            format: date-time
        - name: includeDeleted
          in: query
          required: false
          description: Включать soft-deleted заявки в результат
          schema:
            type: boolean
            default: false
        - name: page
          in: query
          required: false
          description: Номер страницы, начиная с 0
          schema:
            type: integer
            minimum: 0
            default: 0
        - name: size
          in: query
          required: false
          description: Размер страницы
          schema:
            type: integer
            minimum: 1
            maximum: 500
            default: 50
        - name: sort
          in: query
          required: false
          description: Сортировка в формате field,direction. Разрешенные поля зависят от реализации.
          schema:
            type: string
            default: createdAt,desc
          examples:
            createdDesc:
              value: createdAt,desc
            beginAsc:
              value: beginDateTime,asc
      responses:
        '200':
          description: Список заявок
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RequestListResponse'
        '400':
          description: Некорректные query parameters
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Внутренняя ошибка сервера
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /v1/requests/map:
    get:
      tags:
        - Requests
      summary: Получить список заявок с геометрией для карты
      description: |
        Возвращает постраничный список заявок с полной geometry в WKT.

        Endpoint использует те же фильтры и сортировку, что GET /v1/requests, но возвращает расширенную read-модель.
        Используйте его только там, где клиенту действительно нужна геометрия списка (например, для отображения на карте).
      operationId: listRequestsForMap
      parameters:
        - name: status
          in: query
          required: false
          description: Фильтр по статусу заявки
          schema:
            $ref: '#/components/schemas/RequestStatus'
        - name: surveyType
          in: query
          required: false
          description: Фильтр по вычисленному типу заявки
          schema:
            $ref: '#/components/schemas/SurveyType'
        - name: kpp
          in: query
          required: false
          description: Фильтр по номеру КПП. Возвращает заявки, содержащие указанный КПП.
          schema:
            type: integer
          example: 1
        - name: highPriorityTransmit
          in: query
          required: false
          description: Фильтр по признаку высокоприоритетной передачи
          schema:
            type: boolean
        - name: beginFrom
          in: query
          required: false
          description: Нижняя граница beginDateTime, включительно
          schema:
            type: string
            format: date-time
        - name: beginTo
          in: query
          required: false
          description: Верхняя граница beginDateTime, включительно
          schema:
            type: string
            format: date-time
        - name: endFrom
          in: query
          required: false
          description: Нижняя граница endDateTime, включительно
          schema:
            type: string
            format: date-time
        - name: endTo
          in: query
          required: false
          description: Верхняя граница endDateTime, включительно
          schema:
            type: string
            format: date-time
        - name: includeDeleted
          in: query
          required: false
          description: Включать soft-deleted заявки в результат
          schema:
            type: boolean
            default: false
        - name: page
          in: query
          required: false
          description: Номер страницы, начиная с 0
          schema:
            type: integer
            minimum: 0
            default: 0
        - name: size
          in: query
          required: false
          description: Размер страницы
          schema:
            type: integer
            minimum: 1
            maximum: 500
            default: 50
        - name: sort
          in: query
          required: false
          description: Сортировка в формате field,direction. Разрешенные поля зависят от реализации.
          schema:
            type: string
            default: createdAt,desc
          examples:
            createdDesc:
              value: createdAt,desc
            beginAsc:
              value: beginDateTime,asc
      responses:
        '200':
          description: Список заявок с геометрией
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RequestMapPageResponse'
        '400':
          description: Некорректные query parameters
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Внутренняя ошибка сервера
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /v1/requests/{id}/cells:
    get:
      tags:
        - Cells
        - Requests
      summary: Получить заявку с привязанными ячейками
      description: |
        Возвращает заявку и проекцию ее пересечений с ячейками сетки.
      operationId: getRequestWithCells
      parameters:
        - $ref: '#/components/parameters/RequestIdPathParam'
      responses:
        '200':
          description: Заявка с привязанными ячейками
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RequestWithCellsResponse'
        '404':
          description: Заявка не найдена
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                code: REQUEST_NOT_FOUND
                message: Заявка не найдена
        '500':
          description: Внутренняя ошибка сервера
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /v1/requests/{id}:
    get:
      tags:
        - Requests
      summary: Получить одну заявку
      description: Возвращает полную read-модель заявки, включая geometry, optics и rsa.
      operationId: getRequestById
      parameters:
        - $ref: '#/components/parameters/RequestIdPathParam'
      responses:
        '200':
          description: Заявка найдена
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RequestResponse'
        '404':
          description: Заявка не найдена
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                code: REQUEST_NOT_FOUND
                message: Заявка не найдена
        '500':
          description: Внутренняя ошибка сервера
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
    delete:
      tags:
        - Requests
      summary: Мягко удалить заявку
      description: |
        Выполняет soft delete заявки.

        Заявка не удаляется физически. Сервис выставляет status = DELETED и deletedAt.
        Повторный DELETE для уже удаленной заявки считается идемпотентным и возвращает текущий статус DELETED.
      operationId: deleteRequest
      parameters:
        - $ref: '#/components/parameters/RequestIdPathParam'
      responses:
        '200':
          description: Заявка удалена или уже была удалена ранее
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DeleteRequestResponse'
              example:
                id: 3fa85f64-5717-4562-b3fc-2c963f66afa6
                deletedAt: '2026-05-19T13:00:00Z'
        '404':
          description: Заявка не найдена
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                code: REQUEST_NOT_FOUND
                message: Заявка не найдена
        '500':
          description: Внутренняя ошибка сервера
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /v1/grid/settings:
    get:
      tags:
        - Grid
      summary: Получить настройки сетки
      description: Возвращает текущие параметры сетки.
      operationId: getGridSettings
      responses:
        '200':
          description: Текущие настройки сетки
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GridSettingsResponse'
        '500':
          description: Внутренняя ошибка сервера
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
    put:
      tags:
        - Grid
      summary: Обновить настройки сетки
      description: |
        Обновляет параметры сетки.

        Endpoint не выполняет автоматическое перестроение сетки. Для явного перестроения используйте POST /v1/grid/rebuild.
      operationId: updateGridSettings
      requestBody:
        required: true
        description: Новые настройки сетки
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateGridSettingsRequest'
      responses:
        '200':
          description: Настройки сетки обновлены
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GridSettingsResponse'
        '400':
          description: Ошибка валидации запроса
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Внутренняя ошибка сервера
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /v1/grid/rebuild:
    post:
      tags:
        - Grid
      summary: Перестроить сетку
      description: Явно пересоздает сетку и пересобирает request_cells для активных заявок.
      operationId: rebuildGrid
      responses:
        '200':
          description: Сетка и проекции активных заявок перестроены
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GridRebuildResponse'
        '409':
          description: Перестроение сетки уже выполняется
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Внутренняя ошибка сервера
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
components:
  parameters:
    RequestIdPathParam:
      name: id
      in: path
      required: true
      description: Идентификатор заявки
      schema:
        type: string
        format: uuid
      example: 3fa85f64-5717-4562-b3fc-2c963f66afa6
  schemas:
    CreateRequestRequest:
      type: object
      description: Данные для создания заявки.
      required:
        - id
        - name
        - geometry
        - importance
        - beginDateTime
        - endDateTime
      properties:
        id:
          type: string
          format: uuid
          description: Внешний идентификатор заявки
          example: 3fa85f64-5717-4562-b3fc-2c963f66afa6
        name:
          type: string
          minLength: 1
          maxLength: 255
          description: Наименование задания.
          example: Тест1
        geometry:
          type: string
          format: wkt
          description: |
            Геометрия заявки в формате WKT.

            Целевой поддерживаемый тип: Polygon.
            Поддержку MultiPolygon нужно включать отдельно, если она подтверждена на уровне grid-логики.
          example: POLYGON ((37.5 55.5, 37.7 55.5, 37.7 55.7, 37.5 55.7, 37.5 55.5))
        importance:
          type: number
          format: double
          minimum: 0
          description: Важность заявки, используемая при расчете важности ячеек сетки.
          example: 10.0
        beginDateTime:
          type: string
          format: date-time
          description: Дата-время начала выполнения заявки
          example: '2026-01-01T00:00:00Z'
        endDateTime:
          type: string
          format: date-time
          description: Дата-время окончания выполнения заявки
          example: '2026-01-31T23:59:59Z'
        kpp:
          type: array
          description: |
            Список номеров КПП для сброса.
            Если не указан, сброс производится на все доступные КПП.
          items:
            type: integer
          default: []
          example: [1, 2, 3]
        highPriorityTransmit:
          type: boolean
          description: Признак высокоприоритетной передачи
          default: false
          example: false
        optics:
          $ref: '#/components/schemas/OpticsParams'
        rsa:
          $ref: '#/components/schemas/RsaParams'
      additionalProperties: false
      anyOf:
        - required:
            - optics
        - required:
            - rsa
    CreateRequestResponse:
      type: object
      description: Ответ на создание заявки
      required:
        - id
        - name
        - status
        - surveyType
        - importance
      properties:
        id:
          type: string
          format: uuid
          description: Идентификатор заявки
          example: 3fa85f64-5717-4562-b3fc-2c963f66afa6
        name:
          type: string
          minLength: 1
          maxLength: 255
          description: Наименование задания.
          example: Тест1
        status:
          $ref: '#/components/schemas/RequestStatus'
        surveyType:
          $ref: '#/components/schemas/SurveyType'
        importance:
          type: number
          format: double
          minimum: 0
          description: Важность заявки, используемая при расчете важности ячеек сетки.
          example: 10.0
        message:
          type: string
          description: Дополнительное сообщение
          example: Заявка успешно создана
    RequestResponse:
      type: object
      description: Полная read-модель заявки
      required:
        - id
        - name
        - status
        - surveyType
        - geometry
        - importance
        - beginDateTime
        - endDateTime
        - highPriorityTransmit
        - coverage
        - createdAt
        - updatedAt
      properties:
        id:
          type: string
          format: uuid
          description: Идентификатор заявки
          example: 3fa85f64-5717-4562-b3fc-2c963f66afa6
        name:
          type: string
          minLength: 1
          maxLength: 255
          description: Наименование задания.
          example: Тест1
        status:
          $ref: '#/components/schemas/RequestStatus'
        surveyType:
          $ref: '#/components/schemas/SurveyType'
        geometry:
          type: string
          format: wkt
          description: Геометрия заявки в формате WKT
          example: POLYGON ((37.5 55.5, 37.7 55.5, 37.7 55.7, 37.5 55.7, 37.5 55.5))
        importance:
          type: number
          format: double
          minimum: 0
          description: Важность заявки, используемая при расчете важности ячеек сетки.
          example: 10.0
        beginDateTime:
          type: string
          format: date-time
          example: '2026-01-01T00:00:00Z'
        endDateTime:
          type: string
          format: date-time
          example: '2026-01-31T23:59:59Z'
        kpp:
          type: array
          items:
            type: integer
          description: Список номеров КПП для сброса
          example: [1, 2, 3]
        highPriorityTransmit:
          type: boolean
          description: Признак высокоприоритетной передачи
          example: false
        optics:
          allOf:
            - $ref: '#/components/schemas/OpticsParams'
          nullable: true
        rsa:
          allOf:
            - $ref: '#/components/schemas/RsaParams'
          nullable: true
        coverage:
          $ref: '#/components/schemas/CoverageState'
        createdAt:
          type: string
          format: date-time
          description: Дата-время создания заявки
          example: '2026-05-19T12:00:00Z'
        updatedAt:
          type: string
          format: date-time
          description: Дата-время последнего обновления заявки
          example: '2026-05-19T12:30:00Z'
        deletedAt:
          type: string
          format: date-time
          nullable: true
          description: Дата-время soft delete. Null, если заявка не удалена.
          example: null
      additionalProperties: false
    RequestSummaryResponse:
      type: object
      description: Краткая карточка заявки для list endpoint
      required:
        - id
        - name
        - status
        - surveyType
        - importance
        - beginDateTime
        - endDateTime
        - highPriorityTransmit
        - coveragePercent
        - createdAt
        - updatedAt
      properties:
        id:
          type: string
          format: uuid
          description: Идентификатор заявки
          example: 3fa85f64-5717-4562-b3fc-2c963f66afa6
        name:
          type: string
          minLength: 1
          maxLength: 255
          description: Наименование задания.
          example: Тест1
        status:
          $ref: '#/components/schemas/RequestStatus'
        surveyType:
          $ref: '#/components/schemas/SurveyType'
        importance:
          type: number
          format: double
          minimum: 0
          description: Важность заявки, используемая при расчете важности ячеек сетки.
          example: 10.0
        beginDateTime:
          type: string
          format: date-time
          example: '2026-01-01T00:00:00Z'
        endDateTime:
          type: string
          format: date-time
          example: '2026-01-31T23:59:59Z'
        kpp:
          type: array
          items:
            type: integer
          description: Список номеров КПП для сброса
          example: [1, 2, 3]
        highPriorityTransmit:
          type: boolean
          example: false
        coveragePercent:
          type: number
          format: double
          minimum: 0
          maximum: 100
          description: Текущий процент покрытия заявки
          example: 35.5
        createdAt:
          type: string
          format: date-time
          example: '2026-05-19T12:00:00Z'
        updatedAt:
          type: string
          format: date-time
          example: '2026-05-19T12:30:00Z'
        deletedAt:
          type: string
          format: date-time
          nullable: true
          description: Дата-время soft delete. Обычно отсутствует/null при includeDeleted=false.
          example: null
      additionalProperties: false
    RequestListResponse:
      type: object
      description: Постраничный список заявок
      required:
        - items
        - page
        - size
        - totalItems
        - totalPages
      properties:
        items:
          type: array
          items:
            $ref: '#/components/schemas/RequestSummaryResponse'
        page:
          type: integer
          minimum: 0
          example: 0
        size:
          type: integer
          minimum: 1
          example: 50
        totalItems:
          type: integer
          format: int64
          minimum: 0
          example: 1
        totalPages:
          type: integer
          minimum: 0
          example: 1
      additionalProperties: false
    RequestMapItemResponse:
      type: object
      description: Краткая карточка заявки с полной геометрией для GET /v1/requests/map
      required:
        - id
        - name
        - status
        - surveyType
        - geometry
        - importance
        - beginDateTime
        - endDateTime
        - highPriorityTransmit
        - coveragePercent
        - createdAt
        - updatedAt
      properties:
        id:
          type: string
          format: uuid
          description: Идентификатор заявки
          example: 3fa85f64-5717-4562-b3fc-2c963f66afa6
        name:
          type: string
          minLength: 1
          maxLength: 255
          description: Наименование задания.
          example: Тест1
        status:
          $ref: '#/components/schemas/RequestStatus'
        surveyType:
          $ref: '#/components/schemas/SurveyType'
        geometry:
          type: string
          format: wkt
          description: Полная геометрия заявки в формате WKT
          example: POLYGON ((37.5 55.5, 37.7 55.5, 37.7 55.7, 37.5 55.7, 37.5 55.5))
        importance:
          type: number
          format: double
          minimum: 0
          description: Важность заявки, используемая при расчете важности ячеек сетки.
          example: 10.0
        beginDateTime:
          type: string
          format: date-time
          example: '2026-01-01T00:00:00Z'
        endDateTime:
          type: string
          format: date-time
          example: '2026-01-31T23:59:59Z'
        kpp:
          type: array
          items:
            type: integer
          description: Список номеров КПП для сброса
          example: [1, 2, 3]
        highPriorityTransmit:
          type: boolean
          example: false
        coveragePercent:
          type: number
          format: double
          minimum: 0
          maximum: 100
          description: Текущий процент покрытия заявки
          example: 35.5
        createdAt:
          type: string
          format: date-time
          example: '2026-05-19T12:00:00Z'
        updatedAt:
          type: string
          format: date-time
          example: '2026-05-19T12:30:00Z'
        deletedAt:
          type: string
          format: date-time
          nullable: true
          description: Дата-время soft delete. Обычно отсутствует/null при includeDeleted=false.
          example: null
      additionalProperties: false
    RequestMapPageResponse:
      type: object
      description: Постраничный список заявок с полной геометрией для GET /v1/requests/map
      required:
        - items
        - page
        - size
        - totalItems
        - totalPages
      properties:
        items:
          type: array
          items:
            $ref: '#/components/schemas/RequestMapItemResponse'
        page:
          type: integer
          minimum: 0
          example: 0
        size:
          type: integer
          minimum: 1
          example: 50
        totalItems:
          type: integer
          format: int64
          minimum: 0
          example: 1
        totalPages:
          type: integer
          minimum: 0
          example: 1
      additionalProperties: false
    DeleteRequestResponse:
      type: object
      description: Ответ на soft delete заявки
      required:
        - id
        - deletedAt
      properties:
        id:
          type: string
          format: uuid
          description: Идентификатор заявки
          example: 3fa85f64-5717-4562-b3fc-2c963f66afa6
        deletedAt:
          type: string
          format: date-time
          description: Дата-время soft delete
          example: '2026-05-19T13:00:00Z'
      additionalProperties: false
    CellSummaryResponse:
      type: object
      description: Краткая карточка ячейки сетки
      required:
        - cellNum
        - latitude
        - longitude
        - importance
        - contour
      properties:
        cellNum:
          type: integer
          format: int64
          description: Номер ячейки сетки
          example: 32400
        latitude:
          type: number
          format: double
          description: Широта центра ячейки
          example: 55.0
        longitude:
          type: number
          format: double
          description: Долгота центра ячейки
          example: 37.0
        importance:
          type: number
          format: double
          minimum: 0
          description: Расчетная важность ячейки
          example: 10.0
        contour:
          type: string
          format: wkt
          description: Контур ячейки в формате WKT
          example: POLYGON ((36 55, 37 55, 37 56, 36 56, 36 55))
      additionalProperties: false
    CellsListResponse:
      type: object
      description: Постраничный список ячеек сетки
      required:
        - items
        - page
        - size
        - totalItems
        - totalPages
      properties:
        items:
          type: array
          items:
            $ref: '#/components/schemas/CellSummaryResponse'
        page:
          type: integer
          minimum: 0
          example: 0
        size:
          type: integer
          minimum: 1
          example: 50
        totalItems:
          type: integer
          format: int64
          minimum: 0
          example: 1
        totalPages:
          type: integer
          minimum: 0
          example: 1
      additionalProperties: false
    CellWithRequestsResponse:
      type: object
      description: Ячейка сетки с фрагментами заявок
      required:
        - cellNum
        - latitude
        - longitude
        - importance
        - contour
        - requests
      properties:
        cellNum:
          type: integer
          format: int64
          description: Номер ячейки сетки
          example: 32400
        latitude:
          type: number
          format: double
          description: Широта центра ячейки
          example: 55.0
        longitude:
          type: number
          format: double
          description: Долгота центра ячейки
          example: 37.0
        importance:
          type: number
          format: double
          minimum: 0
          description: Расчетная важность ячейки
          example: 10.0
        contour:
          type: string
          format: wkt
          description: Контур ячейки в формате WKT
          example: POLYGON ((36 55, 37 55, 37 56, 36 56, 36 55))
        requests:
          type: array
          description: Фрагменты заявок, пересекающие ячейку
          items:
            $ref: '#/components/schemas/CellRequestFragmentResponse'
      additionalProperties: false
    CellRequestFragmentResponse:
      type: object
      description: Фрагмент заявки внутри ячейки сетки
      required:
        - requestId
        - contour
        - coveragePercent
        - importance
      properties:
        requestId:
          type: string
          format: uuid
          description: Идентификатор заявки
          example: 3fa85f64-5717-4562-b3fc-2c963f66afa6
        contour:
          type: string
          format: wkt
          description: Контур пересечения заявки с ячейкой в формате WKT
          example: POLYGON ((36.5 55.5, 37 55.5, 37 56, 36.5 56, 36.5 55.5))
        coveragePercent:
          type: number
          format: double
          minimum: 0
          maximum: 100
          description: Процент покрытия ячейки фрагментом заявки
          example: 25.0
        importance:
          type: number
          format: double
          minimum: 0
          description: Важность заявки для расчета важности ячейки
          example: 10.0
      additionalProperties: false
    CellPriorityMapResponse:
      type: object
      description: Список ячеек сетки с фрагментами заявок для GET /v1/cells/priority-map
      required:
        - items
      properties:
        items:
          type: array
          items:
            $ref: '#/components/schemas/CellWithRequestsResponse'
      additionalProperties: false
    RequestWithCellsResponse:
      type: object
      description: Заявка с проекциями на ячейки сетки
      required:
        - request
        - cells
      properties:
        request:
          $ref: '#/components/schemas/RequestResponse'
        cells:
          type: array
          items:
            $ref: '#/components/schemas/RequestCellResponse'
      additionalProperties: false
    RequestCellResponse:
      type: object
      description: Ячейка, связанная с заявкой
      required:
        - cellNum
        - coveragePercent
        - importance
        - contour
      properties:
        cellNum:
          type: integer
          format: int64
          description: Номер ячейки сетки
          example: 32400
        coveragePercent:
          type: number
          format: double
          minimum: 0
          maximum: 100
          description: Процент покрытия ячейки заявкой
          example: 25.0
        importance:
          type: number
          format: double
          minimum: 0
          description: Важность заявки для расчета важности ячейки
          example: 10.0
        contour:
          type: string
          format: wkt
          description: Контур пересечения заявки с ячейкой в формате WKT
          example: POLYGON ((36.5 55.5, 37 55.5, 37 56, 36.5 56, 36.5 55.5))
      additionalProperties: false
    GridSettingsResponse:
      type: object
      description: Текущие настройки сетки
      required:
        - settingsId
        - calculationStep
      properties:
        settingsId:
          type: integer
          format: int64
          description: Идентификатор набора настроек сетки
          example: 1
        calculationStep:
          type: number
          format: double
          minimum: 0
          exclusiveMinimum: true
          description: Шаг построения сетки в градусах
          example: 2.0
      additionalProperties: false
    UpdateGridSettingsRequest:
      type: object
      description: Обновляемые настройки сетки
      required:
        - calculationStep
      properties:
        calculationStep:
          type: number
          format: double
          minimum: 0
          exclusiveMinimum: true
          description: Новый шаг построения сетки в градусах. Обновление не запускает rebuild автоматически.
          example: 2.0
      additionalProperties: false
    GridRebuildResponse:
      type: object
      description: Результат явного перестроения сетки
      required:
        - cellsCount
        - rebuiltRequestProjectionsCount
        - rebuiltAt
      properties:
        cellsCount:
          type: integer
          format: int64
          minimum: 0
          description: Количество ячеек после перестроения сетки
          example: 16200
        rebuiltRequestProjectionsCount:
          type: integer
          format: int64
          minimum: 0
          description: Количество пересобранных проекций активных заявок в request_cells
          example: 1250
        rebuiltAt:
          type: string
          format: date-time
          description: Дата-время завершения перестроения
          example: '2026-05-20T10:15:30Z'
      additionalProperties: false
    CoverageState:
      type: object
      description: Состояние покрытия заявки
      required:
        - currentPercent
      properties:
        requiredPercent:
          type: number
          format: double
          minimum: 0
          maximum: 100
          nullable: true
          description: Требуемый процент покрытия
          example: 100.0
        currentPercent:
          type: number
          format: double
          minimum: 0
          maximum: 100
          description: Текущий процент покрытия
          example: 35.5
      additionalProperties: false
    OpticsParams:
      type: object
      required:
        - resultType
        - resolution
      description: Параметры оптической съемки
      properties:
        resultType:
          type: string
          description: Результат оптической съемки
          enum:
            - PANCHROMATIC
            - MULTISPECTRAL
            - PANSHARPENING
          default: PANCHROMATIC
          example: PANCHROMATIC
        resolution:
          type: number
          format: double
          description: Требуемое разрешение съемки, метры
          minimum: 0.1
          example: 1.0
        sunAngleMin:
          type: number
          format: double
          description: Минимальная высота Солнца, градусы
          minimum: 0
          maximum: 90
          default: 10.0
          example: 10.0
        sunAngleMax:
          type: number
          format: double
          description: Максимальная высота Солнца, градусы
          minimum: 0
          maximum: 90
          default: 90.0
          example: 90.0
        clouds:
          type: number
          format: double
          description: Максимально допустимая облачность, проценты
          minimum: 0
          maximum: 100
          default: 100.0
          example: 90.0
      additionalProperties: false
    RsaParams:
      type: object
      required:
        - resultType
        - resolution
        - polarisation
      description: Параметры радиолокационной съемки РСА
      properties:
        resultType:
          type: string
          description: Тип аппаратуры РСА
          enum:
            - SPOTLIGHT
            - STRIPMAP
            - SCANSAR
          example: SPOTLIGHT
        interferometry:
          type: boolean
          description: Признак интерферометрии
          default: false
          example: true
        polarisation:
          type: string
          description: Тип поляризации
          enum:
            - HH
            - VV
          example: HH
        resolution:
          type: number
          format: double
          description: Требуемое разрешение съемки, метры
          minimum: 0.1
          example: 3.0
      additionalProperties: false
    RequestStatus:
      type: string
      description: Доменный статус заявки
      enum:
        - ACCEPTED
        - ACTIVE
        - COMPLETED
        - EXPIRED
        - DELETED
      x-enum-descriptions:
        - Заявка прошла валидацию и сохранена.
        - Заявка актуальна для обработки.
        - Заявка выполнена.
        - Временное окно заявки истекло.
        - Заявка мягко удалена.
    SurveyType:
      type: string
      description: Вычисленный тип заявки по наличию optics/rsa
      enum:
        - OPTICS
        - RSA
        - COMBINED
      x-enum-descriptions:
        - В заявке указан только optics.
        - В заявке указан только rsa.
        - В заявке указаны optics и rsa.
    ErrorResponse:
      type: object
      description: Ошибка API
      required:
        - code
        - message
      properties:
        code:
          type: string
          description: Машиночитаемый код ошибки
          example: VALIDATION_ERROR
        message:
          type: string
          description: Человекочитаемое описание ошибки
          example: 'Должен быть указан хотя бы один блок съемки: optics или rsa'
        details:
          type: array
          description: Детали ошибки по полям
          items:
            $ref: '#/components/schemas/ErrorDetail'
      additionalProperties: false
    ErrorDetail:
      type: object
      description: Деталь ошибки валидации
      required:
        - field
        - message
      properties:
        field:
          type: string
          description: Поле, к которому относится ошибка
          example: optics
        message:
          type: string
          description: Описание ошибки поля
          example: 'Должен быть указан хотя бы один блок съемки: optics или rsa'
      additionalProperties: false
