Allow procurement requests for any department
This commit is contained in:
parent
2b8e02e1f7
commit
e6eee5ddf8
@ -96,10 +96,8 @@ class CanManageProcurementRequest(permissions.BasePermission):
|
||||
- Просмотр (SAFE_METHODS): любой аутентифицированный (фильтрация в queryset)
|
||||
|
||||
- Создание:
|
||||
- admin/staff/superuser → любой отдел
|
||||
- модельные права (add_procurementrequest) → любой отдел
|
||||
- сотрудник отдела → только свой отдел
|
||||
- без отдела → запрещено
|
||||
- любой аутентифицированный пользователь → любой отдел
|
||||
- requestor всегда задаётся текущим пользователем в сериализаторе
|
||||
|
||||
- Изменение:
|
||||
- admin/staff/superuser → любая заявка в DRAFT
|
||||
@ -131,24 +129,6 @@ class CanManageProcurementRequest(permissions.BasePermission):
|
||||
perm = perm_map.get(action)
|
||||
return perm and user.has_perm(perm)
|
||||
|
||||
def _get_user_departments(self, user) -> list[int]:
|
||||
"""Возвращает список ID отделов, где пользователь состоит."""
|
||||
return list(
|
||||
EmployeeDepartment.objects.filter(
|
||||
employee_id=user.id, is_active=True
|
||||
).values_list("department_id", flat=True)
|
||||
)
|
||||
|
||||
def _get_dept_id_from_request(self, request) -> int | None:
|
||||
"""Извлекает ID отдела из данных запроса."""
|
||||
dept_id = request.data.get("department")
|
||||
if dept_id is not None:
|
||||
try:
|
||||
return int(dept_id)
|
||||
except (ValueError, TypeError):
|
||||
pass
|
||||
return None
|
||||
|
||||
def _is_dept_head(self, user, dept_id: int) -> bool:
|
||||
"""Проверяет, является ли пользователь начальником отдела."""
|
||||
return Department.objects.filter(id=dept_id, head_id=user.id).exists()
|
||||
@ -180,22 +160,9 @@ class CanManageProcurementRequest(permissions.BasePermission):
|
||||
if self._has_model_perm(user, action):
|
||||
return True
|
||||
|
||||
# Для создания проверяем отдел
|
||||
# Любой аутентифицированный пользователь может создать заявку
|
||||
# от имени любого отдела. Валидность department проверит сериализатор.
|
||||
if action == "create":
|
||||
dept_id = self._get_dept_id_from_request(request)
|
||||
if dept_id is None:
|
||||
return False
|
||||
|
||||
# Пользователь должен состоять в указанном отделе
|
||||
user_depts = self._get_user_departments(user)
|
||||
if not user_depts:
|
||||
# Пользователь без отдела не может создавать
|
||||
return False
|
||||
|
||||
if dept_id not in user_depts:
|
||||
# Нельзя создавать заявку в чужом отделе
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
# Для update/delete проверка на уровне объекта
|
||||
|
||||
@ -316,10 +316,10 @@ class TestProcurementRequestCreate:
|
||||
assert request.items.count() == 2
|
||||
assert request.total_cost == Decimal('305000.00') # 5*25k + 10*18k
|
||||
|
||||
def test_create_request_wrong_department(
|
||||
def test_create_request_for_other_department(
|
||||
self, api_client, user, db
|
||||
):
|
||||
"""Нельзя создать заявку для чужого отдела."""
|
||||
"""Можно создать заявку для любого отдела."""
|
||||
other_dept = Department.objects.create(
|
||||
name="HR отдел", description="Другой отдел"
|
||||
)
|
||||
@ -336,11 +336,9 @@ class TestProcurementRequestCreate:
|
||||
}
|
||||
|
||||
response = api_client.post(url, data, format='json')
|
||||
# Должна быть ошибка валидации
|
||||
assert response.status_code in [
|
||||
status.HTTP_400_BAD_REQUEST,
|
||||
status.HTTP_403_FORBIDDEN
|
||||
]
|
||||
assert response.status_code == status.HTTP_201_CREATED
|
||||
assert response.data['department'] == other_dept.id
|
||||
assert response.data['requestor'] == user.id
|
||||
|
||||
def test_create_processing_department_request_skips_approvals(
|
||||
self, api_client, user, department, db
|
||||
|
||||
@ -3,10 +3,8 @@
|
||||
|
||||
Сценарии:
|
||||
1. Создание заявки:
|
||||
- admin/staff/superuser → любой отдел
|
||||
- модельные права (add_procurementrequest) → любой отдел
|
||||
- сотрудник отдела → только свой отдел
|
||||
- сотрудник без отдела → запрещено
|
||||
- любой аутентифицированный пользователь → любой отдел
|
||||
- requestor всегда текущий пользователь
|
||||
|
||||
2. Изменение заявки:
|
||||
- admin/staff/superuser → любая заявка в DRAFT
|
||||
@ -292,14 +290,16 @@ class TestProcurementRequestCreateAccess:
|
||||
assert response.status_code == status.HTTP_201_CREATED
|
||||
assert response.data['department'] == dept_it.id
|
||||
|
||||
def test_dept_member_cannot_create_in_other_dept(
|
||||
def test_dept_member_can_create_in_other_dept(
|
||||
self, api_client, dept_member, dept_hr
|
||||
):
|
||||
"""Сотрудник отдела НЕ может создать заявку в ЧУЖОМ отделе."""
|
||||
"""Сотрудник отдела может создать заявку в чужом отделе."""
|
||||
api_client.force_authenticate(user=dept_member)
|
||||
data = valid_request_data(dept_hr)
|
||||
response = api_client.post(request_list_url(), data, format="json")
|
||||
assert response.status_code == status.HTTP_403_FORBIDDEN
|
||||
assert response.status_code == status.HTTP_201_CREATED
|
||||
assert response.data['department'] == dept_hr.id
|
||||
assert response.data['requestor'] == dept_member.id
|
||||
|
||||
def test_dept_head_can_create_in_own_dept(
|
||||
self, api_client, dept_head, dept_it
|
||||
@ -310,23 +310,27 @@ class TestProcurementRequestCreateAccess:
|
||||
response = api_client.post(request_list_url(), data, format="json")
|
||||
assert response.status_code == status.HTTP_201_CREATED
|
||||
|
||||
def test_dept_head_cannot_create_in_other_dept(
|
||||
def test_dept_head_can_create_in_other_dept(
|
||||
self, api_client, dept_head, dept_hr
|
||||
):
|
||||
"""Начальник отдела НЕ может создать заявку в чужом отделе."""
|
||||
"""Начальник отдела может создать заявку в чужом отделе."""
|
||||
api_client.force_authenticate(user=dept_head)
|
||||
data = valid_request_data(dept_hr)
|
||||
response = api_client.post(request_list_url(), data, format="json")
|
||||
assert response.status_code == status.HTTP_403_FORBIDDEN
|
||||
assert response.status_code == status.HTTP_201_CREATED
|
||||
assert response.data['department'] == dept_hr.id
|
||||
assert response.data['requestor'] == dept_head.id
|
||||
|
||||
def test_user_without_dept_cannot_create(
|
||||
def test_user_without_dept_can_create(
|
||||
self, api_client, user_without_dept, dept_it
|
||||
):
|
||||
"""Пользователь без отдела НЕ может создавать заявки."""
|
||||
"""Пользователь без отдела может создать заявку в выбранном отделе."""
|
||||
api_client.force_authenticate(user=user_without_dept)
|
||||
data = valid_request_data(dept_it)
|
||||
response = api_client.post(request_list_url(), data, format="json")
|
||||
assert response.status_code == status.HTTP_403_FORBIDDEN
|
||||
assert response.status_code == status.HTTP_201_CREATED
|
||||
assert response.data['department'] == dept_it.id
|
||||
assert response.data['requestor'] == user_without_dept.id
|
||||
|
||||
def test_requestor_is_set_to_current_user(
|
||||
self, api_client, dept_member, dept_it
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user