Skip to content

Commit f089fdc

Browse files
committed
Добавлена ручка для получения проектов пользователя, где он является лидером
1 parent a00a7e7 commit f089fdc

5 files changed

Lines changed: 113 additions & 3 deletions

File tree

invites/tests.py

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
1+
from datetime import timedelta
2+
13
from django.test import TestCase
4+
from django.utils import timezone
25
from rest_framework.test import APIRequestFactory, force_authenticate
36

4-
from projects.models import Project
7+
from partner_programs.models import PartnerProgram, PartnerProgramProject
8+
from projects.models import Collaborator, Project
59
from tests.constants import USER_CREATE_DATA
610

711
from users.views import UserList
@@ -112,6 +116,51 @@ def test_invites_creation_with_empty_data(self):
112116

113117
self.assertEqual(response.status_code, 400)
114118

119+
def test_invites_creation_for_existing_collaborator(self):
120+
sender = self._user_create("sender@example.com")
121+
recipient = self._user_create("recipient@example.com")
122+
project = self._project_create(sender)
123+
Collaborator.objects.create(user=recipient, project=project, role="Developer")
124+
125+
create_user = self.invite_create_data.copy()
126+
create_user["user"] = recipient.id
127+
create_user["project"] = project.id
128+
request = self.factory.post("invites/", create_user, format="json")
129+
force_authenticate(request, user=sender)
130+
131+
response = self.invite_list_view(request)
132+
133+
self.assertEqual(response.status_code, 400)
134+
self.assertIn("user", response.data)
135+
136+
def test_invites_creation_for_non_program_member(self):
137+
sender = self._user_create("sender@example.com")
138+
recipient = self._user_create("recipient@example.com")
139+
project = self._project_create(sender)
140+
now = timezone.now()
141+
program = PartnerProgram.objects.create(
142+
name="Test program",
143+
tag="test",
144+
city="Moscow",
145+
datetime_registration_ends=now + timedelta(days=1),
146+
datetime_started=now,
147+
datetime_finished=now + timedelta(days=30),
148+
)
149+
PartnerProgramProject.objects.create(
150+
partner_program=program, project=project
151+
)
152+
153+
create_user = self.invite_create_data.copy()
154+
create_user["user"] = recipient.id
155+
create_user["project"] = project.id
156+
request = self.factory.post("invites/", create_user, format="json")
157+
force_authenticate(request, user=sender)
158+
159+
response = self.invite_list_view(request)
160+
161+
self.assertEqual(response.status_code, 400)
162+
self.assertIn("user", response.data)
163+
115164
def test_accept_invite_by_intended_user(self):
116165
sender = self._user_create("sender@example.com")
117166
recipient = self._user_create("recipient@example.com")

projects/admin.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,14 +54,15 @@ class ProjectAdmin(admin.ModelAdmin):
5454
"id",
5555
"name",
5656
"draft",
57+
"is_public",
5758
"is_company",
5859
"trl",
5960
"target_audience",
6061
"implementation_deadline",
6162
)
6263
list_display_links = ("id", "name")
6364
search_fields = ("name",)
64-
list_filter = ("draft", "is_company", "trl")
65+
list_filter = ("draft", "is_public", "is_company", "trl")
6566

6667
fieldsets = (
6768
(
@@ -74,6 +75,7 @@ class ProjectAdmin(admin.ModelAdmin):
7475
"industry",
7576
"region",
7677
"draft",
78+
"is_public",
7779
"is_company",
7880
)
7981
},

users/tests.py

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,17 @@
22
from rest_framework.test import APIRequestFactory, force_authenticate
33
from tests.constants import USER_CREATE_DATA
44

5+
from projects.models import Collaborator, Project
56
from users.models import CustomUser
6-
from users.views import UserList, UserDetail
7+
from users.views import UserLeaderProjectsList, UserList, UserDetail
78

89

910
class UserTestCase(TestCase):
1011
def setUp(self):
1112
self.factory = APIRequestFactory()
1213
self.user_list_view = UserList.as_view()
1314
self.user_detail_view = UserDetail.as_view()
15+
self.user_leader_projects_view = UserLeaderProjectsList.as_view()
1416

1517
def test_user_creation(self):
1618
request = self.factory.post("auth/users/", USER_CREATE_DATA)
@@ -58,3 +60,36 @@ def test_user_update(self):
5860
response = self.user_detail_view(request, pk=user.pk)
5961
self.assertEqual(response.status_code, 200)
6062
self.assertEqual(response.data["first_name"], "Сергей")
63+
64+
def test_user_leader_projects_list(self):
65+
leader = self._user_create("leader@example.com")
66+
collaborator = self._user_create("collaborator@example.com")
67+
68+
leader_project = Project.objects.create(name="Leader project", leader=leader)
69+
second_leader_project = Project.objects.create(
70+
name="Leader project 2", leader=leader, draft=False
71+
)
72+
other_project = Project.objects.create(name="Other project", leader=collaborator)
73+
Collaborator.objects.create(user=leader, project=other_project, role="Member")
74+
75+
request = self.factory.get("users/projects/leader/")
76+
force_authenticate(request, user=leader)
77+
response = self.user_leader_projects_view(request)
78+
79+
self.assertEqual(response.status_code, 200)
80+
self.assertEqual(response.data["count"], 2)
81+
returned_ids = {item["id"] for item in response.data["results"]}
82+
self.assertSetEqual(
83+
returned_ids, {leader_project.id, second_leader_project.id}
84+
)
85+
86+
def _user_create(self, email):
87+
tmp_create_data = USER_CREATE_DATA.copy()
88+
tmp_create_data["email"] = email
89+
request = self.factory.post("auth/users/", tmp_create_data)
90+
response = self.user_list_view(request)
91+
user_id = response.data["id"]
92+
user = CustomUser.objects.get(id=user_id)
93+
user.is_active = True
94+
user.save()
95+
return user

users/urls.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
SpecialistsList,
1010
UserAdditionalRolesView,
1111
UserDetail,
12+
UserLeaderProjectsList,
1213
UserProjectsList,
1314
UserList,
1415
UserTypesView,
@@ -41,6 +42,7 @@
4142
path("users/", UserList.as_view()),
4243
path('public-users/', PublicUserListView.as_view(), name='public-users'),
4344
path("users/projects/", UserProjectsList.as_view()),
45+
path("users/projects/leader/", UserLeaderProjectsList.as_view()),
4446
path("users/liked/", LikedProjectList.as_view()),
4547
path("users/roles/", UserAdditionalRolesView.as_view()),
4648
path("users/types/", UserTypesView.as_view()),

users/views.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,28 @@ def get(self, request):
426426
)
427427

428428

429+
class UserLeaderProjectsList(GenericAPIView):
430+
permission_classes = [IsAuthenticated]
431+
pagination_class = ProjectsPagination
432+
serializer_class = UserProjectListSerializer
433+
434+
def get(self, request):
435+
queryset = (
436+
Project.objects.filter(leader_id=self.request.user.id)
437+
.prefetch_related("program_links__partner_program")
438+
.distinct()
439+
)
440+
441+
page = self.paginate_queryset(queryset)
442+
if page is not None:
443+
serializer = self.get_serializer(page, many=True)
444+
return self.get_paginated_response(serializer.data)
445+
return Response(
446+
{"detail": "Unable to return paginated list"},
447+
status=status.HTTP_400_BAD_REQUEST,
448+
)
449+
450+
429451
class LogoutView(APIView):
430452
permission_classes = [IsAuthenticated]
431453

0 commit comments

Comments
 (0)