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

153 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2025-07-22 20:03 +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 

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

120 waitlistUser = waitlistUser, 

121 attendedUser= eventParticipantData, 

122 rsvpUser= rsvpUser, 

123 event = event) 

124 

125 

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

127def addVolunteer(eventId): 

128 event = Event.get_by_id(eventId) 

129 successfullyAddedVolunteer = False 

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

131 successfullyAddedVolunteer = False 

132 alreadyAddedList = [] 

133 addedSuccessfullyList = [] 

134 errorList = [] 

135 

136 for user in usernameList: 

137 userObj = User.get_by_id(user) 

138 successfullyAddedVolunteer = addPersonToEvent(userObj, event) 

139 if successfullyAddedVolunteer == "already in": 

140 alreadyAddedList.append(userObj.fullName) 

141 else: 

142 if successfullyAddedVolunteer: 

143 addedSuccessfullyList.append(userObj.fullName) 

144 else: 

145 errorList.append(userObj.fullName) 

146 

147 volunteers = "" 

148 if alreadyAddedList: 

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

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

151 

152 if addedSuccessfullyList: 

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

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

155 

156 if errorList: 

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

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

159 

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

161 return '' 

162 

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

164 

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

166def rsvpFromWaitlist(username, eventId): 

167 event = Event.get_by_id(eventId) 

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

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

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

171 if (waitlistUsers): 

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

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

174 return "" 

175 

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

177def isVolunteerBanned(username, eventId): 

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

179 

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

181def removeVolunteerFromEvent(): 

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

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

184 if g.current_user.isAdmin: 

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

186 if (userInRsvpTable): 

187 rsvpUser = userInRsvpTable[0] 

188 if rsvpUser.rsvpWaitlist: 

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

190 else: 

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

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

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

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

195 return "" 

196 

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

198def addBackgroundCheck(): 

199 if g.current_user.isCeltsAdmin: 

200 eventData = request.form 

201 user = eventData['user'] 

202 bgStatus = eventData['bgStatus'] 

203 type = eventData['bgType'] 

204 dateCompleted = eventData['bgDate'] 

205 addUserBackgroundCheck(user, type, bgStatus, dateCompleted) 

206 return "" 

207 

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

209def deleteBackgroundCheck(): 

210 if g.current_user.isCeltsAdmin: 

211 backgroundData = request.form 

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

213 session["lastDeletedBgCheck"] = bgToDelete.id 

214 user = g.current_user 

215 deleteUserBackgroundCheck(bgToDelete.id, user) 

216 return "" 

217 

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

219def updateProgramManager(): 

220 if g.current_user.isCeltsAdmin: 

221 data =request.form 

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

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

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

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

226 return "" 

227 else: 

228 abort(403) 

229 

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

231def updatePhone(): 

232 newinfo=request.form 

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

234 return ""