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