Отчёты (API)
REST API конструктора отчётов: управление определениями, выполнение, экспорт и расписания. Все маршруты требуют аутентификации (Bearer-токен, см. Аутентификация).
Эндпоинты
| Метод | URL | Назначение |
|---|---|---|
GET | /api/sys/reports/entities | Сущности текущего тенанта, доступные для отчётов |
GET | /api/sys/reports/meta/{sysTableId} | Дерево полей сущности (включая поля связанных) и источники агрегатов |
GET | /api/sys/reports | Список доступных отчётов |
POST | /api/sys/reports | Создать отчёт |
GET | /api/sys/reports/{id} | Получить отчёт |
PUT | /api/sys/reports/{id} | Обновить отчёт |
DELETE | /api/sys/reports/{id} | Удалить отчёт (вместе с расписаниями и файлами) |
GET/PUT | /api/sys/reports/{id}/assignments | Доступ: назначения на пользователей/роли/группы |
POST | /api/sys/reports/{id}/data | Выполнить синхронно (HTML-просмотр, до 10 000 строк) |
POST | /api/sys/reports/{id}/export | Запустить фоновый экспорт (csv / xlsx / pdf) |
GET | /api/sys/reports/{id}/runs | История выгрузок |
GET | /api/sys/report-runs/{runId} | Статус выгрузки (queued / running / done / failed) |
GET | /api/sys/report-runs/{runId}/download | Скачать готовый файл |
GET/POST | /api/sys/reports/{id}/schedules | Расписания отчёта |
PUT/DELETE | /api/sys/report-schedules/{scheduleId} | Изменить/удалить расписание |
POST | /api/sys/report-schedules/{scheduleId}/run-now | Выполнить расписание немедленно |
Права: reports.build — создание/редактирование своих отчётов, reports.view — выполнение назначенных, admin.reports (роль report_administrator) — все отчёты тенанта. Данные фильтруются правилами доступа к записям выполняющего пользователя; расписания выполняются от имени владельца отчёта.
Структура определения (definition)
{
"columns": [
{ "field": "number" },
{ "field": "title", "label": { "ru": "Тема", "en": "Subject" } },
{ "path": ["client_id"], "field": "name" },
{
"type": "related_aggregate",
"fn": "count",
"relation": { "kind": "reverse_field", "entity": "deals", "field": "client_id" },
"conditions": [
{ "field": "status", "operator": "=", "value": "open" }
],
"label": { "ru": "Открытых сделок" }
}
],
"filters": [
{
"id": "created_period",
"field": "created_at",
"operator": "relative_period",
"value": { "period": "last_week" },
"is_parameter": true,
"required": true
}
],
"group_by": [
{ "field": "assignee_id", "order": "asc" }
],
"aggregations": [
{ "fn": "count", "field": "*" },
{ "fn": "p90", "field": "resolution_hours" }
],
"sort": [
{ "field": "created_at", "dir": "desc" }
]
}Ключевые правила (проверяются валидатором при сохранении):
columns— обязательна хотя бы одна колонка. Поле связанной сущности задаётся черезpath— список ссылочных полей-переходов от основной сущности (не более 2 переходов). Колонок типаrelated_aggregate— не более 10.filters.operator— один из:=,!=,like,>,<,>=,<=,in,date_range,relative_period,between,is_null,not_null,category,exists_related. Фильтр сis_parameter: trueможет быть переопределён при выполнении.group_by— не более 3 уровней,order—asc|desc.aggregations.fn—count,sum,avg,min,maxили перцентильpNN(p50,p90,p95,p99, …). Все, кромеcount, требуют числовое поле; агрегируемое поле должно присутствовать вcolumns— итог выводится в этой колонке."field": "*"допустим только дляcount.related_aggregate—fnте же; для не-countобязателен числовойtarget_fieldдочерней сущности;conditionsподдерживают операторы=,!=,like,>,<,>=,<=,in,date_range,is_null,not_null.
Примеры
Создать отчёт
curl -X POST "$ORBITA_URL/api/sys/reports" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"title": "Заявки за неделю по исполнителям",
"sys_table_id": 12,
"definition": {
"columns": [
{ "field": "number" },
{ "field": "title" },
{ "field": "assignee_id" }
],
"filters": [
{ "id": "period", "field": "created_at", "operator": "relative_period",
"value": { "period": "last_week" }, "is_parameter": true }
],
"group_by": [{ "field": "assignee_id", "order": "asc" }],
"aggregations": [{ "fn": "count", "field": "*" }]
}
}'Выполнить с параметрами
Значения параметров передаются по id фильтра:
curl -X POST "$ORBITA_URL/api/sys/reports/5/data" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{ "parameters": { "period": { "period": "last_n_days", "n": 30 } } }'Экспорт и скачивание
Экспорт асинхронный: запрос ставит задачу в отдельную очередь reports, ответ содержит run. Дальше — опрос статуса и скачивание:
RUN_ID=$(curl -s -X POST "$ORBITA_URL/api/sys/reports/5/export" \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{ "format": "xlsx" }' | jq -r '.data.id')
# статус: queued → running → done | failed
curl -s "$ORBITA_URL/api/sys/report-runs/$RUN_ID" -H "Authorization: Bearer $TOKEN"
curl -L -o report.xlsx "$ORBITA_URL/api/sys/report-runs/$RUN_ID/download" \
-H "Authorization: Bearer $TOKEN"Лимиты форматов: XLSX — 50 000 строк, PDF — 1 000 строк (настраиваются переменными REPORTS_XLSX_MAX_ROWS / REPORTS_PDF_MAX_ROWS, см. Переменные окружения). Файлы хранятся 30 дней (REPORTS_RUN_TTL_DAYS).
Расписание рассылки
curl -X POST "$ORBITA_URL/api/sys/reports/5/schedules" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"cron_expression": "0 8 * * 1",
"timezone": "Europe/Moscow",
"format": "xlsx",
"recipients": [
{ "type": "user", "id": 7 },
{ "type": "email", "value": "cfo@example.com" }
],
"parameters": { "period": { "period": "last_week" } },
"is_active": true
}'Файл до 10 МБ уходит вложением, крупнее — подписанной ссылкой (срок жизни 7 дней). Письма отправляются от имени владельца отчёта и с его правами на данные.
Очередь reports
Экспорт и расписания обрабатывает выделенная очередь reports (соединение database_reports или redis_reports — по драйверу очередей инсталляции). Убедитесь, что воркер этой очереди запущен: php artisan queue:work database_reports --queue=reports.