Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1from settings import REASON_CATEGORIES 

2from flask import current_app 

3from flask_jwt_extended import get_jwt_claims 

4from sqlalchemy import func, text, select, and_ 

5from sqlalchemy.sql.expression import null 

6 

7from src import db, settings 

8from src.utils import pagination_resp, internal_err_resp, message, Paginator, err_resp 

9from src.model import BookModel, UserModel, ContentModel, RecommendedContentModel, RecommendedContentForGroupModel, MetaUserContentModel, BadRecommendationContentModel, BookAdditionalModel 

10from src.schemas import BookBase, BookExtra, MetaUserContentBase, BookAdditionalBase 

11 

12 

13class BookService: 

14 @staticmethod 

15 def search_book_data(search_term, page, connected_user_uuid): 

16 """ Search book data by title """ 

17 if not (UserModel.query.filter_by(uuid=connected_user_uuid).first()): 

18 return err_resp("User not found!", 404) 

19 books, total_pages = Paginator.get_from( 

20 BookModel.query.filter(BookModel.title.ilike(search_term+"%")).union( 

21 BookModel.query.filter(BookModel.title.ilike("%"+search_term+"%"))), 

22 page, 

23 ) 

24 

25 try: 

26 book_data = BookBase.loads(books) 

27 

28 return pagination_resp( 

29 message="Book data sent", 

30 content=book_data, 

31 page=page, 

32 total_pages=total_pages 

33 ) 

34 

35 except Exception as error: 

36 current_app.logger.error(error) 

37 return internal_err_resp() 

38 

39 @staticmethod 

40 def get_popular_books(page, connected_user_uuid): 

41 if not (user := UserModel.query.filter_by(uuid=connected_user_uuid).first()): 

42 return err_resp("User not found!", 404) 

43 

44 books, total_pages = Paginator.get_from( 

45 BookModel.query.join(BookModel.content, aliased=True).order_by( 

46 ContentModel.popularity_score.desc().nullslast(), 

47 ), 

48 page, 

49 ) 

50 

51 try: 

52 book_data = BookBase.loads(books) 

53 

54 return pagination_resp( 

55 message="Most popular book data sent", 

56 content=book_data, 

57 page=page, 

58 total_pages=total_pages 

59 ) 

60 

61 except Exception as error: 

62 current_app.logger.error(error) 

63 return internal_err_resp() 

64 

65 @staticmethod 

66 def get_recommended_books_for_user(page, connected_user_uuid, reco_engine): 

67 if not (user := UserModel.query.filter_by(uuid=connected_user_uuid).first()): 

68 return err_resp("User not found!", 404) 

69 

70 filters = [RecommendedContentModel.user_id == user.user_id] 

71 if reco_engine is not None: 

72 filters.append(RecommendedContentModel.engine == reco_engine) 

73 

74 books, total_pages = Paginator.get_from( 

75 db.session.query(RecommendedContentModel, BookModel) 

76 .join(BookModel.content) 

77 .join(RecommendedContentModel, RecommendedContentModel.content_id == ContentModel.content_id) 

78 .filter( 

79 and_(*filters) 

80 ) 

81 .order_by( 

82 RecommendedContentModel.score.desc().nullslast(), 

83 ContentModel.popularity_score.desc().nullslast(), 

84 ), 

85 page, 

86 ) 

87 

88 try: 

89 def c_load(row): 

90 book = BookExtra.load(row[1]) 

91 book["reco_engine"] = row[0].engine 

92 book["reco_score"] = row[0].score 

93 return book 

94 

95 book_data = list(map(c_load, books)) 

96 

97 return pagination_resp( 

98 message="Most popular book data sent", 

99 content=book_data, 

100 page=page, 

101 total_pages=total_pages 

102 ) 

103 

104 except Exception as error: 

105 current_app.logger.error(error) 

106 return internal_err_resp() 

107 

108 @staticmethod 

109 def get_recommended_books_for_group(page, connected_user_uuid, reco_engine): 

110 if not (user := UserModel.query.filter_by(uuid=connected_user_uuid).first()): 

111 return err_resp("User not found!", 404) 

112 

113 # Query for recommendation from group 

114 groups_ids = [ 

115 *list(map(lambda x: x.group_id, user.groups)), 

116 *list(map(lambda x: x.group_id, user.owned_groups)) 

117 ] 

118 

119 filters = [RecommendedContentForGroupModel.group_id.in_(groups_ids)] 

120 if reco_engine is not None: 

121 filters.append(RecommendedContentModel.engine == reco_engine) 

122 

123 books, total_pages = Paginator.get_from( 

124 db.session.query(RecommendedContentForGroupModel, BookModel) 

125 .join(BookModel.content) 

126 .join(RecommendedContentForGroupModel, RecommendedContentForGroupModel.content_id == ContentModel.content_id) 

127 .filter( 

128 and_(*filters) 

129 ) 

130 .order_by( 

131 RecommendedContentModel.score.desc().nullslast(), 

132 ContentModel.popularity_score.desc().nullslast(), 

133 ), 

134 page, 

135 ) 

136 

137 try: 

138 def c_load(row): 

139 book = BookExtra.load(row[1]) 

140 book["reco_engine"] = row[0].engine 

141 book["reco_score"] = row[0].score 

142 return app 

143 

144 book_data = list(map(c_load, books)) 

145 

146 return pagination_resp( 

147 message="Most popular book data sent", 

148 content=book_data, 

149 page=page, 

150 total_pages=total_pages 

151 ) 

152 

153 except Exception as error: 

154 current_app.logger.error(error) 

155 return internal_err_resp() 

156 

157 @staticmethod 

158 def add_bad_recommendation(user_uuid, content_id, data): 

159 """ Add bad user recommendation """ 

160 if not (user := UserModel.query.filter_by(uuid=user_uuid).first()): 

161 return err_resp("User not found!", 404) 

162 

163 if not (book := BookModel.query.filter_by(content_id=content_id).first()): 

164 return err_resp("Book not found!", 404) 

165 

166 try: 

167 for type, value in data.items(): 

168 if type in REASON_CATEGORIES['book']: 

169 for r in value: 

170 

171 new_bad_reco = BadRecommendationContentModel( 

172 user_id=user.user_id, 

173 content_id=book.content_id, 

174 reason_categorie=type, 

175 reason=r 

176 ) 

177 

178 db.session.add(new_bad_reco) 

179 db.session.flush() 

180 db.session.commit() 

181 

182 resp = message(True, "Bad recommendation has been registered.") 

183 return resp, 201 

184 

185 except Exception as error: 

186 current_app.logger.error(error) 

187 return internal_err_resp() 

188 

189 @staticmethod 

190 def add_additional_book(user_uuid, data): 

191 """ Add additional book""" 

192 if not (user := UserModel.query.filter_by(uuid=user_uuid).first()): 

193 return err_resp("User not found!", 404) 

194 

195 # Check permissions 

196 permissions = get_jwt_claims()['permissions'] 

197 if "add_content" not in permissions: 

198 return err_resp("Permission missing", 403) 

199 

200 try: 

201 

202 new_additional_book = BookAdditionalModel( 

203 title=data['title'], 

204 isbn=data['isbn'], 

205 ) 

206 

207 if 'author' in data: 

208 new_additional_book.author = data['author'] 

209 if 'year_of_publication' in data: 

210 new_additional_book.year_of_publication = data['year_of_publication'] 

211 if 'publisher' in data: 

212 new_additional_book.publisher = data['publisher'] 

213 if 'image_url_s' in data: 

214 new_additional_book.image_url_s = data['image_url_s'] 

215 if 'image_url_m' in data: 

216 new_additional_book.image_url_m = data['image_url_m'] 

217 if 'image_url_l' in data: 

218 new_additional_book.image_url_l = data['image_url_l'] 

219 

220 db.session.add(new_additional_book) 

221 db.session.commit() 

222 

223 resp = message(True, "Book have been added to validation.") 

224 return resp, 201 

225 

226 except Exception as error: 

227 current_app.logger.error(error) 

228 return internal_err_resp() 

229 

230 

231 @staticmethod 

232 def get_additional_book(connected_user_uuid, page): 

233 if not (user := UserModel.query.filter_by(uuid=connected_user_uuid).first()): 

234 return err_resp("User not found!", 404) 

235 

236 # Check permissions 

237 permissions = get_jwt_claims()['permissions'] 

238 if "add_content" not in permissions: 

239 return err_resp("Permission missing", 403) 

240 

241 books, total_pages = Paginator.get_from( 

242 BookAdditionalModel.query, 

243 page, 

244 ) 

245 

246 try: 

247 book_data = BookAdditionalBase.loads(books) 

248 

249 return pagination_resp( 

250 message="Additional Book data sent", 

251 content=book_data, 

252 page=page, 

253 total_pages=total_pages 

254 ) 

255 

256 except Exception as error: 

257 current_app.logger.error(error) 

258 return internal_err_resp() 

259 

260 @staticmethod 

261 def validate_additional_book(connected_user_uuid, book_id): 

262 if not (user := UserModel.query.filter_by(uuid=connected_user_uuid).first()): 

263 return err_resp("User not found!", 404) 

264 

265 # Check permissions 

266 permissions = get_jwt_claims()['permissions'] 

267 if "validate_added_content" not in permissions: 

268 return err_resp("Permission missing", 403) 

269 

270 if not (book := BookAdditionalModel.query.filter_by(book_id=book_id).first()): 

271 return err_resp("Additional book not found!", 404) 

272 

273 try: 

274 content = ContentModel(rating=None) 

275 db.session.add(content) 

276 db.session.flush() 

277 

278 new_book = BookModel( 

279 isbn=book.isbn, 

280 title=book.title, 

281 author=book.author, 

282 year_of_publication=book.year_of_publication, 

283 publisher=book.publisher, 

284 image_url_s=book.image_url_s, 

285 image_url_m=book.image_url_m, 

286 image_url_l=book.image_url_l, 

287 content=content 

288 ) 

289 db.session.add(new_book) 

290 db.session.delete(book) 

291 

292 db.session.commit() 

293 

294 resp = message( 

295 True, "Additional book data successfully validated") 

296 return resp, 201 

297 

298 except Exception as error: 

299 current_app.logger.error(error) 

300 return internal_err_resp() 

301 

302 @staticmethod 

303 def decline_additional_book(connected_user_uuid, book_id): 

304 if not (user := UserModel.query.filter_by(uuid=connected_user_uuid).first()): 

305 return err_resp("User not found!", 404) 

306 

307 # Check permissions 

308 permissions = get_jwt_claims()['permissions'] 

309 if "delete_content" not in permissions: 

310 return err_resp("Permission missing", 403) 

311 

312 if not (book := BookAdditionalModel.query.filter_by(book_id=book_id).first()): 

313 return err_resp("Additional book not found!", 404) 

314 

315 try: 

316 db.session.delete(book) 

317 db.session.commit() 

318 

319 resp = message(True, "Additional book successfully deleted") 

320 return resp, 201 

321 

322 except Exception as error: 

323 current_app.logger.error(error) 

324 return internal_err_resp()