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
« 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
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 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]
121 return render_template("/events/volunteerDetails.html",
122 waitlistUser = waitlistUser,
123 attendedUser = attendedUser,
124 rsvpUser = rsvpUser,
125 event = event)
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 = []
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)
149 volunteers = ""
150 if alreadyAddedList:
151 volunteers = ", ".join(vol for vol in alreadyAddedList)
152 flash(f"{volunteers} was already added to this event.", "warning")
154 if addedSuccessfullyList:
155 volunteers = ", ".join(vol for vol in addedSuccessfullyList)
156 flash(f"{volunteers} added successfully.", "success")
158 if errorList:
159 volunteers = ", ".join(vol for vol in errorList)
160 flash(f"Error when adding {volunteers} to event.", "danger")
162 if 'ajax' in request.form and request.form['ajax']:
163 return ''
165 return redirect(url_for('admin.manageVolunteersPage', eventID = eventId))
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 ""
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}
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 ""
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 ""
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 ""
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)
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 ""