Coverage for apps/kwai-api/src/kwai_api/v1/trainings/endpoints.py: 86%
83 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 endpoints for trainings."""
3from datetime import datetime
5from fastapi import APIRouter, Depends, HTTPException, Query, status
6from kwai_bc_identity.users.user import UserEntity
7from kwai_bc_training.coaches.coach_db_repository import CoachDbRepository
8from kwai_bc_training.coaches.coach_repository import CoachNotFoundException
9from kwai_bc_training.create_training import CreateTraining, CreateTrainingCommand
10from kwai_bc_training.delete_training import DeleteTraining, DeleteTrainingCommand
11from kwai_bc_training.get_training import GetTraining, GetTrainingCommand
12from kwai_bc_training.get_trainings import GetTrainings, GetTrainingsCommand
13from kwai_bc_training.teams.team_db_repository import TeamDbRepository
14from kwai_bc_training.training_command import Coach
15from kwai_bc_training.trainings.training_db_repository import TrainingDbRepository
16from kwai_bc_training.trainings.training_repository import TrainingNotFoundException
17from kwai_bc_training.trainings.training_schedule_db_repository import (
18 TrainingScheduleDbRepository,
19)
20from kwai_bc_training.trainings.training_schedule_repository import (
21 TrainingScheduleNotFoundException,
22)
23from kwai_bc_training.update_training import UpdateTraining, UpdateTrainingCommand
24from kwai_core.db.uow import UnitOfWork
25from kwai_core.domain.use_case import TextCommand
26from kwai_core.domain.value_objects.owner import Owner
27from kwai_core.json_api import PaginationModel
28from pydantic import BaseModel, Field
30from kwai_api.dependencies import create_database, get_current_user
31from kwai_api.v1.trainings.coaches.schemas import TrainingCoachResource
32from kwai_api.v1.trainings.presenters import (
33 JsonApiTrainingPresenter,
34 JsonApiTrainingsDocumentPresenter,
35)
36from kwai_api.v1.trainings.schemas import TrainingDocument, TrainingsDocument
39router = APIRouter()
42class TrainingsFilterModel(BaseModel):
43 """Define the JSON:API filter for trainings."""
45 year: int | None = Field(Query(default=None, alias="filter[year]"))
46 month: int | None = Field(Query(default=None, alias="filter[month]"))
47 start: datetime | None = Field(Query(default=None, alias="filter[start]"))
48 end: datetime | None = Field(Query(default=None, alias="filter[end]"))
49 active: bool = Field(Query(default=True, alias="filter[active]"))
50 coach: int | None = Field(Query(default=None, alias="filter[coach]"))
51 schedule: int | None = Field(Query(default=None, alias="filter[schedule]"))
54@router.get(
55 "/trainings",
56 responses={
57 status.HTTP_404_NOT_FOUND: {
58 "description": "Coach or Training schedule was not found."
59 }
60 },
61)
62async def get_trainings(
63 pagination: PaginationModel = Depends(PaginationModel),
64 trainings_filter: TrainingsFilterModel = Depends(TrainingsFilterModel),
65 db=Depends(create_database),
66) -> TrainingsDocument:
67 """Get all trainings."""
68 command = GetTrainingsCommand(
69 offset=pagination.offset or 0,
70 limit=pagination.limit,
71 year=trainings_filter.year,
72 month=trainings_filter.month,
73 start=trainings_filter.start,
74 end=trainings_filter.end,
75 active=trainings_filter.active,
76 coach=trainings_filter.coach,
77 schedule=trainings_filter.schedule,
78 )
79 presenter = JsonApiTrainingsDocumentPresenter()
80 try:
81 await GetTrainings(
82 TrainingDbRepository(db),
83 CoachDbRepository(db),
84 TrainingScheduleDbRepository(db),
85 presenter,
86 ).execute(command)
87 except TrainingScheduleNotFoundException as ex:
88 raise HTTPException(
89 status_code=status.HTTP_404_NOT_FOUND, detail=str(ex)
90 ) from ex
91 except CoachNotFoundException as ex:
92 raise HTTPException(
93 status_code=status.HTTP_404_NOT_FOUND, detail=str(ex)
94 ) from ex
96 return presenter.get_document()
99@router.get(
100 "/trainings/{training_id}",
101 responses={status.HTTP_404_NOT_FOUND: {"description": "Training was not found."}},
102)
103async def get_training(
104 training_id: int,
105 db=Depends(create_database),
106) -> TrainingDocument:
107 """Get the training with the given id."""
108 command = GetTrainingCommand(id=training_id)
109 presenter = JsonApiTrainingPresenter()
110 try:
111 await GetTraining(TrainingDbRepository(db), presenter).execute(command)
112 except TrainingNotFoundException as ex:
113 raise HTTPException(
114 status_code=status.HTTP_404_NOT_FOUND, detail=str(ex)
115 ) from ex
117 return presenter.get_document()
120@router.post(
121 "/trainings",
122 status_code=status.HTTP_201_CREATED,
123)
124async def create_training(
125 resource: TrainingDocument,
126 db=Depends(create_database),
127 user: UserEntity = Depends(get_current_user),
128) -> TrainingDocument:
129 """Create a new training."""
130 coaches = [
131 coach for coach in resource.included if isinstance(coach, TrainingCoachResource)
132 ]
133 command = CreateTrainingCommand(
134 start_date=resource.data.attributes.event.start_date,
135 end_date=resource.data.attributes.event.end_date,
136 active=resource.data.attributes.event.active,
137 cancelled=resource.data.attributes.event.cancelled,
138 texts=[
139 TextCommand(
140 locale=text.locale,
141 format=text.format,
142 title=text.title,
143 summary=text.original_summary or "",
144 content=text.original_content or "",
145 )
146 for text in resource.data.attributes.texts
147 ],
148 coaches=[
149 Coach(
150 id=int(coach.id),
151 head=coach.attributes.head,
152 present=coach.attributes.present,
153 payed=coach.attributes.payed,
154 )
155 for coach in coaches
156 ],
157 teams=[int(team.id) for team in resource.data.relationships.teams.data],
158 schedule=None
159 if resource.data.relationships.schedule.data is None
160 or resource.data.relationships.schedule.data.id is None
161 else int(resource.data.relationships.schedule.data.id),
162 location=resource.data.attributes.event.location,
163 remark=resource.data.attributes.remark,
164 )
166 presenter = JsonApiTrainingPresenter()
167 async with UnitOfWork(db):
168 try:
169 await CreateTraining(
170 TrainingDbRepository(db),
171 TrainingScheduleDbRepository(db),
172 CoachDbRepository(db),
173 TeamDbRepository(db),
174 Owner(id=user.id, uuid=user.uuid, name=user.name),
175 presenter,
176 ).execute(command)
177 except ValueError as ve:
178 raise HTTPException(
179 status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail=str(ve)
180 ) from ve
182 return presenter.get_document()
185@router.patch(
186 "/trainings/{training_id}",
187 responses={status.HTTP_404_NOT_FOUND: {"description": "Training was not found."}},
188)
189async def update_training(
190 training_id: int,
191 resource: TrainingDocument,
192 db=Depends(create_database),
193 user: UserEntity = Depends(get_current_user),
194) -> TrainingDocument:
195 """Update a training."""
196 coaches = [
197 coach for coach in resource.included if isinstance(coach, TrainingCoachResource)
198 ]
199 command = UpdateTrainingCommand(
200 id=training_id,
201 start_date=resource.data.attributes.event.start_date,
202 end_date=resource.data.attributes.event.end_date,
203 active=resource.data.attributes.event.active,
204 cancelled=resource.data.attributes.event.cancelled,
205 texts=[
206 TextCommand(
207 locale=text.locale,
208 format=text.format,
209 title=text.title,
210 summary=text.original_summary or "",
211 content=text.original_content or "",
212 )
213 for text in resource.data.attributes.texts
214 ],
215 coaches=[
216 Coach(
217 id=int(coach.id),
218 head=coach.attributes.head,
219 present=coach.attributes.present,
220 payed=coach.attributes.payed,
221 )
222 for coach in coaches
223 ],
224 teams=[int(team.id) for team in resource.data.relationships.teams.data],
225 schedule=None
226 if resource.data.relationships.schedule.data is None
227 else int(resource.data.relationships.schedule.data.id),
228 location=resource.data.attributes.event.location,
229 remark=resource.data.attributes.remark,
230 )
232 presenter = JsonApiTrainingPresenter()
233 async with UnitOfWork(db):
234 try:
235 await UpdateTraining(
236 TrainingDbRepository(db),
237 TrainingScheduleDbRepository(db),
238 CoachDbRepository(db),
239 TeamDbRepository(db),
240 Owner(id=user.id, uuid=user.uuid, name=user.name),
241 presenter,
242 ).execute(command)
243 except TrainingNotFoundException as ex:
244 raise HTTPException(
245 status_code=status.HTTP_404_NOT_FOUND, detail=str(ex)
246 ) from ex
247 except ValueError as ve:
248 raise HTTPException(
249 status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail=str(ve)
250 ) from ve
252 return presenter.get_document()
255@router.delete(
256 "/trainings/{training_id}",
257 responses={status.HTTP_404_NOT_FOUND: {"description": "Training was not found."}},
258)
259async def delete_training(
260 training_id: int,
261 db=Depends(create_database),
262 user: UserEntity = Depends(get_current_user),
263) -> None:
264 """Delete a training schedule."""
265 command = DeleteTrainingCommand(id=training_id)
266 async with UnitOfWork(db):
267 await DeleteTraining(TrainingDbRepository(db)).execute(command)