Coverage for app/controllers/serviceLearning/routes.py: 28%

182 statements  

« prev     ^ index     » next       coverage.py v7.2.5, created at 2023-05-24 14:13 +0000

1from flask import request, render_template, g, url_for, abort, redirect, flash, session, send_from_directory, send_file, jsonify 

2from werkzeug.utils import safe_join 

3import os 

4from peewee import * 

5from app.models.user import User 

6from app.models.term import Term 

7from app.models.course import Course 

8from app.models.courseStatus import CourseStatus 

9from app.models.courseInstructor import CourseInstructor 

10from app.models.courseQuestion import CourseQuestion 

11from app.models.attachmentUpload import AttachmentUpload 

12from app.logic.utils import selectSurroundingTerms, getFilesFromRequest 

13from app.logic.fileHandler import FileHandler 

14from app.logic.serviceLearningCoursesData import getServiceLearningCoursesData, withdrawProposal, renewProposal 

15from app.logic.courseManagement import updateCourse, createCourse 

16from app.logic.downloadFile import * 

17from app.logic.courseManagement import approvedCourses 

18from app.controllers.main.routes import getRedirectTarget, setRedirectTarget 

19from app.controllers.serviceLearning import serviceLearning_bp 

20 

21 

22@serviceLearning_bp.route('/serviceLearning/courseManagement', methods = ['GET']) 

23@serviceLearning_bp.route('/serviceLearning/courseManagement/<username>', methods = ['GET']) 

24def serviceCourseManagement(username=None): 

25 if g.current_user.isStudent: 

26 abort(403) 

27 if g.current_user.isCeltsAdmin or g.current_user.isFaculty: 

28 setRedirectTarget("/serviceLearning/courseManagement") 

29 user = User.get(User.username==username) if username else g.current_user 

30 courseDict = getServiceLearningCoursesData(user) 

31 termList = selectSurroundingTerms(g.current_term, prevTerms=0) 

32 return render_template('serviceLearning/slcManagement.html', 

33 user=user, 

34 courseDict=courseDict, 

35 termList=termList) 

36 else: 

37 flash("Unauthorized to view page", 'warning') 

38 return redirect(url_for('main.events', selectedTerm=g.current_term)) 

39 

40@serviceLearning_bp.route('/serviceLearning/viewProposal/<courseID>', methods=['GET']) 

41@serviceLearning_bp.route('/serviceLearning/editProposal/upload/<courseID>', methods=['GET']) 

42@serviceLearning_bp.route('/serviceLearning/editProposal/<courseID>', methods=['GET']) 

43def slcEditProposal(courseID): 

44 """ 

45 Route for editing proposals, it will fill the form with the data found in the database 

46 given a courseID. 

47 """ 

48 instructors = CourseInstructor.select().where(CourseInstructor.course==courseID) 

49 courseInstructors = [instructor.user for instructor in instructors] 

50 if g.current_user.isCeltsAdmin or g.current_user in courseInstructors: 

51 course = Course.get_by_id(courseID) 

52 courseStatus = CourseStatus.get_by_id(course.status) 

53 courseStatusInt = courseStatus.get_id() 

54 approved = 3 

55 # Condition to check the route you are comming from 

56 if courseStatusInt==approved and request.path == f"/serviceLearning/editProposal/{courseID}": 

57 return redirect(f"/serviceLearning/viewProposal/{courseID}") 

58 else: 

59 statusOfCourse = Course.select(Course.status) 

60 questionData = (CourseQuestion.select().where(CourseQuestion.course == course)) 

61 questionanswers = [question.questionContent for question in questionData] 

62 courseInstructor = CourseInstructor.select().where(CourseInstructor.course == courseID) 

63 associatedAttachments = AttachmentUpload.select().where(AttachmentUpload.course == course.id) 

64 

65 filepaths = FileHandler(courseId=course.id).retrievePath(associatedAttachments) 

66 

67 terms = selectSurroundingTerms(g.current_term, 0) 

68 return render_template('serviceLearning/slcNewProposal.html', 

69 course = course, 

70 questionanswers = questionanswers, 

71 terms = terms, 

72 statusOfCourse = statusOfCourse, 

73 courseStatus = courseStatus, 

74 courseInstructor = courseInstructor, 

75 filepaths = filepaths, 

76 redirectTarget=getRedirectTarget()) 

77 else: 

78 abort(403) 

79 

80 

81@serviceLearning_bp.route('/serviceLearning/createCourse', methods=['POST']) 

82def slcCreateCourse(): 

83 """will give a new course ID so that it can redirect to an edit page""" 

84 course = createCourse(g.current_user) 

85 

86 return redirect(url_for('serviceLearning.slcEditProposal', courseID = course.id)) 

87 

88@serviceLearning_bp.route('/serviceLearning/saveExit', methods=['POST']) 

89@serviceLearning_bp.route('/serviceLearning/saveProposal', methods=['POST']) 

90def slcSaveContinue(): 

91 """Will update the the course proposal and return an empty string since ajax request needs a response 

92 Also, it updates the course status as 'in progress'""" 

93 course = updateCourse(request.form.copy()) 

94 

95 if not course: 

96 flash("Error saving changes", "danger") 

97 else: 

98 course.status = CourseStatus.IN_PROGRESS 

99 course.save() 

100 flash(f"Proposal has been saved.", "success") 

101 return "" 

102 

103@serviceLearning_bp.route('/serviceLearning/newProposal', methods=['GET', 'POST']) 

104def slcCreateOrEdit(): 

105 if request.method == "POST": 

106 course = updateCourse(request.form.copy()) 

107 if not course: 

108 flash("Error saving changes", "danger") 

109 else: 

110 if getRedirectTarget(False): 

111 return redirect('' + getRedirectTarget(True) + '') 

112 return redirect('/serviceLearning/courseManagement') 

113 

114 terms = Term.select().where(Term.year >= g.current_term.year) 

115 courseData = None 

116 return render_template('serviceLearning/slcNewProposal.html', 

117 terms = terms, 

118 courseData = courseData, 

119 redirectTarget = getRedirectTarget(True)) 

120 

121@serviceLearning_bp.route('/serviceLearning/approveCourse', methods=['POST']) 

122def approveCourse(): 

123 """ 

124 This function updates and approves a Service-Learning Course when using the 

125 approve button. 

126 return: empty string because AJAX needs to receive something 

127 """ 

128 

129 try: 

130 # We are only approving, and not updating 

131 if len(request.form) == 1: 

132 course = Course.get_by_id(request.form['courseID']) 

133 

134 # We have data and need to update the course first 

135 else: 

136 course = updateCourse(request.form.copy()) 

137 

138 course.status = CourseStatus.APPROVED 

139 course.save() 

140 flash("Course approved!", "success") 

141 

142 except Exception as e: 

143 print(e) 

144 flash("Course not approved!", "danger") 

145 return "" 

146@serviceLearning_bp.route('/serviceLearning/unapproveCourse', methods=['POST']) 

147def unapproveCourse(): 

148 """ 

149 This function updates and unapproves a Service-Learning Course when using the 

150 unapprove button. 

151 return: empty string because AJAX needs to receive something 

152 """ 

153 

154 try: 

155 if len(request.form) == 1: 

156 course = Course.get_by_id(request.form['courseID']) 

157 else: 

158 course = updateCourse(request.form.copy()) 

159 

160 course.status = CourseStatus.SUBMITTED 

161 course.save() 

162 flash("Course unapproved!", "success") 

163 

164 except Exception as e: 

165 print(e) 

166 flash("Course was not unapproved!", "danger") 

167 

168 return "" 

169 

170@serviceLearning_bp.route('/updateInstructorPhone', methods=['POST']) 

171def updateInstructorPhone(): 

172 instructorData = request.get_json() 

173 (User.update(phoneNumber=instructorData[1]) 

174 .where(User.username == instructorData[0])).execute() 

175 return "success" 

176 

177@serviceLearning_bp.route('/serviceLearning/withdraw/<courseID>', methods = ['POST']) 

178def withdrawCourse(courseID): 

179 try: 

180 if g.current_user.isAdmin or g.current_user.isFaculty: 

181 withdrawProposal(courseID) 

182 flash("Course successfully withdrawn", 'success') 

183 else: 

184 flash("Unauthorized to perform this action", 'warning') 

185 except Exception as e: 

186 print(e) 

187 flash("Withdrawal Unsuccessful", 'warning') 

188 return "" 

189 

190@serviceLearning_bp.route('/serviceLearning/renew/<courseID>/<termID>/', methods = ['POST']) 

191def renewCourse(courseID, termID): 

192 """ 

193 This function checks to see if the user is a CELTS admin or is 

194 an instructor of a course (faculty) and allows courses to be renewed. 

195 :return: empty string because AJAX needs to receive something 

196 """ 

197 instructors = CourseInstructor.select().where(CourseInstructor.course==courseID) 

198 courseInstructors = [instructor.user for instructor in instructors] 

199 try: 

200 if g.current_user.isCeltsAdmin or g.current_user in courseInstructors: 

201 renewedProposal = renewProposal(courseID, termID) 

202 flash("Course successfully renewed", 'success') 

203 return str(renewedProposal.id) 

204 else: 

205 flash("Unauthorized to perform this action", 'warning') 

206 except Exception as e: 

207 print(e) 

208 flash("Renewal Unsuccessful", 'warning') 

209 

210 return "", 500 

211 

212@serviceLearning_bp.route('/serviceLearning/print/<courseID>', methods=['GET']) 

213def printCourse(courseID): 

214 """ 

215 This function will print a PDF of an SLC proposal. 

216 """ 

217 instructors = CourseInstructor.select().where(CourseInstructor.course==courseID) 

218 courseInstructors = [instructor.user for instructor in instructors] 

219 isCreator = Course.select().where(Course.createdBy == g.current_user, Course.id==courseID).exists() 

220 if g.current_user.isCeltsAdmin or g.current_user in courseInstructors or isCreator: 

221 try: 

222 course = Course.get_by_id(courseID) 

223 pdfCourse = Course.select().where(Course.id == courseID) 

224 pdfInstructor = CourseInstructor.select().where(CourseInstructor.course == courseID) 

225 pdfQuestions = (CourseQuestion.select().where(CourseQuestion.course == course)) 

226 questionanswers = [question.questionContent for question in pdfQuestions] 

227 

228 return render_template('serviceLearning/slcFormPrint.html', 

229 course = course, 

230 pdfCourse = pdfCourse, 

231 pdfInstructor = pdfInstructor, 

232 pdfQuestions = pdfQuestions, 

233 questionanswers=questionanswers 

234 ) 

235 except Exception as e: 

236 flash("An error was encountered when printing, please try again.", 'warning') 

237 print(e) 

238 return "", 500 

239 else: 

240 abort(403) 

241 

242@serviceLearning_bp.route("/uploadCourseFile", methods=['GET', "POST"]) 

243def uploadCourseFile(): 

244 try: 

245 attachment = getFilesFromRequest(request) 

246 courseID = request.form["courseID"] 

247 addFile= FileHandler(attachment, courseId=courseID) 

248 addFile.saveFiles() 

249 except: 

250 flash("No file selected.", "warning") 

251 return redirect('/serviceLearning/editProposal/upload/'+courseID) 

252 

253 

254@serviceLearning_bp.route("/deleteCourseFile", methods=["POST"]) 

255def deleteCourseFile(): 

256 fileData= request.form 

257 courseFile=FileHandler(courseId=fileData["courseId"]) 

258 courseFile.deleteFile(fileData["fileId"]) 

259 return "" 

260 

261@serviceLearning_bp.route('/serviceLearning/downloadApprovedCourses/<termID>', methods = ['GET']) 

262def downloadApprovedCourses(termID): 

263 """ 

264 This function allows the download of csv file 

265 """ 

266 try: 

267 designator = "downloadApprovedCourses" 

268 csvInfo = approvedCourses(termID) 

269 fileFormat = {"headers":["Course Name", "Course Number", "Faculty", "Term", "Previously Approved Course?"]} 

270 filePath = safe_join(os.getcwd(), app.config['files']['base_path']) 

271 newFile = fileMaker(designator, csvInfo, "CSV", fileFormat) 

272 return send_from_directory(filePath, 'ApprovedCourses.csv', as_attachment=True) 

273 

274 except Exception as e: 

275 print(e) 

276 return ""