Coverage for app/controllers/admin/volunteers.py: 27%

153 statements  

« prev     ^ index     » next       coverage.py v7.10.2, created at 2026-04-09 12:45 +0000

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

2from peewee import DoesNotExist, JOIN 

3from datetime import datetime 

4from playhouse.shortcuts import model_to_dict 

5from app.controllers.admin import admin_bp 

6from app.models.event import Event 

7from app.models.program import Program 

8from app.models.user import User 

9from app.models.eventParticipant import EventParticipant 

10from app.models.emergencyContact import EmergencyContact 

11from app.models.insuranceInfo import InsuranceInfo 

12from app.logic.searchUsers import searchUsers 

13from app.logic.volunteers import updateEventParticipants, getEventLengthInHours, addUserBackgroundCheck, setProgramManager, deleteUserBackgroundCheck 

14from app.logic.participants import trainedParticipants, addPersonToEvent, getParticipationStatusForTrainings, sortParticipantsByStatus 

15from app.logic.events import getPreviousSeriesEventData, getEventRsvpCount 

16from app.models.eventRsvp import EventRsvp 

17from app.models.backgroundCheck import BackgroundCheck 

18from app.logic.createLogs import createActivityLog, createRsvpLog 

19from app.logic.users import getBannedUsers, isBannedFromEvent 

20 

21 

22@admin_bp.route('/searchVolunteers/<query>', methods = ['GET']) 

23def getVolunteers(query): 

24 '''Accepts user input and queries the database returning results that matches user search''' 

25 

26 return json.dumps(searchUsers(query)) 

27 

28@admin_bp.route('/event/<eventID>/manage_volunteers', methods=['GET', 'POST']) 

29def manageVolunteersPage(eventID): 

30 """ 

31 Controller that handles POST and GET requests regarding the Manage Volunteers page. 

32 

33 POST: updates the event participants for a particular event by calling  

34 updateEventParticipants on the form. 

35 

36 GET: retrieves all necessary participant lists and dictionaries and categorizes 

37 the participants/volunteers into their respective participation statuses. Then  

38 renders the manageVolunteers.html template. 

39 """ 

40 try: 

41 event = Event.get_by_id(eventID) 

42 except DoesNotExist as e: 

43 print(f"No event found for {eventID}", e) 

44 abort(404) 

45 

46 # ------------ POST request ------------ 

47 if request.method == "POST": 

48 volunteerUpdated = updateEventParticipants(request.form) 

49 

50 # error handling depending on the boolean returned from updateEventParticipants 

51 if volunteerUpdated: 

52 flash("Volunteer table succesfully updated", "success") 

53 else: 

54 flash("Error adding volunteer", "danger") 

55 return redirect(url_for("admin.manageVolunteersPage", eventID=eventID)) 

56 

57 # ------------ GET request ------------ 

58 elif request.method == "GET": 

59 if not (g.current_user.isCeltsAdmin or (g.current_user.isCeltsStudentStaff and g.current_user.isProgramManagerForEvent(event))): 

60 abort(403) 

61 

62 # ------- Grab the different lists of participants ------- 

63 trainedParticipantsForProgramAndTerm = trainedParticipants(event.program, event.term) 

64 

65 bannedUsersForProgram = [bannedUser.user for bannedUser in getBannedUsers(event.program)] 

66 

67 eventNonAttendedData, eventWaitlistData, eventVolunteerData, eventParticipants = sortParticipantsByStatus(event) 

68 

69 allRelevantUsers = list(set(participant.user for participant in (eventParticipants + eventNonAttendedData + eventWaitlistData + eventVolunteerData))) 

70 # ----------- Get miscellaneous data ----------- 

71 

72 participationStatusForTrainings = getParticipationStatusForTrainings(event.program, allRelevantUsers, event.term) 

73 

74 eventLengthInHours = getEventLengthInHours(event.timeStart, event.timeEnd, event.startDate) 

75 

76 repeatingVolunteers = getPreviousSeriesEventData(event.seriesId) 

77 

78 currentRsvpAmount = getEventRsvpCount(event.id) 

79 

80 # ----------- Render template with all of the data ------------ 

81 return render_template("/events/manageVolunteers.html", 

82 eventVolunteerData = eventVolunteerData, 

83 eventNonAttendedData = eventNonAttendedData, 

84 eventWaitlistData = eventWaitlistData, 

85 eventLength = eventLengthInHours, 

86 event = event, 

87 repeatingVolunteers = repeatingVolunteers, 

88 bannedUsersForProgram = bannedUsersForProgram, 

89 trainedParticipantsForProgramAndTerm = trainedParticipantsForProgramAndTerm, 

90 participationStatusForTrainings = participationStatusForTrainings, 

91 currentRsvpAmount = currentRsvpAmount) 

92 

93@admin_bp.route('/event/<eventID>/volunteer_details', methods=['GET']) 

94def volunteerDetailsPage(eventID): 

95 try: 

96 event = Event.get_by_id(eventID) 

97 except DoesNotExist as e: 

98 print(f"No event found for {eventID}", e) 

99 abort(404) 

100 

101 if not (g.current_user.isCeltsAdmin or (g.current_user.isCeltsStudentStaff and g.current_user.isProgramManagerForEvent(event))): 

102 abort(403) 

103 

104 eventRsvpData = list(EventRsvp.select(EmergencyContact, InsuranceInfo, EventRsvp) 

105 .join(EmergencyContact, JOIN.LEFT_OUTER, on=(EmergencyContact.user==EventRsvp.user)) 

106 .switch(EventRsvp) 

107 .join(InsuranceInfo, JOIN.LEFT_OUTER, on=(InsuranceInfo.user==EventRsvp.user)) 

108 .where(EventRsvp.event==event)) 

109 eventParticipantData = list(EventParticipant.select(EmergencyContact, EventParticipant,InsuranceInfo) 

110 .join(EmergencyContact, JOIN.LEFT_OUTER, on=(EmergencyContact.user==EventParticipant.user)) 

111 .switch(EventParticipant) 

112 .join(InsuranceInfo, JOIN.LEFT_OUTER, on=(InsuranceInfo.user==EventParticipant.user)) 

113 .where(EventParticipant.event==event)) 

114 

115 

116 waitlistUser = list(set([obj for obj in eventRsvpData if obj.rsvpWaitlist])) 

117 rsvpUser = list(set([obj for obj in eventRsvpData if not obj.rsvpWaitlist ])) 

118 return render_template("/events/volunteerDetails.html", 

119 waitlistUser = waitlistUser, 

120 attendedUser= eventParticipantData, 

121 rsvpUser= rsvpUser, 

122 event = event) 

123 

124 

125@admin_bp.route('/addVolunteersToEvent/<eventId>', methods = ['POST']) 

126def addVolunteer(eventId): 

127 event = Event.get_by_id(eventId) 

128 successfullyAddedVolunteer = False 

129 usernameList = request.form.getlist("selectedVolunteers[]") 

130 successfullyAddedVolunteer = False 

131 alreadyAddedList = [] 

132 addedSuccessfullyList = [] 

133 errorList = [] 

134 

135 for user in usernameList: 

136 userObj = User.get_by_id(user) 

137 successfullyAddedVolunteer = addPersonToEvent(userObj, event) 

138 if successfullyAddedVolunteer == "already in": 

139 alreadyAddedList.append(userObj.fullName) 

140 else: 

141 if successfullyAddedVolunteer: 

142 addedSuccessfullyList.append(userObj.fullName) 

143 else: 

144 errorList.append(userObj.fullName) 

145 

146 volunteers = "" 

147 if alreadyAddedList: 

148 volunteers = ", ".join(vol for vol in alreadyAddedList) 

149 flash(f"{volunteers} was already added to this event.", "warning") 

150 

151 if addedSuccessfullyList: 

152 volunteers = ", ".join(vol for vol in addedSuccessfullyList) 

153 flash(f"{volunteers} added successfully.", "success") 

154 

155 if errorList: 

156 volunteers = ", ".join(vol for vol in errorList) 

157 flash(f"Error when adding {volunteers} to event.", "danger") 

158 

159 if 'ajax' in request.form and request.form['ajax']: 

160 return '' 

161 

162 return redirect(url_for('admin.manageVolunteersPage', eventID = eventId)) 

163 

164@admin_bp.route('/rsvpFromWaitlist/<username>/<eventId>', methods = ['POST']) 

165def rsvpFromWaitlist(username, eventId): 

166 event = Event.get_by_id(eventId) 

167 isProgramManager = g.current_user.isProgramManagerFor(event.program) 

168 if g.current_user.isCeltsAdmin or (g.current_user.isCeltsStudentStaff and isProgramManager): 

169 waitlistUsers = EventRsvp.select(EventRsvp, User).join(User).where(EventRsvp.user == username, EventRsvp.event==eventId).execute() 

170 if (waitlistUsers): 

171 createRsvpLog(event.id, f"Moved {waitlistUsers[0].user.fullName} from waitlist to RSVP.") 

172 (EventRsvp.update(rsvpWaitlist = False).where(EventRsvp.event_id == eventId, EventRsvp.user_id == username)).execute() 

173 return "" 

174 

175@admin_bp.route('/addVolunteersToEvent/<username>/<eventId>/isBanned', methods = ['GET']) 

176def isVolunteerBanned(username, eventId): 

177 return {"banned":1} if isBannedFromEvent(username, eventId) else {"banned":0} 

178 

179@admin_bp.route('/removeVolunteerFromEvent', methods = ['POST']) 

180def removeVolunteerFromEvent(): 

181 user = request.form.get('username') 

182 eventID = request.form.get('eventId') 

183 if g.current_user.isAdmin: 

184 userInRsvpTable = EventRsvp.select(EventRsvp, User).join(User).where(EventRsvp.user == user, EventRsvp.event==eventID).execute() 

185 if (userInRsvpTable): 

186 rsvpUser = userInRsvpTable[0] 

187 if rsvpUser.rsvpWaitlist: 

188 createRsvpLog(eventID, f"Removed {rsvpUser.user.fullName} from waitlist.") 

189 else: 

190 createRsvpLog(eventID, f"Removed {rsvpUser.user.fullName} from RSVP list.") 

191 (EventParticipant.delete().where(EventParticipant.user==user, EventParticipant.event==eventID)).execute() 

192 (EventRsvp.delete().where(EventRsvp.user==user, EventRsvp.event==eventID)).execute() 

193 flash("Volunteer successfully removed", "success") 

194 return "" 

195 

196@admin_bp.route('/addBackgroundCheck', methods = ['POST']) 

197def addBackgroundCheck(): 

198 if g.current_user.isCeltsAdmin: 

199 eventData = request.form 

200 user = eventData['user'] 

201 bgStatus = eventData['bgStatus'] 

202 type = eventData['bgType'] 

203 dateCompleted = eventData['bgDate'] 

204 addUserBackgroundCheck(user, type, bgStatus, dateCompleted) 

205 return "" 

206 

207@admin_bp.route('/deleteBackgroundCheck', methods = ['POST']) 

208def deleteBackgroundCheck(): 

209 if g.current_user.isCeltsAdmin: 

210 backgroundData = request.form 

211 bgToDelete = BackgroundCheck.get_by_id(backgroundData['bgID']) 

212 session["lastDeletedBgCheck"] = bgToDelete.id 

213 user = g.current_user 

214 deleteUserBackgroundCheck(bgToDelete.id, user) 

215 return "" 

216 

217@admin_bp.route('/updateProgramManager', methods=["POST"]) 

218def updateProgramManager(): 

219 if g.current_user.isCeltsAdmin: 

220 data =request.form 

221 username = User.get(User.username == data["username"]) 

222 program = Program.get_by_id(data['programId']) 

223 setProgramManager(data["username"], data["programId"], data["action"]) 

224 createActivityLog(f'{username.firstName} has been {data["action"]}ed as a Program Manager for {program.programName}') 

225 return "" 

226 else: 

227 abort(403) 

228 

229@admin_bp.route("/updatePhone", methods=["POST"]) 

230def updatePhone(): 

231 newinfo=request.form 

232 User.update(phoneNumber=newinfo["phoneNumber"]).where(User.username==newinfo["username"]).execute() 

233 return ""