Skip to content

Commit 0bffd57

Browse files
feat: add endpoint to retrieve team details by ID (#150)
Co-authored-by: Amit Prakash <[email protected]>
1 parent 926d641 commit 0bffd57

File tree

3 files changed

+77
-1
lines changed

3 files changed

+77
-1
lines changed

todo/services/team_service.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,3 +138,32 @@ def get_user_teams(cls, user_id: str) -> GetUserTeamsResponse:
138138

139139
except Exception as e:
140140
raise ValueError(f"Failed to get user teams: {str(e)}")
141+
142+
@classmethod
143+
def get_team_by_id(cls, team_id: str) -> TeamDTO:
144+
"""
145+
Get a team by its ID.
146+
147+
Args:
148+
team_id: ID of the team to retrieve
149+
150+
Returns:
151+
TeamDTO with the team details
152+
153+
Raises:
154+
ValueError: If the team is not found
155+
"""
156+
team = TeamRepository.get_by_id(team_id)
157+
if not team:
158+
raise ValueError(f"Team with id {team_id} not found")
159+
return TeamDTO(
160+
id=str(team.id),
161+
name=team.name,
162+
description=team.description,
163+
poc_id=str(team.poc_id) if team.poc_id else None,
164+
invite_code=team.invite_code,
165+
created_by=str(team.created_by),
166+
updated_by=str(team.updated_by),
167+
created_at=team.created_at,
168+
updated_at=team.updated_at,
169+
)

todo/urls.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,12 @@
55
from todo.views.auth import GoogleLoginView, GoogleCallbackView, LogoutView
66
from todo.views.role import RoleListView, RoleDetailView
77
from todo.views.label import LabelListView
8-
from todo.views.team import TeamListView
8+
from todo.views.team import TeamListView, TeamDetailView
99
from todo.views.watchlist import WatchlistListView, WatchlistDetailView
1010

1111
urlpatterns = [
1212
path("teams", TeamListView.as_view(), name="teams"),
13+
path("teams/<str:team_id>", TeamDetailView.as_view(), name="team_detail"),
1314
path("tasks", TaskListView.as_view(), name="tasks"),
1415
path("tasks/<str:task_id>", TaskDetailView.as_view(), name="task_detail"),
1516
path("roles", RoleListView.as_view(), name="roles"),

todo/views/team.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111
from todo.dto.responses.get_user_teams_response import GetUserTeamsResponse
1212
from todo.dto.responses.error_response import ApiErrorResponse, ApiErrorDetail, ApiErrorSource
1313
from todo.constants.messages import ApiErrors
14+
from drf_spectacular.utils import extend_schema, OpenApiParameter, OpenApiResponse
15+
from drf_spectacular.types import OpenApiTypes
16+
from todo.dto.team_dto import TeamDTO
1417

1518

1619
class TeamListView(APIView):
@@ -90,3 +93,46 @@ def _handle_validation_errors(self, errors):
9093
error_response = ApiErrorResponse(statusCode=400, message=ApiErrors.VALIDATION_ERROR, errors=formatted_errors)
9194

9295
return Response(data=error_response.model_dump(mode="json"), status=status.HTTP_400_BAD_REQUEST)
96+
97+
98+
class TeamDetailView(APIView):
99+
@extend_schema(
100+
operation_id="get_team_by_id",
101+
summary="Get team by ID",
102+
description="Retrieve a single team by its unique identifier",
103+
tags=["teams"],
104+
parameters=[
105+
OpenApiParameter(
106+
name="team_id",
107+
type=OpenApiTypes.STR,
108+
location=OpenApiParameter.PATH,
109+
description="Unique identifier of the team",
110+
),
111+
],
112+
responses={
113+
200: OpenApiResponse(description="Team retrieved successfully"),
114+
404: OpenApiResponse(description="Team not found"),
115+
500: OpenApiResponse(description="Internal server error"),
116+
},
117+
)
118+
def get(self, request: Request, team_id: str):
119+
"""
120+
Retrieve a single team by ID.
121+
"""
122+
try:
123+
team_dto: TeamDTO = TeamService.get_team_by_id(team_id)
124+
return Response(data=team_dto.model_dump(mode="json"), status=status.HTTP_200_OK)
125+
except ValueError as e:
126+
fallback_response = ApiErrorResponse(
127+
statusCode=404,
128+
message=str(e),
129+
errors=[{"detail": str(e)}],
130+
)
131+
return Response(data=fallback_response.model_dump(mode="json"), status=404)
132+
except Exception as e:
133+
fallback_response = ApiErrorResponse(
134+
statusCode=500,
135+
message=ApiErrors.UNEXPECTED_ERROR_OCCURRED,
136+
errors=[{"detail": str(e) if settings.DEBUG else ApiErrors.INTERNAL_SERVER_ERROR}],
137+
)
138+
return Response(data=fallback_response.model_dump(mode="json"), status=500)

0 commit comments

Comments
 (0)