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
« 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
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'''
27 return json.dumps(searchUsers(query))
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.
34 POST: updates the event participants for a particular event by calling
35 updateEventVolunteers on the form.
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)
47 # ------------ POST request ------------
48 if request.method == "POST":
49 volunteerUpdated = updateEventVolunteers(request.form)
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))
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)
63 # ------- Grab the different lists of participants -------
64 trainedParticipantsForProgramAndTerm = trainedParticipants(event.program, event.term)
66 bannedUsersForProgram = [bannedUser.user for bannedUser in getBannedUsers(event.program)]
68 eventNonAttendedData, eventWaitlistData, eventVolunteerData, eventVolunteers = sortParticipants(event, False)
70 allRelevantUsers = list(set(participant.user for participant in (eventVolunteers + eventNonAttendedData + eventWaitlistData + eventVolunteerData)))
71 # ----------- Get miscellaneous data -----------
73 participationStatusForTrainings = getParticipationStatusForTrainings(event.program, allRelevantUsers, event.term)
75 eventLengthInHours = getEventLengthInHours(event.timeStart, event.timeEnd, event.startDate)
77 repeatingVolunteers = getPreviousSeriesEventData(event.seriesId)
79 currentRsvpAmount = getEventRsvpCount(event.id)
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)
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)
102 if not (g.current_user.isCeltsAdmin or (g.current_user.isCeltsStudentStaff and g.current_user.isProgramManagerForEvent(event))):
103 abort(403)
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))
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 ]))
120 return render_template("/events/volunteerDetails.html",
121 waitlistUser = waitlistUser,
122 attendedUser= eventParticipantData,
123 rsvpUser= rsvpUser,
124 event = event)
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 = []
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)
148 volunteers = ""
149 if alreadyAddedList:
150 volunteers = ", ".join(vol for vol in alreadyAddedList)
151 flash(f"{volunteers} was already added to this event.", "warning")
153 if addedSuccessfullyList:
154 volunteers = ", ".join(vol for vol in addedSuccessfullyList)
155 flash(f"{volunteers} added successfully.", "success")
157 if errorList:
158 volunteers = ", ".join(vol for vol in errorList)
159 flash(f"Error when adding {volunteers} to event.", "danger")
161 if 'ajax' in request.form and request.form['ajax']:
162 return ''
164 return redirect(url_for('admin.manageVolunteersPage', eventID = eventId))
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 ""
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}
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 ""
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 ""
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 ""
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)
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 ""