diff --git a/backend/api/v1/procurement/permissions.py b/backend/api/v1/procurement/permissions.py index cbb5d000..6dc0291c 100644 --- a/backend/api/v1/procurement/permissions.py +++ b/backend/api/v1/procurement/permissions.py @@ -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 проверка на уровне объекта diff --git a/backend/tests/api/v1/procurement/test_procurement_requests.py b/backend/tests/api/v1/procurement/test_procurement_requests.py index 6154e497..d62fbce2 100644 --- a/backend/tests/api/v1/procurement/test_procurement_requests.py +++ b/backend/tests/api/v1/procurement/test_procurement_requests.py @@ -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 diff --git a/backend/tests/procurement/test_procurement_request_permissions.py b/backend/tests/procurement/test_procurement_request_permissions.py index 8010e459..c7b17ee7 100644 --- a/backend/tests/procurement/test_procurement_request_permissions.py +++ b/backend/tests/procurement/test_procurement_request_permissions.py @@ -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