From cc2cd4053255fa2b9b796a9dad5dd1e3bc2b03f5 Mon Sep 17 00:00:00 2001 From: TianyangZhang Date: Tue, 24 Mar 2026 17:37:54 +0800 Subject: [PATCH] fix: fix organizations view queryset and add API tests Co-Authored-By: Claude Sonnet 4.6 --- .../apps/organizations/serializers.py | 2 +- .../organizations/tests/test_organizations.py | 58 +++++++++++++++++++ offer_backend/apps/organizations/views.py | 6 +- 3 files changed, 62 insertions(+), 4 deletions(-) diff --git a/offer_backend/apps/organizations/serializers.py b/offer_backend/apps/organizations/serializers.py index c3b2e32..6a1a2f8 100644 --- a/offer_backend/apps/organizations/serializers.py +++ b/offer_backend/apps/organizations/serializers.py @@ -18,5 +18,5 @@ class OrganizationTreeSerializer(serializers.ModelSerializer): def get_children(self, obj): return OrganizationSerializer( - obj.children.filter(is_active=True), many=True + obj.children.filter(is_active=True), many=True, context=self.context ).data diff --git a/offer_backend/apps/organizations/tests/test_organizations.py b/offer_backend/apps/organizations/tests/test_organizations.py index 9d1e4b1..669b4fa 100644 --- a/offer_backend/apps/organizations/tests/test_organizations.py +++ b/offer_backend/apps/organizations/tests/test_organizations.py @@ -21,3 +21,61 @@ class TestOrganizationModel: Organization.objects.create(name='子A', email='a@example.com', parent=parent) Organization.objects.create(name='子B', email='b@example.com', parent=parent) assert parent.children.count() == 2 + + +@pytest.mark.django_db +class TestOrganizationPublicAPI: + def test_public_list_returns_top_level_orgs(self, client): + parent = Organization.objects.create(name='集团', email='g@example.com') + Organization.objects.create(name='子A', email='a@example.com', parent=parent) + response = client.get('/api/organizations/public/') + assert response.status_code == 200 + # 只返回顶级组织(集团),不直接返回子公司 + assert response.data['count'] == 1 + assert response.data['results'][0]['name'] == '集团' + + def test_inactive_org_not_in_public_list(self, client): + Organization.objects.create(name='停用集团', email='inactive@example.com', is_active=False) + Organization.objects.create(name='启用集团', email='active@example.com', is_active=True) + response = client.get('/api/organizations/public/') + assert response.status_code == 200 + assert response.data['count'] == 1 + + def test_manage_requires_auth(self, client): + response = client.get('/api/organizations/manage/') + assert response.status_code == 401 + + +@pytest.mark.django_db +class TestOrganizationManageAPI: + def test_superadmin_can_create_org(self, client): + from django.contrib.auth import get_user_model + from rest_framework_simplejwt.tokens import RefreshToken + User = get_user_model() + superadmin = User.objects.create_user( + username='super1', password='pass123', role='superadmin' + ) + refresh = RefreshToken.for_user(superadmin) + token = str(refresh.access_token) + response = client.post( + '/api/organizations/manage/', + {'name': '新集团', 'email': 'new@example.com'}, + content_type='application/json', + HTTP_AUTHORIZATION=f'Bearer {token}' + ) + assert response.status_code == 201 + + def test_seeker_cannot_access_manage(self, client): + from django.contrib.auth import get_user_model + from rest_framework_simplejwt.tokens import RefreshToken + User = get_user_model() + seeker = User.objects.create_user( + username='seeker1', password='pass123', role='seeker' + ) + refresh = RefreshToken.for_user(seeker) + token = str(refresh.access_token) + response = client.get( + '/api/organizations/manage/', + HTTP_AUTHORIZATION=f'Bearer {token}' + ) + assert response.status_code == 403 diff --git a/offer_backend/apps/organizations/views.py b/offer_backend/apps/organizations/views.py index 0293d3f..f1c6c7c 100644 --- a/offer_backend/apps/organizations/views.py +++ b/offer_backend/apps/organizations/views.py @@ -6,9 +6,9 @@ from apps.accounts.permissions import IsSuperAdmin class OrganizationPublicViewSet(viewsets.ReadOnlyModelViewSet): - """公开只读:门户展示用""" - queryset = Organization.objects.filter(is_active=True, parent__isnull=False) - serializer_class = OrganizationSerializer + """公开只读:门户展示用,返回顶级组织(集团)及其子公司树""" + queryset = Organization.objects.filter(is_active=True, parent__isnull=True) + serializer_class = OrganizationTreeSerializer permission_classes = [AllowAny]