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
« 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
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'''
26 return json.dumps(searchUsers(query))
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.
33 POST: updates the event participants for a particular event by calling
34 updateEventParticipants on the form.
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)
46 # ------------ POST request ------------
47 if request.method == "POST":
48 volunteerUpdated = updateEventParticipants(request.form)
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))
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)
62 # ------- Grab the different lists of participants -------
63 trainedParticipantsForProgramAndTerm = trainedParticipants(event.program, event.term)
65 bannedUsersForProgram = [bannedUser.user for bannedUser in getBannedUsers(event.program)]
67 eventNonAttendedData, eventWaitlistData, eventVolunteerData, eventParticipants = sortParticipantsByStatus(event)
69 allRelevantUsers = list(set(participant.user for participant in (eventParticipants + eventNonAttendedData + eventWaitlistData + eventVolunteerData)))
70 # ----------- Get miscellaneous data -----------
72 participationStatusForTrainings = getParticipationStatusForTrainings(event.program, allRelevantUsers, event.term)
74 eventLengthInHours = getEventLengthInHours(event.timeStart, event.timeEnd, event.startDate)
76 repeatingVolunteers = getPreviousSeriesEventData(event.seriesId)
78 currentRsvpAmount = getEventRsvpCount(event.id)
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)
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)
101 if not (g.current_user.isCeltsAdmin or (g.current_user.isCeltsStudentStaff and g.current_user.isProgramManagerForEvent(event))):
102 abort(403)
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))
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)
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 = []
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)
146 volunteers = ""
147 if alreadyAddedList:
148 volunteers = ", ".join(vol for vol in alreadyAddedList)
149 flash(f"{volunteers} was already added to this event.", "warning")
151 if addedSuccessfullyList:
152 volunteers = ", ".join(vol for vol in addedSuccessfullyList)
153 flash(f"{volunteers} added successfully.", "success")
155 if errorList:
156 volunteers = ", ".join(vol for vol in errorList)
157 flash(f"Error when adding {volunteers} to event.", "danger")
159 if 'ajax' in request.form and request.form['ajax']:
160 return ''
162 return redirect(url_for('admin.manageVolunteersPage', eventID = eventId))
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 ""
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}
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 ""
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 ""
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 ""
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)
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 ""