feat(requests): Этап 3 - обновлена логика доступа с поддержкой получателей

- Обновлен get_queryset в RequestViewSet с учетом recipients и cc_users
- Добавлен параметр ?addressed_to_me=true для фильтрации заявок, адресованных текущему пользователю
- Получатели теперь видят заявки через recipients, cc_users или sent_to_all_department
- Департаментные права работают с новым полем departments (ManyToMany)
- Добавлена поддержка видимости по нескольким отделам
This commit is contained in:
admin i 2025-12-02 17:15:55 +03:00
parent 7cfd290d7d
commit ca056a15f8

View File

@ -113,12 +113,12 @@ class RequestViewSet(viewsets.ModelViewSet):
) )
def get_queryset(self) -> QuerySet[EmployeeRequest]: def get_queryset(self) -> QuerySet[EmployeeRequest]:
"""Список заявок с учётом прав: """Список заявок с учётом прав и получателей:
- staff/глобальные видят всё (или только свои при ?view=mine), - staff/глобальные видят всё (или только свои при ?view=mine),
- остальные: свои + отделы с правом 'view_request', руководимые отделы, - автор видит свои заявки,
отделы с правом 'can_process_requests'. - получатели (recipients/cc_users) видят адресованные им,
- Вариант B: добавляем заявки сотрудников этих отделов даже если - сотрудники отделов видят заявки отделов (с правами),
у заявок department_id = NULL. - при sent_to_all_department видят все из отделов.
""" """
qs = super().get_queryset() qs = super().get_queryset()
user = self.request.user user = self.request.user
@ -128,12 +128,49 @@ class RequestViewSet(viewsets.ModelViewSet):
want_mine = (params.get("view") == "mine") or ( want_mine = (params.get("view") == "mine") or (
mine_raw in {"1", "true", "yes", "on"} mine_raw in {"1", "true", "yes", "on"}
) )
# Новый параметр для фильтрации "мне адресовано"
addressed_to_me = params.get("addressed_to_me") == "true"
if user.is_staff or self._can_view_all(user): if user.is_staff or self._can_view_all(user):
if want_mine: if want_mine:
qs = qs.filter(employee_id=user.id) qs = qs.filter(employee_id=user.id)
# Для staff: не возвращаем сразу, применяем фильтры ниже elif addressed_to_me:
# Заявки, где я получатель
my_dept_ids = EmployeeDepartment.objects.filter(
employee=user,
is_active=True
).values_list('department_id', flat=True)
scope = (
Q(recipients=user) |
Q(cc_users=user) |
Q(
sent_to_all_department=True,
departments__in=my_dept_ids
)
)
qs = qs.filter(scope).distinct()
else: else:
# Обычный пользователь
scope = Q(employee_id=user.id) # Свои заявки
# Заявки, где я получатель (основной или CC)
scope |= Q(recipients=user) | Q(cc_users=user)
# Заявки отделов с sent_to_all_department
my_dept_ids = EmployeeDepartment.objects.filter(
employee=user,
is_active=True
).values_list('department_id', flat=True)
if my_dept_ids:
scope |= Q(
sent_to_all_department=True,
departments__in=my_dept_ids
)
# Департаментные права (как было)
view_dept_ids = ( view_dept_ids = (
EmployeeDepartment.objects.filter( EmployeeDepartment.objects.filter(
employee_id=user.id, employee_id=user.id,
@ -152,30 +189,43 @@ class RequestViewSet(viewsets.ModelViewSet):
.values_list("department_id", flat=True) .values_list("department_id", flat=True)
.distinct() .distinct()
) )
head_dept_ids = Department.objects.filter(head_id=user.id).values_list( head_dept_ids = Department.objects.filter(
"id", flat=True head_id=user.id
).values_list("id", flat=True)
combined_ids = (
set(view_dept_ids) | set(proc_dept_ids) | set(head_dept_ids)
) )
combined_ids = set(view_dept_ids) | set(proc_dept_ids) | set(head_dept_ids)
# сотрудники этих отделов (активные) if combined_ids:
dept_emp_ids = ( # Заявки этих отделов (новое поле departments)
EmployeeDepartment.objects.filter( scope |= Q(departments__in=combined_ids)
department_id__in=list(combined_ids) if combined_ids else [],
is_active=True, # Заявки сотрудников этих отделов
dept_emp_ids = (
EmployeeDepartment.objects.filter(
department_id__in=list(combined_ids),
is_active=True,
)
.values_list("employee_id", flat=True)
.distinct()
) )
.values_list("employee_id", flat=True)
.distinct()
) if combined_ids else []
if want_mine:
qs = qs.filter(employee_id=user.id)
else:
scope = Q(employee_id=user.id)
if combined_ids:
scope |= Q(department_id__in=list(combined_ids))
if dept_emp_ids: if dept_emp_ids:
scope |= Q(employee_id__in=list(dept_emp_ids)) scope |= Q(employee_id__in=list(dept_emp_ids))
qs = qs.filter(scope)
# Фильтр "только адресованные мне"
if addressed_to_me:
scope = (
Q(recipients=user) | Q(cc_users=user) |
Q(
sent_to_all_department=True,
departments__in=my_dept_ids
)
)
elif want_mine:
scope = Q(employee_id=user.id)
qs = qs.filter(scope).distinct()
# Применяем фильтры type/status для всех пользователей # Применяем фильтры type/status для всех пользователей
t = (params.get("type") or "").strip() t = (params.get("type") or "").strip()