Corp/backend/search/views.py

101 lines
3.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from typing import Dict, Any, List
from django.contrib.auth.decorators import login_required
from django.db.models import Q, QuerySet
from django.shortcuts import render
from django.utils.html import escape
# Модели
from feed.models import Post # подставьте актуальный путь
from employees.models import Employee
from requests_app.models import Request
# ====== ВСПОМОГАТЕЛЬНО: доступ к заявлениям ======
def _is_hr(user) -> bool:
# считаем HR по группе/правам как вы уже настроили
return user.is_active and (
user.groups.filter(name="HR").exists()
or user.has_perm("requests_app.can_view_all_requests")
or user.has_perm("requests_app.can_process_requests")
)
def _is_head(user) -> bool:
# есть related_name=headed_departments в Employee
return user.headed_departments.exists()
def _allowed_requests_qs(user) -> QuerySet[Request]:
base = Request.objects.select_related("employee", "department", "approver")
if _is_hr(user):
return base
if _is_head(user):
return base.filter(
employee__departments_links__department__head=user,
employee__departments_links__is_active=True,
).distinct()
return base.filter(employee=user)
# ====== ПОИСК ======
@login_required
def search_view(request):
q = (request.GET.get("q") or "").strip()
query = q[:100] # ограничим длину для безопасности
results: Dict[str, List[Any]] = {"posts": [], "employees": [], "requests": []}
counts: Dict[str, int] = {"posts": 0, "employees": 0, "requests": 0}
if query:
# --- Посты (новости)
posts_qs = Post.objects.all()
posts_qs = (
posts_qs.filter(Q(title__icontains=query) | Q(body__icontains=query))
.only("id", "title")
.order_by("-id")
)
counts["posts"] = posts_qs.count()
results["posts"] = list(posts_qs[:10])
# --- Сотрудники
emp_qs = Employee.objects.all()
emp_qs = (
emp_qs.filter(
Q(first_name__icontains=query)
| Q(last_name__icontains=query)
| Q(patronymic__icontains=query)
| Q(email__icontains=query)
| Q(phone_number__icontains=query)
)
.only("id", "first_name", "last_name", "patronymic", "email")
.order_by("last_name", "first_name")
)
counts["employees"] = emp_qs.count()
results["employees"] = list(emp_qs[:10])
# --- Заявления (с учётом прав)
req_qs = _allowed_requests_qs(request.user)
req_qs = (
req_qs.filter(
Q(title__icontains=query)
| Q(comment__icontains=query)
| Q(employee__first_name__icontains=query)
| Q(employee__last_name__icontains=query)
)
.only("id", "title", "status", "employee", "department", "created_at")
.order_by("-created_at")
)
counts["requests"] = req_qs.count()
results["requests"] = list(req_qs[:10])
# Пустой запрос — просто страница с формой/подсказкой
ctx = {
"query": query,
"results": results,
"counts": counts,
}
return render(request, "search/results.html", ctx)