Coverage for apps/kwai-api/src/kwai_api/v1/club/coaches/endpoints.py: 83%
58 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_coaches import GetCoaches, GetCoachesCommand
8from kwai_bc_club.repositories.coach_db_repository import CoachDbRepository
9from kwai_bc_club.repositories.coach_repository import (
10 CoachAlreadyExistException,
11 CoachNotFoundException,
12)
13from kwai_bc_club.repositories.member_db_repository import MemberDbRepository
14from kwai_bc_club.repositories.member_repository import MemberNotFoundException
15from kwai_bc_club.update_coach import UpdateCoach, UpdateCoachCommand
16from kwai_bc_identity.users.user import UserEntity
17from kwai_core.db.database import Database
18from kwai_core.db.uow import UnitOfWork
19from kwai_core.json_api import PaginationModel
20from pydantic import BaseModel, Field
22from kwai_api.dependencies import create_database, get_current_user, get_optional_user
23from kwai_api.v1.club.coaches.presenters import (
24 JsonApiCoachesPresenter,
25 JsonApiCoachPresenter,
26 JsonApiPublicCoachesPresenter,
27)
28from kwai_api.v1.club.coaches.schemas import (
29 CoachDocument,
30 CoachesDocument,
31 PublicCoachesDocument,
32)
35router = APIRouter()
38class CoachesFilterModel(BaseModel):
39 """JSON:API filter for coaches."""
41 enabled: bool = Field(Query(default=True, alias="filter[enabled]"))
44@router.get("/coaches")
45async def get_coaches(
46 pagination: Annotated[PaginationModel, Depends(PaginationModel)],
47 coaches_filter: Annotated[CoachesFilterModel, Depends(CoachesFilterModel)],
48 db: Annotated[Database, Depends(create_database)],
49 user: Annotated[UserEntity | None, Depends(get_optional_user)],
50) -> PublicCoachesDocument | CoachesDocument:
51 """Get all coaches."""
52 if user is None:
53 presenter = JsonApiPublicCoachesPresenter()
54 active = True
55 else:
56 presenter = JsonApiCoachesPresenter()
57 active = coaches_filter.enabled
59 command = GetCoachesCommand(
60 offset=pagination.offset, limit=pagination.limit, active=active
61 )
62 await GetCoaches(CoachDbRepository(db), presenter).execute(command)
64 return presenter.get_document()
67@router.post(
68 "/coaches",
69 responses={
70 status.HTTP_201_CREATED: {"description": "Coach was created."},
71 status.HTTP_404_NOT_FOUND: {"description": "Member is not found."},
72 status.HTTP_409_CONFLICT: {"description": "Coach already exists."},
73 status.HTTP_422_UNPROCESSABLE_ENTITY: {"description": "Data is invalid."},
74 },
75 status_code=status.HTTP_201_CREATED,
76)
77async def create_coach(
78 db: Annotated[Database, Depends(create_database)],
79 user: Annotated[UserEntity, Depends(get_current_user)],
80 resource: CoachDocument,
81) -> CoachDocument:
82 """Create a new coach."""
83 if (
84 resource.data.relationships is None
85 or resource.data.relationships.member is None
86 or resource.data.relationships.member.data is None
87 or resource.data.relationships.member.data.id is None
88 ):
89 raise HTTPException(
90 status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
91 detail="Member relationship data is missing.",
92 )
94 command = CreateCoachCommand(
95 description=resource.data.attributes.description,
96 diploma=resource.data.attributes.diploma,
97 remark=resource.data.attributes.remark,
98 active=resource.data.attributes.active,
99 member_uuid=resource.data.relationships.member.data.id,
100 )
101 presenter = JsonApiCoachPresenter()
103 async with UnitOfWork(db):
104 try:
105 await CreateCoach(
106 CoachDbRepository(db), MemberDbRepository(db), presenter
107 ).execute(command)
108 except MemberNotFoundException as ex:
109 raise HTTPException(
110 status_code=status.HTTP_404_NOT_FOUND, detail=str(ex)
111 ) from ex
112 except CoachAlreadyExistException as ex:
113 raise HTTPException(
114 status_code=status.HTTP_409_CONFLICT, detail=str(ex)
115 ) from ex
116 except ValueError as ve:
117 raise HTTPException(
118 status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail=str(ve)
119 ) from ve
121 return presenter.get_document()
124@router.patch(
125 "/coaches/{coach_id}",
126 responses={status.HTTP_404_NOT_FOUND: {"description": "Coach was not found."}},
127)
128async def update_coach(
129 db: Annotated[Database, Depends(create_database)],
130 user: Annotated[UserEntity, Depends(get_current_user)],
131 coach_id: int,
132 resource: CoachDocument,
133) -> CoachDocument:
134 """Update a coach."""
135 command = UpdateCoachCommand(
136 id=coach_id,
137 diploma=resource.data.attributes.diploma,
138 description=resource.data.attributes.description,
139 active=resource.data.attributes.active,
140 remark=resource.data.attributes.remark,
141 )
142 presenter = JsonApiCoachPresenter()
143 async with UnitOfWork(db):
144 try:
145 await UpdateCoach(CoachDbRepository(db), presenter).execute(command)
146 except CoachNotFoundException as ex:
147 raise HTTPException(
148 status_code=status.HTTP_404_NOT_FOUND, detail=str(ex)
149 ) from ex
150 except ValueError as ve:
151 raise HTTPException(
152 status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail=str(ve)
153 ) from ve
155 return presenter.get_document()