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

154 statements  

« prev     ^ index     » next       coverage.py v7.10.2, created at 2025-09-02 19:10 +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.participants import updateEventVolunteers, addUserBackgroundCheck, setProgramManager, deleteUserBackgroundCheck 

14from app.logic.participants import trainedParticipants, addParticipantToEvent, getParticipationStatusForTrainings, sortParticipants 

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 

20from app.logic.sharedLogic import getEventLengthInHours 

21 

22 

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

24def getVolunteers(query): 

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

26 

27 return json.dumps(searchUsers(query)) 

28 

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

30def manageVolunteersPage(eventID): 

31 """ 

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

33 

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

35 updateEventVolunteers on the form. 

36 

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

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

39 renders the manageVolunteers.html template. 

40 """ 

41 try: 

42 event = Event.get_by_id(eventID) 

43 except DoesNotExist as e: 

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

45 abort(404) 

46 

47 # ------------ POST request ------------ 

48 if request.method == "POST": 

49 volunteerUpdated = updateEventVolunteers(request.form) 

50 

51 # error handling depending on the boolean returned from updateEventVolunteers 

52 if volunteerUpdated: 

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

54 else: 

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

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

57 

58 # ------------ GET request ------------ 

59 elif request.method == "GET": 

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

61 abort(403) 

62 

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

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

65 

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

67 

68 eventNonAttendedData, eventWaitlistData, eventVolunteerData, eventVolunteers = sortParticipants(event, False) 

69 

70 allRelevantUsers = list(set(participant.user for participant in (eventVolunteers + eventNonAttendedData + eventWaitlistData + eventVolunteerData))) 

71 # ----------- Get miscellaneous data ----------- 

72 

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

74 

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

76 

77 repeatingVolunteers = getPreviousSeriesEventData(event.seriesId) 

78 

79 currentRsvpAmount = getEventRsvpCount(event.id) 

80 

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

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

83 eventVolunteerData = eventVolunteerData, 

84 eventNonAttendedData = eventNonAttendedData, 

85 eventWaitlistData = eventWaitlistData, 

86 eventLength = eventLengthInHours, 

87 event = event, 

88 repeatingVolunteers = repeatingVolunteers, 

89 bannedUsersForProgram = bannedUsersForProgram, 

90 trainedParticipantsForProgramAndTerm = trainedParticipantsForProgramAndTerm, 

91 participationStatusForTrainings = participationStatusForTrainings, 

92 currentRsvpAmount = currentRsvpAmount) 

93 

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

95def volunteerDetailsPage(eventID): 

96 try: 

97 event = Event.get_by_id(eventID) 

98 except DoesNotExist as e: 

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

100 abort(404) 

101 

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

103 abort(403) 

104 

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

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

107 .switch(EventRsvp) 

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

109 .where(EventRsvp.event==event)) 

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

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

112 .switch(EventParticipant) 

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

114 .where(EventParticipant.event==event)) 

115 

116 

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

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

119 

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

121 waitlistUser = waitlistUser, 

122 attendedUser= eventParticipantData, 

123 rsvpUser= rsvpUser, 

124 event = event) 

125 

126 

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

128def addVolunteer(eventId): 

129 event = Event.get_by_id(eventId) 

130 successfullyAddedVolunteer = False 

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

132 successfullyAddedVolunteer = False 

133 alreadyAddedList = [] 

134 addedSuccessfullyList = [] 

135 errorList = [] 

136 

137 for user in usernameList: 

138 userObj = User.get_by_id(user) 

139 successfullyAddedVolunteer = addParticipantToEvent(userObj, event, False) 

140 if successfullyAddedVolunteer == "already in": 

141 alreadyAddedList.append(userObj.fullName) 

142 else: 

143 if successfullyAddedVolunteer: 

144 addedSuccessfullyList.append(userObj.fullName) 

145 else: 

146 errorList.append(userObj.fullName) 

147 

148 volunteers = "" 

149 if alreadyAddedList: 

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

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

152 

153 if addedSuccessfullyList: 

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

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

156 

157 if errorList: 

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

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

160 

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

162 return '' 

163 

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

165 

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

167def rsvpFromWaitlist(username, eventId): 

168 event = Event.get_by_id(eventId) 

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

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

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

172 if (waitlistUsers): 

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

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

175 return "" 

176 

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

178def isVolunteerBanned(username, eventId): 

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

180 

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

182def removeVolunteerFromEvent(): 

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

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

185 if g.current_user.isAdmin: 

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

187 if (userInRsvpTable): 

188 rsvpUser = userInRsvpTable[0] 

189 if rsvpUser.rsvpWaitlist: 

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

191 else: 

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

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

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

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

196 return "" 

197 

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

199def addBackgroundCheck(): 

200 if g.current_user.isCeltsAdmin: 

201 eventData = request.form 

202 user = eventData['user'] 

203 bgStatus = eventData['bgStatus'] 

204 type = eventData['bgType'] 

205 dateCompleted = eventData['bgDate'] 

206 addUserBackgroundCheck(user, type, bgStatus, dateCompleted) 

207 return "" 

208 

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

210def deleteBackgroundCheck(): 

211 if g.current_user.isCeltsAdmin: 

212 backgroundData = request.form 

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

214 session["lastDeletedBgCheck"] = bgToDelete.id 

215 user = g.current_user 

216 deleteUserBackgroundCheck(bgToDelete.id, user) 

217 return "" 

218 

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

220def updateProgramManager(): 

221 if g.current_user.isCeltsAdmin: 

222 data =request.form 

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

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

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

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

227 return "" 

228 else: 

229 abort(403) 

230 

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

232def updatePhone(): 

233 newinfo=request.form 

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

235 return ""