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

155 statements  

« prev     ^ index     » next       coverage.py v7.10.2, created at 2026-04-29 19:36 +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 attendedUser = list(set([obj for obj in eventParticipantData if not obj.rsvpWaitlist])) 

117 attendedUserIds = {obj.user.id for obj in attendedUser} 

118 waitlistUser = [obj for obj in eventRsvpData if obj.rsvpWaitlist and obj.user.id not in attendedUserIds] 

119 rsvpUser = [obj for obj in eventRsvpData if not obj.rsvpWaitlist and obj.user.id not in attendedUserIds] 

120 

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

122 waitlistUser = waitlistUser, 

123 attendedUser = attendedUser, 

124 rsvpUser = rsvpUser, 

125 event = event) 

126 

127 

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

129def addVolunteer(eventId): 

130 event = Event.get_by_id(eventId) 

131 successfullyAddedVolunteer = False 

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

133 successfullyAddedVolunteer = False 

134 alreadyAddedList = [] 

135 addedSuccessfullyList = [] 

136 errorList = [] 

137 

138 for user in usernameList: 

139 userObj = User.get_by_id(user) 

140 successfullyAddedVolunteer = addPersonToEvent(userObj, event) 

141 if successfullyAddedVolunteer == "already in": 

142 alreadyAddedList.append(userObj.fullName) 

143 else: 

144 if successfullyAddedVolunteer: 

145 addedSuccessfullyList.append(userObj.fullName) 

146 else: 

147 errorList.append(userObj.fullName) 

148 

149 volunteers = "" 

150 if alreadyAddedList: 

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

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

153 

154 if addedSuccessfullyList: 

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

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

157 

158 if errorList: 

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

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

161 

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

163 return '' 

164 

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

166 

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

168def rsvpFromWaitlist(username, eventId): 

169 event = Event.get_by_id(eventId) 

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

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

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

173 if (waitlistUsers): 

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

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

176 return "" 

177 

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

179def isVolunteerBanned(username, eventId): 

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

181 

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

183def removeVolunteerFromEvent(): 

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

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

186 if g.current_user.isAdmin: 

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

188 if (userInRsvpTable): 

189 rsvpUser = userInRsvpTable[0] 

190 if rsvpUser.rsvpWaitlist: 

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

192 else: 

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

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

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

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

197 return "" 

198 

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

200def addBackgroundCheck(): 

201 if g.current_user.isCeltsAdmin: 

202 eventData = request.form 

203 user = eventData['user'] 

204 bgStatus = eventData['bgStatus'] 

205 type = eventData['bgType'] 

206 dateCompleted = eventData['bgDate'] 

207 addUserBackgroundCheck(user, type, bgStatus, dateCompleted) 

208 return "" 

209 

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

211def deleteBackgroundCheck(): 

212 if g.current_user.isCeltsAdmin: 

213 backgroundData = request.form 

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

215 session["lastDeletedBgCheck"] = bgToDelete.id 

216 user = g.current_user 

217 deleteUserBackgroundCheck(bgToDelete.id, user) 

218 return "" 

219 

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

221def updateProgramManager(): 

222 if g.current_user.isCeltsAdmin: 

223 data =request.form 

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

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

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

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

228 return "" 

229 else: 

230 abort(403) 

231 

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

233def updatePhone(): 

234 newinfo=request.form 

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

236 return ""