Перейти к содержимому
СервисАпп API
На этой странице

Расчёт и применение маршрута выездов

Все операции. Авторизация. Запросы и повторы.

Все пути в этом файле дополняют /api/v1 на домене организации.

Описание и ограничения

Назначение

Проверяемый расчёт оптимизации/распределения выездов и отдельное применение предложения к расписанию.

Поля и назначение

Публичное поле Формат и смысл Доступ
id UUID только чтение
date, workshop_id, user_ids, visit_ids один день, мастерская и ограниченные наборы входное поле
mode, work_start, work_end, return_to_workshop optimize / distribute, HH:mm, логическое значение входное поле
status, progress, preview состояние и предложение только чтение
version меняется на advance/apply/cancel, непрозрачная строка только чтение
source_version отдельная непрозрачная строка; сохраняется на старте только чтение
operation_id ID расчётной операции только чтение
budget max_requests и max_matrix_pairs, положительные целые входное поле / только чтение
usage requests и matrix_pairs, целые числа только чтение
error null либо объект code/message; без сырых ошибок провайдера только чтение

Обязательность и null указаны в схемах каждой операции ниже.

Доступ и выборка

visit_route_plans:read/write и полномочия диспетчеризации; доступ к каждой мастерской/единице состава и отдельный разрешённый бюджет геосервиса.

Запросы и состояния

Для создания требуются date, workshop_id, mode, work_start, work_end, user_ids, visit_ids и budget. Work_start/work_end — HH:mm в context.timezone, внутри одного дня, начало раньше конца. user_ids — 1–100 уникальных сотрудников одной мастерской; для optimize ровно один. visit_ids — 1–100 уникальных доступных выездов. Это лимит пакета внешнего API, не ограничение числа выездов в панели. return_to_workshop=false по умолчанию. Переданные source/matrix/preview/status запрещены.

budget содержит ровно max_requests (1–1000 внешних HTTP-запросов route/matrix суммарно) и max_matrix_pairs (1–10000 пар матрицы). Это ограничение количества платных обращений, не обещание фиксированной цены в RUB. Оно дополнительно ограничивается доступной квотой подключения; денежный тариф геосервиса не меняется. Расход по лимиту резервируется до внешнего запроса и учитывает неизвестный результат. Повтор запроса шага не расходует бюджет снова; иной Idempotency-Key не даёт выполнить уже закреплённый шаг повторно.

Для платных шагов нужна отдельно настроенная дневная квота подключения. День считается по UTC. Без положительной квоты такие шаги запрещены. Расход относится к дню резервирования; поздний ответ, восстановление или отмена не переносят его на другой день. Неизвестный результат внешнего запроса не освобождает зарезервированный расход. Каждый новый шаг ограничен оставшимся бюджетом плана и дневной квотой.

Создание возвращает 201 с карточкой status=pending и сохранённым source_version, без оплачиваемого расчёта. status: pending/processing/ready/applied/cancelled/failed/needs_reconciliation. progress: { "completed_steps": 0, "total_steps": 4 }; total_steps может уточниться после разбивки дальних пар. preview=null до готовности, затем { "moves": [{"visit_id": 12, "crew_user_ids": [3], "starts_at": "…", "ends_at": "…"}], "unassigned_visit_ids": [] }; это только предложение, без сырых provider matrix/source. operation_id указывает на последний принятый шаг.

Advance/apply/cancel принимают {} и If-Resource-Version версии расчёта. Advance закрепляет один следующий шаг, отвечает 202 при фоновой обработке или 200 при уже готовом расчёте без нового эффекта; одновременно допускается один исполнитель. Исчерпание бюджета — failed с ROUTE_BUDGET_EXHAUSTED; неизвестный внешний исход — needs_reconciliation, без слепого повтора. Apply разрешён только для ready, перепроверяет source_version, текущие права, весь состав, окна и пересечения под блокировками, затем атомарно сохраняет предложение; устаревшее расписание — 409 ROUTE_SOURCE_CHANGED, новое действие требует нового расчёта. Устаревший If-Resource-Version самого плана — 412.

Если бюджета недостаточно до закрепления внешнего шага, advance возвращает 200 с карточкой status=failed и error.code=ROUTE_BUDGET_EXHAUSTED; расход не увеличивается, ложный ответ 202 не создаётся. error=null означает отсутствие сохранённой ошибки. Остальные значения ошибки преобразуются через фиксированный список разрешённых значений кодов и сообщений сервера.

Ответ 202 содержит карточку со status=processing, а также транспортный state=processing и ID принятой операции. Эта запись об операции неизменна: повтор запроса возвращает исходный 202 и после завершения шага. Текущее состояние читается через GET плана или журнал операции; новый advance готового плана без эффекта возвращает 200.

Apply возвращает 200 с карточкой applied и affected_resources выездов; GET карточки не делает геозапросов. Cancel прекращает только новые шаги, уже отправленный запрос доводится до учёта результата/неизвестного результата; 200 с cancelled, расход уже отправленного шага не обещается вернуть. Отмена applied не откатывает расписание и возвращает 409 ROUTE_PLAN_ALREADY_APPLIED.

Готовое предложение без изменений расписания не применяется: apply возвращает 409 ROUTE_PLAN_HAS_NO_CHANGES, сохраняя карточку ready. Неготовое или уже завершённое состояние возвращает 409 ROUTE_PLAN_NOT_READY.

Правила и связи

  • Клиент получает ID и не может прислать отредактированную matrix/source/preview для apply.
  • GET не запускает геозапросы. Каждый POST advance имеет собственный ключ шага; повтор шага не запрашивает платную матрицу повторно.
  • Применение сравнивает актуальный состав/расписание и атомарно меняет назначения.
  • Расчёт и сохранение расписания разделены; cancel расчёта не отменяет уже применённые выезды.
  • Следуют существующим ограничениям бригад, окон и одной мастерской/дня.

Операции

Метод Путь Назначение
POST /visit-route-plans Создание серверного расчёта с явным бюджетом
GET /visit-route-plans/{id} Текущее состояние и предложение
POST /visit-route-plans/{id}/cancel Остановка незавершённого расчёта
POST /visit-route-plans/{id}/advance Продолжение ограниченного шага расчёта
POST /visit-route-plans/{id}/apply Применение актуального предложения

POST /visit-route-plans

Создание серверного расчёта с явным бюджетом.

Доступ. Разрешения подключения: visit_route_plans:write. Права сотрудника: «Акты приёма оборудования → Изменение», «Акты приёма оборудования → Просмотр». Дополнительно действуют доступ к записям, мастерским, модулям и условия полей из описания ресурса выше.

Параметры

Имя Где Тип Обязательно null Ограничения
Authorization заголовок строка да нет Bearer <SERVICEAPP_TOKEN>
Idempotency-Key заголовок строка да нет не менее 1 символов; не более 128 символов; Шаблон: ^[A-Za-z0-9._:-]+$

Тело запроса

Content-Type: application/json. Тело обязательно.

Поле Тип Обязательно null Ограничения и смысл
date строка (дата) да нет —
workshop_id целое число да нет ≥ 1
mode строка да нет Допустимо: "optimize", "distribute"
work_start строка да нет Шаблон: ^(?:[01]\d|2[0-3]):[0-5]\d$
work_end строка да нет Шаблон: ^(?:[01]\d|2[0-3]):[0-5]\d$; Условие: after:work_start
user_ids массив да нет не менее 1 элементов; не более 100 элементов; Без повторов
user_ids[] целое число да нет ≥ 1
visit_ids массив да нет не менее 1 элементов; не более 100 элементов; Без повторов
visit_ids[] целое число да нет ≥ 1
return_to_workshop логическое значение нет нет —
budget объект да нет Только перечисленные ключи
budget.max_requests целое число да нет ≥ 1; ≤ 1000
budget.max_matrix_pairs целое число да нет ≥ 1; ≤ 10000

Ответы

HTTP Назначение и схема
201 Создано. Полная схема и пример
401 Требуется действующий Bearer. Коды и формат ошибки
403 Недостаточно допуска. Коды и формат ошибки
404 Не найдено или недоступно. Коды и формат ошибки
409 Конфликт состояния или повтора. Коды и формат ошибки
422 Ошибка входных данных. Коды и формат ошибки
429 Лимит запросов, Retry-After. Коды и формат ошибки
503 Временно недоступно. Коды и формат ошибки
HTTP Заголовок ответа Тип Описание
201 Location строка

Каждый ответ содержит новый X-Request-Id в заголовке. Общие транспортные отказы и правила повтора действуют также при отказе до контроллера; см. ошибки.

У принятого POST Location и meta.operation_id указывают на журнал операции; ETag отсутствует. При повторе запроса сохраняются исходные data/meta, добавляется Idempotency-Replayed: true. Версии передавайте по назначению, указанному в описании ресурса.

Пример запроса

Запускается из каталога комплекта после настройки переменных в быстром старте. Замените демонстрационные идентификаторы 101 и UUID идентификаторами доступных записей. $RESOURCE_VERSION берётся из GET владельца версии, описанного выше. Для нового действия сохраните новый ключ; для повтора используйте прежний.

curl --silent --show-error --globoff --request POST \
  "$API/visit-route-plans" \
  --header "Authorization: Bearer $SERVICEAPP_TOKEN" \
  --header "Accept: application/json" \
  --header "Idempotency-Key: example:v1-visit-route-plans-create:001" \
  --header "Content-Type: application/json" \
  --data-binary '@examples/requests/v1.visit-route-plans.create.json'

GET /visit-route-plans/{id}

Текущее состояние и предложение.

Доступ. Разрешения подключения: visit_route_plans:read. Права сотрудника: «Акты приёма оборудования → Просмотр». Дополнительно действуют доступ к записям, мастерским, модулям и условия полей из описания ресурса выше.

Параметры

Имя Где Тип Обязательно null Ограничения
Authorization заголовок строка да нет Bearer <SERVICEAPP_TOKEN>
id путь строка да нет Шаблон: ^(?:[\da-fA-F]{8}-[\da-fA-F]{4}-[\da-fA-F]{4}-[\da-fA-F]{4}-[\da-fA-F]{12})$
If-None-Match заголовок строка нет нет —

Ответы

HTTP Назначение и схема
200 Успех. Полная схема и пример
304 Представление не изменилось, без тела. Условный GET
401 Требуется действующий Bearer. Коды и формат ошибки
403 Недостаточно допуска. Коды и формат ошибки
404 Не найдено или недоступно. Коды и формат ошибки
422 Ошибка входных данных. Коды и формат ошибки
429 Лимит запросов, Retry-After. Коды и формат ошибки
503 Временно недоступно. Коды и формат ошибки
HTTP Заголовок ответа Тип Описание
200 ETag строка
304 ETag строка

Каждый ответ содержит новый X-Request-Id в заголовке. Общие транспортные отказы и правила повтора действуют также при отказе до контроллера; см. ошибки.

Пример запроса

Запускается из каталога комплекта после настройки переменных в быстром старте. Замените демонстрационные идентификаторы 101 и UUID идентификаторами доступных записей. $RESOURCE_VERSION берётся из GET владельца версии, описанного выше. Для нового действия сохраните новый ключ; для повтора используйте прежний.

curl --silent --show-error --globoff \
  "$API/visit-route-plans/ef62763b-87f9-4c90-83bb-e919f3c8e111" \
  --header "Authorization: Bearer $SERVICEAPP_TOKEN" \
  --header "Accept: application/json"

POST /visit-route-plans/{id}/cancel

Остановка незавершённого расчёта.

Доступ. Разрешения подключения: visit_route_plans:write. Права сотрудника: «Акты приёма оборудования → Изменение», «Акты приёма оборудования → Просмотр». Дополнительно действуют доступ к записям, мастерским, модулям и условия полей из описания ресурса выше.

Параметры

Имя Где Тип Обязательно null Ограничения
Authorization заголовок строка да нет Bearer <SERVICEAPP_TOKEN>
id путь строка да нет Шаблон: ^(?:[\da-fA-F]{8}-[\da-fA-F]{4}-[\da-fA-F]{4}-[\da-fA-F]{4}-[\da-fA-F]{12})$
Idempotency-Key заголовок строка да нет не менее 1 символов; не более 128 символов; Шаблон: ^[A-Za-z0-9._:-]+$
If-Resource-Version заголовок строка да нет не менее 1 символов; не более 128 символов; Шаблон: ^[A-Za-z0-9._~-]+$

Тело запроса

Content-Type: application/json. Тело обязательно.

Тело — пустой JSON-объект {}. Другие ключи не принимаются.

Ответы

HTTP Назначение и схема
200 Успех. Полная схема и пример
401 Требуется действующий Bearer. Коды и формат ошибки
403 Недостаточно допуска. Коды и формат ошибки
404 Не найдено или недоступно. Коды и формат ошибки
409 Конфликт состояния или повтора. Коды и формат ошибки
412 Версия устарела. Коды и формат ошибки
422 Ошибка входных данных. Коды и формат ошибки
428 Нужно предусловие версии. Коды и формат ошибки
429 Лимит запросов, Retry-After. Коды и формат ошибки
503 Временно недоступно. Коды и формат ошибки
HTTP Заголовок ответа Тип Описание
200 Location строка

Каждый ответ содержит новый X-Request-Id в заголовке. Общие транспортные отказы и правила повтора действуют также при отказе до контроллера; см. ошибки.

У принятого POST Location и meta.operation_id указывают на журнал операции; ETag отсутствует. При повторе запроса сохраняются исходные data/meta, добавляется Idempotency-Replayed: true. Версии передавайте по назначению, указанному в описании ресурса.

Пример запроса

Запускается из каталога комплекта после настройки переменных в быстром старте. Замените демонстрационные идентификаторы 101 и UUID идентификаторами доступных записей. $RESOURCE_VERSION берётся из GET владельца версии, описанного выше. Для нового действия сохраните новый ключ; для повтора используйте прежний.

curl --silent --show-error --globoff --request POST \
  "$API/visit-route-plans/ef62763b-87f9-4c90-83bb-e919f3c8e111/cancel" \
  --header "Authorization: Bearer $SERVICEAPP_TOKEN" \
  --header "Accept: application/json" \
  --header "Idempotency-Key: example:v1-visit-route-plans-cancel:001" \
  --header "If-Resource-Version: $RESOURCE_VERSION" \
  --header "Content-Type: application/json" \
  --data-binary '@examples/requests/v1.visit-route-plans.cancel.json'

POST /visit-route-plans/{id}/advance

Продолжение ограниченного шага расчёта.

Доступ. Разрешения подключения: visit_route_plans:write. Права сотрудника: «Акты приёма оборудования → Изменение», «Акты приёма оборудования → Просмотр». Дополнительно действуют доступ к записям, мастерским, модулям и условия полей из описания ресурса выше.

Параметры

Имя Где Тип Обязательно null Ограничения
Authorization заголовок строка да нет Bearer <SERVICEAPP_TOKEN>
id путь строка да нет Шаблон: ^(?:[\da-fA-F]{8}-[\da-fA-F]{4}-[\da-fA-F]{4}-[\da-fA-F]{4}-[\da-fA-F]{12})$
Idempotency-Key заголовок строка да нет не менее 1 символов; не более 128 символов; Шаблон: ^[A-Za-z0-9._:-]+$
If-Resource-Version заголовок строка да нет не менее 1 символов; не более 128 символов; Шаблон: ^[A-Za-z0-9._~-]+$

Тело запроса

Content-Type: application/json. Тело обязательно.

Тело — пустой JSON-объект {}. Другие ключи не принимаются.

Ответы

HTTP Назначение и схема
200 Успех. Полная схема и пример
202 Принято, итог в журнале. Полная схема и пример
401 Требуется действующий Bearer. Коды и формат ошибки
403 Недостаточно допуска. Коды и формат ошибки
404 Не найдено или недоступно. Коды и формат ошибки
409 Конфликт состояния или повтора. Коды и формат ошибки
412 Версия устарела. Коды и формат ошибки
422 Ошибка входных данных. Коды и формат ошибки
428 Нужно предусловие версии. Коды и формат ошибки
429 Лимит запросов, Retry-After. Коды и формат ошибки
503 Временно недоступно. Коды и формат ошибки
HTTP Заголовок ответа Тип Описание
200 Location строка
202 Location строка
202 Retry-After строка
401 Location строка
403 Location строка
404 Location строка
409 Location строка
412 Location строка
422 Location строка
428 Location строка
429 Location строка
503 Location строка

Каждый ответ содержит новый X-Request-Id в заголовке. Общие транспортные отказы и правила повтора действуют также при отказе до контроллера; см. ошибки.

У принятого POST Location и meta.operation_id указывают на журнал операции; ETag отсутствует. При повторе запроса сохраняются исходные data/meta, добавляется Idempotency-Replayed: true. Версии передавайте по назначению, указанному в описании ресурса.

Пример запроса

Запускается из каталога комплекта после настройки переменных в быстром старте. Замените демонстрационные идентификаторы 101 и UUID идентификаторами доступных записей. $RESOURCE_VERSION берётся из GET владельца версии, описанного выше. Для нового действия сохраните новый ключ; для повтора используйте прежний.

curl --silent --show-error --globoff --request POST \
  "$API/visit-route-plans/ef62763b-87f9-4c90-83bb-e919f3c8e111/advance" \
  --header "Authorization: Bearer $SERVICEAPP_TOKEN" \
  --header "Accept: application/json" \
  --header "Idempotency-Key: example:v1-visit-route-plans-advance:001" \
  --header "If-Resource-Version: $RESOURCE_VERSION" \
  --header "Content-Type: application/json" \
  --data-binary '@examples/requests/v1.visit-route-plans.advance.json'

POST /visit-route-plans/{id}/apply

Применение актуального предложения.

Доступ. Разрешения подключения: visit_route_plans:write. Права сотрудника: «Акты приёма оборудования → Изменение», «Акты приёма оборудования → Просмотр». Дополнительно действуют доступ к записям, мастерским, модулям и условия полей из описания ресурса выше.

Параметры

Имя Где Тип Обязательно null Ограничения
Authorization заголовок строка да нет Bearer <SERVICEAPP_TOKEN>
id путь строка да нет Шаблон: ^(?:[\da-fA-F]{8}-[\da-fA-F]{4}-[\da-fA-F]{4}-[\da-fA-F]{4}-[\da-fA-F]{12})$
Idempotency-Key заголовок строка да нет не менее 1 символов; не более 128 символов; Шаблон: ^[A-Za-z0-9._:-]+$
If-Resource-Version заголовок строка да нет не менее 1 символов; не более 128 символов; Шаблон: ^[A-Za-z0-9._~-]+$

Тело запроса

Content-Type: application/json. Тело обязательно.

Тело — пустой JSON-объект {}. Другие ключи не принимаются.

Ответы

HTTP Назначение и схема
200 Успех. Полная схема и пример
401 Требуется действующий Bearer. Коды и формат ошибки
403 Недостаточно допуска. Коды и формат ошибки
404 Не найдено или недоступно. Коды и формат ошибки
409 Конфликт состояния или повтора. Коды и формат ошибки
412 Версия устарела. Коды и формат ошибки
422 Ошибка входных данных. Коды и формат ошибки
428 Нужно предусловие версии. Коды и формат ошибки
429 Лимит запросов, Retry-After. Коды и формат ошибки
503 Временно недоступно. Коды и формат ошибки
HTTP Заголовок ответа Тип Описание
200 Location строка

Каждый ответ содержит новый X-Request-Id в заголовке. Общие транспортные отказы и правила повтора действуют также при отказе до контроллера; см. ошибки.

У принятого POST Location и meta.operation_id указывают на журнал операции; ETag отсутствует. При повторе запроса сохраняются исходные data/meta, добавляется Idempotency-Replayed: true. Версии передавайте по назначению, указанному в описании ресурса.

Пример запроса

Запускается из каталога комплекта после настройки переменных в быстром старте. Замените демонстрационные идентификаторы 101 и UUID идентификаторами доступных записей. $RESOURCE_VERSION берётся из GET владельца версии, описанного выше. Для нового действия сохраните новый ключ; для повтора используйте прежний.

curl --silent --show-error --globoff --request POST \
  "$API/visit-route-plans/ef62763b-87f9-4c90-83bb-e919f3c8e111/apply" \
  --header "Authorization: Bearer $SERVICEAPP_TOKEN" \
  --header "Accept: application/json" \
  --header "Idempotency-Key: example:v1-visit-route-plans-apply:001" \
  --header "If-Resource-Version: $RESOURCE_VERSION" \
  --header "Content-Type: application/json" \
  --data-binary '@examples/requests/v1.visit-route-plans.apply.json'