Coverage for src/kwai/api/v1/trainings/endpoints/trainings.py: 89%
74 statements
« prev ^ index » next coverage.py v7.6.10, created at 2024-01-01 00:00 +0000
« prev ^ index » next coverage.py v7.6.10, 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 pydantic import BaseModel, Field
8from kwai.api.dependencies import create_database, get_current_user
9from kwai.api.v1.trainings.schemas.training import TrainingDocument
10from kwai.core.domain.use_case import TextCommand
11from kwai.core.domain.value_objects.owner import Owner
12from kwai.core.json_api import Meta, PaginationModel
13from kwai.modules.identity.users.user import UserEntity
14from kwai.modules.training.coaches.coach_db_repository import CoachDbRepository
15from kwai.modules.training.coaches.coach_repository import CoachNotFoundException
16from kwai.modules.training.create_training import (
17 CreateTraining,
18 CreateTrainingCommand,
19)
20from kwai.modules.training.delete_training import DeleteTraining, DeleteTrainingCommand
21from kwai.modules.training.get_training import GetTraining, GetTrainingCommand
22from kwai.modules.training.get_trainings import GetTrainings, GetTrainingsCommand
23from kwai.modules.training.teams.team_db_repository import TeamDbRepository
24from kwai.modules.training.training_command import Coach
25from kwai.modules.training.trainings.training_db_repository import TrainingDbRepository
26from kwai.modules.training.trainings.training_definition_db_repository import (
27 TrainingDefinitionDbRepository,
28)
29from kwai.modules.training.trainings.training_definition_repository import (
30 TrainingDefinitionNotFoundException,
31)
32from kwai.modules.training.trainings.training_repository import (
33 TrainingNotFoundException,
34)
35from kwai.modules.training.update_training import UpdateTraining, UpdateTrainingCommand
38router = APIRouter()
41class TrainingsFilterModel(BaseModel):
42 """Define the JSON:API filter for trainings."""
44 year: int | None = Field(Query(default=None, alias="filter[year]"))
45 month: int | None = Field(Query(default=None, alias="filter[month]"))
46 start: datetime | None = Field(Query(default=None, alias="filter[start]"))
47 end: datetime | None = Field(Query(default=None, alias="filter[end]"))
48 active: bool = Field(Query(default=True, alias="filter[active]"))
49 coach: int | None = Field(Query(default=None, alias="filter[coach]"))
50 definition: int | None = Field(Query(default=None, alias="filter[definition]"))
53@router.get(
54 "/trainings",
55 responses={
56 status.HTTP_404_NOT_FOUND: {
57 "description": "Coach or Training definition was not found."
58 }
59 },
60)
61async def get_trainings(
62 pagination: PaginationModel = Depends(PaginationModel),
63 trainings_filter: TrainingsFilterModel = Depends(TrainingsFilterModel),
64 db=Depends(create_database),
65) -> TrainingDocument:
66 """Get all trainings."""
67 command = GetTrainingsCommand(
68 offset=pagination.offset or 0,
69 limit=pagination.limit,
70 year=trainings_filter.year,
71 month=trainings_filter.month,
72 start=trainings_filter.start,
73 end=trainings_filter.end,
74 active=trainings_filter.active,
75 coach=trainings_filter.coach,
76 definition=trainings_filter.definition,
77 )
79 try:
80 count, training_iterator = await GetTrainings(
81 TrainingDbRepository(db),
82 CoachDbRepository(db),
83 TrainingDefinitionDbRepository(db),
84 ).execute(command)
85 except TrainingDefinitionNotFoundException as ex:
86 raise HTTPException(
87 status_code=status.HTTP_404_NOT_FOUND, detail=str(ex)
88 ) from ex
89 except CoachNotFoundException as ex:
90 raise HTTPException(
91 status_code=status.HTTP_404_NOT_FOUND, detail=str(ex)
92 ) from ex
94 document: TrainingDocument = TrainingDocument(
95 meta=Meta(count=count, offset=command.offset, limit=command.limit), data=[]
96 )
97 async for training in training_iterator:
98 document.merge(TrainingDocument.create(training))
100 return document
103@router.get(
104 "/trainings/{training_id}",
105 responses={status.HTTP_404_NOT_FOUND: {"description": "Training was not found."}},
106)
107async def get_training(
108 training_id: int,
109 db=Depends(create_database),
110) -> TrainingDocument:
111 """Get the training with the given id."""
112 command = GetTrainingCommand(id=training_id)
114 try:
115 training = await GetTraining(TrainingDbRepository(db)).execute(command)
116 except TrainingNotFoundException as ex:
117 raise HTTPException(
118 status_code=status.HTTP_404_NOT_FOUND, detail=str(ex)
119 ) from ex
121 return TrainingDocument.create(training)
124@router.post(
125 "/trainings",
126 status_code=status.HTTP_201_CREATED,
127)
128async def create_training(
129 resource: TrainingDocument,
130 db=Depends(create_database),
131 user: UserEntity = Depends(get_current_user),
132) -> TrainingDocument:
133 """Create a new training."""
134 command = CreateTrainingCommand(
135 start_date=resource.data.attributes.event.start_date,
136 end_date=resource.data.attributes.event.end_date,
137 active=resource.data.attributes.event.active,
138 cancelled=resource.data.attributes.event.cancelled,
139 texts=[
140 TextCommand(
141 locale=text.locale,
142 format=text.format,
143 title=text.title,
144 summary=text.original_summary,
145 content=text.original_content,
146 )
147 for text in resource.data.attributes.texts
148 ],
149 coaches=[
150 Coach(
151 id=int(coach.id),
152 head=coach.head,
153 present=coach.present,
154 payed=coach.payed,
155 )
156 for coach in resource.data.attributes.coaches
157 ],
158 teams=[int(team.id) for team in resource.data.relationships.teams.data],
159 definition=None
160 if resource.data.relationships.definition.data is None
161 else resource.data.relationships.definition.data.id,
162 location=resource.data.attributes.event.location,
163 remark=resource.data.attributes.remark,
164 )
166 try:
167 training = await CreateTraining(
168 TrainingDbRepository(db),
169 TrainingDefinitionDbRepository(db),
170 CoachDbRepository(db),
171 TeamDbRepository(db),
172 Owner(id=user.id, uuid=user.uuid, name=user.name),
173 ).execute(command)
174 except ValueError as ve:
175 raise HTTPException(
176 status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail=str(ve)
177 ) from ve
179 return TrainingDocument.create(training)
182@router.patch(
183 "/trainings/{training_id}",
184 responses={status.HTTP_404_NOT_FOUND: {"description": "Training was not found."}},
185)
186async def update_training(
187 training_id: int,
188 resource: TrainingDocument,
189 db=Depends(create_database),
190 user: UserEntity = Depends(get_current_user),
191) -> TrainingDocument:
192 """Update a training."""
193 command = UpdateTrainingCommand(
194 id=training_id,
195 start_date=resource.data.attributes.event.start_date,
196 end_date=resource.data.attributes.event.end_date,
197 active=resource.data.attributes.event.active,
198 cancelled=resource.data.attributes.event.cancelled,
199 texts=[
200 TextCommand(
201 locale=text.locale,
202 format=text.format,
203 title=text.title,
204 summary=text.original_summary,
205 content=text.original_content,
206 )
207 for text in resource.data.attributes.texts
208 ],
209 coaches=[
210 Coach(
211 id=int(coach.id),
212 head=coach.head,
213 present=coach.present,
214 payed=coach.payed,
215 )
216 for coach in resource.data.attributes.coaches
217 ],
218 teams=[int(team.id) for team in resource.data.relationships.teams.data],
219 definition=None
220 if resource.data.relationships.definition.data is None
221 else resource.data.relationships.definition.data.id,
222 location=resource.data.attributes.event.location,
223 remark=resource.data.attributes.remark,
224 )
226 try:
227 training = await UpdateTraining(
228 TrainingDbRepository(db),
229 TrainingDefinitionDbRepository(db),
230 CoachDbRepository(db),
231 TeamDbRepository(db),
232 Owner(id=user.id, uuid=user.uuid, name=user.name),
233 ).execute(command)
234 except TrainingNotFoundException as ex:
235 raise HTTPException(
236 status_code=status.HTTP_404_NOT_FOUND, detail=str(ex)
237 ) from ex
238 except ValueError as ve:
239 raise HTTPException(
240 status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail=str(ve)
241 ) from ve
243 return TrainingDocument.create(training)
246@router.delete(
247 "/trainings/{training_id}",
248 responses={status.HTTP_404_NOT_FOUND: {"description": "Training was not found."}},
249)
250async def delete_training(
251 training_id: int,
252 db=Depends(create_database),
253 user: UserEntity = Depends(get_current_user),
254) -> None:
255 """Delete a training definition."""
256 command = DeleteTrainingCommand(id=training_id)
257 await DeleteTraining(TrainingDbRepository(db)).execute(command)