Coverage for apps/kwai-api/src/kwai_api/v1/club/coaches/endpoints.py: 87%
62 statements
« prev ^ index » next coverage.py v7.11.0, created at 2024-01-01 00:00 +0000
« prev ^ index » next coverage.py v7.11.0, created at 2024-01-01 00:00 +0000
1"""Module for defining endpoints for coaches of the club API."""
3from typing import Annotated
5from fastapi import APIRouter, Depends, HTTPException, Query, status
6from kwai_bc_club.create_coach import CreateCoach, CreateCoachCommand
7from kwai_bc_club.get_coach import GetCoach, GetCoachCommand
8from kwai_bc_club.get_coaches import GetCoaches, GetCoachesCommand
9from kwai_bc_club.repositories.coach_db_repository import CoachDbRepository
10from kwai_bc_club.repositories.coach_repository import (
11 CoachAlreadyExistException,
12 CoachNotFoundException,
13)
14from kwai_bc_club.repositories.member_db_repository import MemberDbRepository
15from kwai_bc_club.repositories.member_repository import MemberNotFoundException
16from kwai_bc_club.update_coach import UpdateCoach, UpdateCoachCommand
17from kwai_bc_identity.users.user import UserEntity
18from kwai_core.db.database import Database
19from kwai_core.db.uow import UnitOfWork
20from kwai_core.json_api import PaginationModel
21from pydantic import BaseModel, Field
23from kwai_api.dependencies import create_database, get_current_user
24from kwai_api.v1.club.coaches.presenters import (
25 JsonApiCoachesPresenter,
26 JsonApiCoachPresenter,
27)
28from kwai_api.v1.club.coaches.schemas import CoachDocument, CoachesDocument
31router = APIRouter()
34class CoachesFilterModel(BaseModel):
35 """JSON:API filter for coaches."""
37 enabled: bool = Field(Query(default=True, alias="filter[enabled]"))
40@router.get("/coaches")
41async def get_coaches(
42 pagination: Annotated[PaginationModel, Depends(PaginationModel)],
43 coaches_filter: Annotated[CoachesFilterModel, Depends(CoachesFilterModel)],
44 db: Annotated[Database, Depends(create_database)],
45 user: Annotated[UserEntity | None, Depends(get_current_user)],
46) -> CoachesDocument:
47 """Get all coaches."""
48 presenter = JsonApiCoachesPresenter()
49 active = coaches_filter.enabled
51 command = GetCoachesCommand(
52 offset=pagination.offset, limit=pagination.limit, active=active
53 )
54 await GetCoaches(CoachDbRepository(db), presenter).execute(command)
56 return presenter.get_document()
59@router.get("/coaches/{coach_uuid}")
60async def get_coach(
61 coach_uuid: str,
62 db: Annotated[Database, Depends(create_database)],
63 user: Annotated[UserEntity | None, Depends(get_current_user)],
64) -> CoachDocument:
65 """Get a coach.
67 The unique id of the member is used to retrieve the coach.
68 """
69 presenter = JsonApiCoachPresenter()
70 command = GetCoachCommand(uuid=coach_uuid)
71 await GetCoach(CoachDbRepository(db), presenter).execute(command)
73 return presenter.get_document()
76@router.post(
77 "/coaches",
78 responses={
79 status.HTTP_201_CREATED: {"description": "Coach was created."},
80 status.HTTP_404_NOT_FOUND: {"description": "Member is not found."},
81 status.HTTP_409_CONFLICT: {"description": "Coach already exists."},
82 status.HTTP_422_UNPROCESSABLE_ENTITY: {"description": "Data is invalid."},
83 },
84 status_code=status.HTTP_201_CREATED,
85)
86async def create_coach(
87 db: Annotated[Database, Depends(create_database)],
88 user: Annotated[UserEntity, Depends(get_current_user)],
89 resource: CoachDocument,
90) -> CoachDocument:
91 """Create a new coach."""
92 if (
93 resource.data.relationships is None
94 or resource.data.relationships.member is None
95 or resource.data.relationships.member.data is None
96 or resource.data.relationships.member.data.id is None
97 ):
98 raise HTTPException(
99 status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
100 detail="Member relationship data is missing.",
101 )
103 command = CreateCoachCommand(
104 description=resource.data.attributes.description,
105 diploma=resource.data.attributes.diploma,
106 remark=resource.data.attributes.remark,
107 active=resource.data.attributes.active,
108 head=resource.data.attributes.head,
109 member_uuid=resource.data.relationships.member.data.id,
110 )
111 presenter = JsonApiCoachPresenter()
113 async with UnitOfWork(db):
114 try:
115 await CreateCoach(
116 CoachDbRepository(db), MemberDbRepository(db), presenter
117 ).execute(command)
118 except MemberNotFoundException as ex:
119 raise HTTPException(
120 status_code=status.HTTP_404_NOT_FOUND, detail=str(ex)
121 ) from ex
122 except CoachAlreadyExistException as ex:
123 raise HTTPException(
124 status_code=status.HTTP_409_CONFLICT, detail=str(ex)
125 ) from ex
126 except ValueError as ve:
127 raise HTTPException(
128 status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail=str(ve)
129 ) from ve
131 return presenter.get_document()
134@router.patch(
135 "/coaches/{coach_uuid}",
136 responses={status.HTTP_404_NOT_FOUND: {"description": "Coach was not found."}},
137)
138async def update_coach(
139 db: Annotated[Database, Depends(create_database)],
140 user: Annotated[UserEntity, Depends(get_current_user)],
141 coach_uuid: str,
142 resource: CoachDocument,
143) -> CoachDocument:
144 """Update a coach."""
145 command = UpdateCoachCommand(
146 uuid=coach_uuid,
147 diploma=resource.data.attributes.diploma,
148 description=resource.data.attributes.description,
149 active=resource.data.attributes.active,
150 remark=resource.data.attributes.remark,
151 head=resource.data.attributes.head,
152 )
153 presenter = JsonApiCoachPresenter()
154 async with UnitOfWork(db):
155 try:
156 await UpdateCoach(CoachDbRepository(db), presenter).execute(command)
157 except CoachNotFoundException as ex:
158 raise HTTPException(
159 status_code=status.HTTP_404_NOT_FOUND, detail=str(ex)
160 ) from ex
161 except ValueError as ve:
162 raise HTTPException(
163 status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail=str(ve)
164 ) from ve
166 return presenter.get_document()