Coverage for kwai/api/v1/trainings/endpoints/trainings.py: 90%

71 statements  

« prev     ^ index     » next       coverage.py v7.3.0, created at 2023-09-05 17:55 +0000

1"""Module for endpoints for trainings.""" 

2from datetime import datetime 

3 

4from fastapi import APIRouter, Depends, HTTPException, Query, status 

5from pydantic import BaseModel, Field 

6 

7from kwai.api.dependencies import deps, get_current_user 

8from kwai.api.v1.trainings.schemas.training import TrainingResource 

9from kwai.core.db.database import Database 

10from kwai.core.domain.value_objects.owner import Owner 

11from kwai.core.json_api import Meta, PaginationModel 

12from kwai.modules.identity.users.user import UserEntity 

13from kwai.modules.training.coaches.coach_db_repository import CoachDbRepository 

14from kwai.modules.training.coaches.coach_repository import CoachNotFoundException 

15from kwai.modules.training.create_training import ( 

16 CreateTraining, 

17 CreateTrainingCommand, 

18) 

19from kwai.modules.training.delete_training import DeleteTraining, DeleteTrainingCommand 

20from kwai.modules.training.get_training import GetTraining, GetTrainingCommand 

21from kwai.modules.training.get_trainings import GetTrainings, GetTrainingsCommand 

22from kwai.modules.training.teams.team_db_repository import TeamDbRepository 

23from kwai.modules.training.training_command import Coach 

24from kwai.modules.training.trainings.training_db_repository import TrainingDbRepository 

25from kwai.modules.training.trainings.training_definition_db_repository import ( 

26 TrainingDefinitionDbRepository, 

27) 

28from kwai.modules.training.trainings.training_definition_repository import ( 

29 TrainingDefinitionNotFoundException, 

30) 

31from kwai.modules.training.trainings.training_repository import ( 

32 TrainingNotFoundException, 

33) 

34from kwai.modules.training.update_training import UpdateTraining, UpdateTrainingCommand 

35 

36router = APIRouter() 

37 

38 

39class TrainingsFilterModel(BaseModel): 

40 """Define the JSON:API filter for trainings.""" 

41 

42 year: int | None = Field(Query(default=None, alias="filter[year]")) 

43 month: int | None = Field(Query(default=None, alias="filter[month]")) 

44 start: datetime | None = Field(Query(default=None, alias="filter[start]")) 

45 end: datetime | None = Field(Query(default=None, alias="filter[end]")) 

46 active: bool = Field(Query(default=True, alias="filter[active]")) 

47 coach: int | None = Field(Query(default=None, alias="filter[coach]")) 

48 definition: int | None = Field(Query(default=None, alias="filter[definition]")) 

49 

50 

51@router.get( 

52 "/trainings", 

53 responses={ 

54 status.HTTP_404_NOT_FOUND: { 

55 "description": "Coach or Training definition was not found." 

56 } 

57 }, 

58) 

59async def get_trainings( 

60 pagination: PaginationModel = Depends(PaginationModel), 

61 trainings_filter: TrainingsFilterModel = Depends(TrainingsFilterModel), 

62 db=deps.depends(Database), 

63) -> TrainingResource.get_document_model(): 

64 """Get all trainings.""" 

65 command = GetTrainingsCommand( 

66 offset=pagination.offset or 0, 

67 limit=pagination.limit, 

68 year=trainings_filter.year, 

69 month=trainings_filter.month, 

70 start=trainings_filter.start, 

71 end=trainings_filter.end, 

72 active=trainings_filter.active, 

73 coach=trainings_filter.coach, 

74 definition=trainings_filter.definition, 

75 ) 

76 

77 try: 

78 count, training_iterator = await GetTrainings( 

79 TrainingDbRepository(db), 

80 CoachDbRepository(db), 

81 TrainingDefinitionDbRepository(db), 

82 ).execute(command) 

83 except TrainingDefinitionNotFoundException as ex: 

84 raise HTTPException( 

85 status_code=status.HTTP_404_NOT_FOUND, detail=str(ex) 

86 ) from ex 

87 except CoachNotFoundException as ex: 

88 raise HTTPException( 

89 status_code=status.HTTP_404_NOT_FOUND, detail=str(ex) 

90 ) from ex 

91 

92 document = TrainingResource.serialize_list( 

93 [TrainingResource(training) async for training in training_iterator] 

94 ) 

95 document.meta = Meta(count=count, offset=command.offset, limit=command.limit) 

96 

97 return document 

98 

99 

100@router.get( 

101 "/trainings/{training_id}", 

102 responses={status.HTTP_404_NOT_FOUND: {"description": "Training was not found."}}, 

103) 

104async def get_training( 

105 training_id: int, 

106 db=deps.depends(Database), 

107) -> TrainingResource.get_document_model(): 

108 """Get the training with the given id.""" 

109 command = GetTrainingCommand(id=training_id) 

110 

111 try: 

112 training = await GetTraining(TrainingDbRepository(db)).execute(command) 

113 except TrainingNotFoundException as ex: 

114 raise HTTPException( 

115 status_code=status.HTTP_404_NOT_FOUND, detail=str(ex) 

116 ) from ex 

117 

118 return TrainingResource.serialize(TrainingResource(training)) 

119 

120 

121@router.post( 

122 "/trainings", 

123 status_code=status.HTTP_201_CREATED, 

124) 

125async def create_training( 

126 resource: TrainingResource.get_resource_data_model(), 

127 db=deps.depends(Database), 

128 user: UserEntity = Depends(get_current_user), 

129) -> TrainingResource.get_document_model(): 

130 """Create a new training.""" 

131 command = CreateTrainingCommand( 

132 start_date=resource.data.attributes.event.start_date, 

133 end_date=resource.data.attributes.event.end_date, 

134 active=resource.data.attributes.event.active, 

135 cancelled=resource.data.attributes.event.cancelled, 

136 text=[ 

137 { 

138 "locale": text.locale, 

139 "format": text.format, 

140 "title": text.title, 

141 "summary": text.summary, 

142 "content": text.content, 

143 } 

144 for text in resource.data.attributes.contents 

145 ], 

146 coaches=[ 

147 Coach( 

148 id=int(coach.id), 

149 head=coach.head, 

150 present=coach.present, 

151 payed=coach.payed, 

152 ) 

153 for coach in resource.data.attributes.coaches 

154 ], 

155 teams=[int(team.id) for team in resource.data.relationships.teams.data], 

156 definition=None, 

157 location=resource.data.attributes.event.location, 

158 remark=resource.data.attributes.remark, 

159 ) 

160 

161 try: 

162 resource = await CreateTraining( 

163 TrainingDbRepository(db), 

164 TrainingDefinitionDbRepository(db), 

165 CoachDbRepository(db), 

166 TeamDbRepository(db), 

167 Owner(id=user.id, uuid=user.uuid, name=user.name), 

168 ).execute(command) 

169 except ValueError as ve: 

170 raise HTTPException( 

171 status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail=str(ve) 

172 ) from ve 

173 

174 return TrainingResource.serialize(TrainingResource(resource)) 

175 

176 

177@router.patch( 

178 "/trainings/{training_id}", 

179 responses={status.HTTP_404_NOT_FOUND: {"description": "Training was not found."}}, 

180) 

181async def update_training( 

182 training_id: int, 

183 resource: TrainingResource.get_resource_data_model(), 

184 db=deps.depends(Database), 

185 user: UserEntity = Depends(get_current_user), 

186) -> TrainingResource.get_document_model(): 

187 """Update a training.""" 

188 command = UpdateTrainingCommand( 

189 id=training_id, 

190 start_date=resource.data.attributes.event.start_date, 

191 end_date=resource.data.attributes.event.end_date, 

192 active=resource.data.attributes.event.active, 

193 cancelled=resource.data.attributes.event.cancelled, 

194 text=[ 

195 { 

196 "locale": text.locale, 

197 "format": text.format, 

198 "title": text.title, 

199 "summary": text.summary, 

200 "content": text.content, 

201 } 

202 for text in resource.data.attributes.contents 

203 ], 

204 coaches=[ 

205 Coach( 

206 id=int(coach.id), 

207 head=coach.head, 

208 present=coach.present, 

209 payed=coach.payed, 

210 ) 

211 for coach in resource.data.attributes.coaches 

212 ], 

213 teams=[int(team.id) for team in resource.data.relationships.teams.data], 

214 definition=None, 

215 location=resource.data.attributes.event.location, 

216 remark=resource.data.attributes.remark, 

217 ) 

218 

219 try: 

220 resource = await UpdateTraining( 

221 TrainingDbRepository(db), 

222 TrainingDefinitionDbRepository(db), 

223 CoachDbRepository(db), 

224 TeamDbRepository(db), 

225 Owner(id=user.id, uuid=user.uuid, name=user.name), 

226 ).execute(command) 

227 except ValueError as ve: 

228 raise HTTPException( 

229 status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail=str(ve) 

230 ) from ve 

231 

232 return TrainingResource.serialize(TrainingResource(resource)) 

233 

234 

235@router.delete( 

236 "/trainings/{training_id}", 

237 responses={status.HTTP_404_NOT_FOUND: {"description": "Training was not found."}}, 

238) 

239async def delete_training_definition( 

240 training_definition_id: int, 

241 resource: TrainingResource.get_resource_data_model(), 

242 db=deps.depends(Database), 

243 user: UserEntity = Depends(get_current_user), 

244) -> None: 

245 """Delete a training definition.""" 

246 command = DeleteTrainingCommand(id=training_definition_id) 

247 await DeleteTraining(TrainingDbRepository(db)).execute(command)