Глобальный поиск
Глобальный поиск предназначен для одной фронтенд-страницы поиска и быстрых переходов из результатов в рабочие сущности системы.
Endpoint
GET /api/v1/search?q=<query>&limit=<n>
qобязателен, минимум 2 символа.limitзадает максимум результатов на каждый тип сущности, по умолчанию5, максимум20.- Требуется
Authorization: Bearer <token>.
Что ищется
Ответ сгруппирован по типам:
companies— активные компании по названию, юр. названию, ИНН и email.contacts— активные контакты по ФИО, email и телефону.projects— неархивные проекты по названию и описанию.tasks— задачи по названию и описанию.users— активные пользователи по ФИО, email и должности.
Видимость
Поиск не раскрывает сущности сверх прав текущего пользователя.
- Компании возвращаются только при
companies.manageили ролиadmin. - Контакты возвращаются только при
contacts.manageили ролиadmin. - Проекты для не-admin ограничены проектами, где пользователь менеджер, участник команды или участник связанной задачи; руководитель отдела продаж видит все проекты.
- Задачи для не-admin ограничены задачами, где пользователь автор, исполнитель, соисполнитель, руководитель исполнителя/соисполнителя или менеджер проекта.
- Пользователи доступны всем авторизованным пользователям.
Формат результата
Каждый результат содержит url — SPA-путь для перехода во фронтенде (как entityRoute клиента): компания /companies/:id, контакт /clients/:id, проект /projects/:id, задача /tasks?taskId=:id&taskProjectId=:project_id, сотрудник /admin/org?userId=:id. Клиент строит ссылку сам по type/id и не показывает ссылку, если маршрут закрыт матрицей прав. Для дочерних сущностей может быть parent, чтобы UI мог показать контекст и перейти в родительскую карточку.
{
"query": "иван",
"results": {
"companies": [
{
"type": "company",
"id": 1,
"title": "ООО Пример",
"subtitle": "Общество с ограниченной ответственностью Пример",
"url": "/companies/1"
}
],
"contacts": [
{
"type": "contact",
"id": 7,
"title": "Иван Петров",
"subtitle": "ivan.petrov@example.com",
"url": "/clients/7",
"parent": {
"type": "company",
"id": 1,
"title": "ООО Пример",
"url": "/companies/1"
}
}
],
"projects": [],
"tasks": [],
"users": []
}
}Производительность
Миграция 0084_global_search_indexes.sql включает pg_trgm и добавляет GIN trigram-индексы на поля, участвующие в ILIKE '%query%'. Это важно для интерактивной страницы поиска: фронтенд может безопасно debounce-запросы, а backend не должен сканировать крупные таблицы полностью.