Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Selectively remove service transcript entry for banned programs #1176

Open
wants to merge 41 commits into
base: development
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 32 commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
a1c0e85
push branch
gahimbaref Feb 5, 2024
3c4eb34
add checkbox in modal
gahimbaref Feb 5, 2024
6c848b4
Added functionality for removing banned users from transcript, still …
Karina-Agliullova Feb 7, 2024
fa020dd
add function to handle checkbox
gahimbaref Feb 9, 2024
d6ee173
fix conflicts
gahimbaref Feb 9, 2024
4b1d9ee
Fixed merge conflict
Karina-Agliullova Feb 13, 2024
793e87b
add remove from transcript field
gahimbaref Feb 19, 2024
5394bdb
merge development
gahimbaref Feb 19, 2024
3205cf7
Fixed logic
Karina-Agliullova Feb 21, 2024
f17f91b
fix checkbox functionality, only show on banned modals
gahimbaref Feb 23, 2024
f9506eb
remove print
gahimbaref Feb 23, 2024
e9248e4
Fixing merge conflicts
Karina-Agliullova Mar 5, 2024
c69653f
Fixing merge conflicts on transcript.py
Karina-Agliullova Mar 5, 2024
b5e9366
Made changes to keep checkbox consistent
Karina-Agliullova Mar 6, 2024
6f4a093
Added tests, modififed code to fix consistency issue
Karina-Agliullova Mar 11, 2024
6177f68
fix merge conflicts
gahimbaref Mar 11, 2024
c43cfd5
readd code to show/hide checkbox
gahimbaref Mar 11, 2024
22a3dc0
Fixing the checkbox
Karina-Agliullova Mar 19, 2024
33dfc1a
Fixing the checkbox frontend
Karina-Agliullova Mar 19, 2024
3237498
fix merge conflicts
gahimbaref Mar 21, 2024
a6ad471
merge development
gahimbaref Apr 2, 2024
463c029
fix merge conflicts
gahimbaref Apr 2, 2024
413c8cf
reset to working version
gahimbaref Apr 2, 2024
8d2b452
fix the way programs appear
gahimbaref Apr 2, 2024
a886752
merge development
gahimbaref Apr 8, 2024
d337fe5
pushed some sample code
bledsoef Apr 8, 2024
001562d
fix checkbox status issue
gahimbaref Apr 9, 2024
652b51b
merge development
gahimbaref Apr 9, 2024
158fa2f
Removed redundant code
Karina-Agliullova Apr 9, 2024
464921b
try to fix unnecessary line changes
gahimbaref Apr 9, 2024
31ec70e
update branch
gahimbaref Apr 9, 2024
49a9261
Merge branch 'development' into serviceTEntry658
AndersonStettner Apr 10, 2024
ca7b7cf
rename function
gahimbaref Apr 15, 2024
9b04efb
use camelcase
gahimbaref Apr 15, 2024
6a3d3e2
fix capitalization of a variable
gahimbaref Apr 15, 2024
d968653
variable name fix
gahimbaref Apr 15, 2024
8fa706e
Merge branch 'development' into serviceTEntry658
bledsoef Apr 17, 2024
4693c03
Fixed the comments
Karina-Agliullova Apr 19, 2024
2d32488
Fixed comments for userProfile.js
Karina-Agliullova Apr 22, 2024
02069b6
use defaultdict for efficiency
gahimbaref Apr 22, 2024
bf06345
Merge branch 'development' into serviceTEntry658
AndersonStettner May 8, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
72 changes: 57 additions & 15 deletions app/controllers/main/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from peewee import JOIN
from http import cookies
from playhouse.shortcuts import model_to_dict
from flask import request, render_template, g, abort, flash, redirect, url_for
from flask import request, render_template, g, abort, flash, redirect, url_for,jsonify

from app.controllers.main import main_bp
from app import app
Expand Down Expand Up @@ -55,7 +55,7 @@ def landingPage():
.distinct()
.execute()) # Ensure only unique programs are included

return render_template("/main/landingPage.html",
return render_template("/main/landingPage.html",
managerProgramDict=managerProgramDict,
term=g.current_term,
programsWithEventsList=programsWithEventsList)
Expand All @@ -73,20 +73,20 @@ def events(selectedTerm, activeTab, programID):
if selectedTerm:
currentTerm = selectedTerm
currentTime = datetime.datetime.now()

listOfTerms = Term.select()
participantRSVP = EventRsvp.select(EventRsvp, Event).join(Event).where(EventRsvp.user == g.current_user)
rsvpedEventsID = [event.event.id for event in participantRSVP]

term = Term.get_by_id(currentTerm)
term = Term.get_by_id(currentTerm)

currentEventRsvpAmount = getEventRsvpCountsForTerm(term)
studentLedEvents = getStudentLedEvents(term)
countUpcomingStudentLedEvents = getUpcomingStudentLedCount(term, currentTime)
trainingEvents = getTrainingEvents(term, g.current_user)
bonnerEvents = getBonnerEvents(term)
otherEvents = getOtherEvents(term)

managersProgramDict = getManagerProgramDict(g.current_user)

return render_template("/events/event_list.html",
Expand Down Expand Up @@ -146,7 +146,7 @@ def viewUsersProfile(username):
ProgramBan.program == program,
ProgramBan.endDate > datetime.datetime.now()).execute())
userParticipatedTrainingEvents = getParticipationStatusForTrainings(program, [volunteer], g.current_term)
try:
try:
allTrainingsComplete = False not in [attended for event, attended in userParticipatedTrainingEvents[username]] # Did volunteer attend all events
except KeyError:
allTrainingsComplete = False
Expand Down Expand Up @@ -201,7 +201,7 @@ def emergencyContactInfo(username):
contactInfo=contactInfo,
readOnly=readOnly
)

elif request.method == 'POST':
if g.current_user.username != username:
abort(403)
Expand All @@ -210,8 +210,8 @@ def emergencyContactInfo(username):
if not rowsUpdated:
EmergencyContact.create(user = username, **request.form)
createAdminLog(f"{g.current_user} updated {username}'s emergency contact information.")
flash('Emergency contact information saved successfully!', 'success')
flash('Emergency contact information saved successfully!', 'success')

if request.args.get('action') == 'exit':
return redirect (f"/profile/{username}")
else:
Expand Down Expand Up @@ -243,7 +243,7 @@ def insuranceInfo(username):
if not rowsUpdated:
InsuranceInfo.create(user = username, **request.form)
createAdminLog(f"{g.current_user} updated {username}'s emergency contact information.")
flash('Insurance information saved successfully!', 'success')
flash('Insurance information saved successfully!', 'success')

if request.args.get('action') == 'exit':
return redirect (f"/profile/{username}")
Expand All @@ -254,7 +254,7 @@ def insuranceInfo(username):
def travelForm(username):
if not (g.current_user.username == username or g.current_user.isCeltsAdmin):
abort(403)

user = (User.select(User, EmergencyContact, InsuranceInfo)
.join(EmergencyContact, JOIN.LEFT_OUTER).switch()
.join(InsuranceInfo, JOIN.LEFT_OUTER)
Expand Down Expand Up @@ -449,6 +449,48 @@ def serviceTranscript(username):
startDate = startDate,
userData = user)

@main_bp.route('/profile/<username>/removeFromTranscript/<program_id>', methods=['GET'])
def checkRemoved(username, program_id):
gahimbaref marked this conversation as resolved.
Show resolved Hide resolved
# Check if the user is banned from the program
user = User.get_or_none(User.username == username)
if user is None:
abort(404)

try:
program_ban = ProgramBan.get((ProgramBan.program == program_id) & (ProgramBan.user == user))
# If the user is banned, check if it's marked for removal from transcript
if program_ban.removeFromTranscript:
gahimbaref marked this conversation as resolved.
Show resolved Hide resolved
return jsonify({'removedFromTranscript': True})
else:
return jsonify({'removedFromTranscript': False})
except ProgramBan.DoesNotExist:
return jsonify({'status': 'error', 'message': 'ProgramBan not found'})

@main_bp.route('/profile/<username>/updateTranscript/<program_id>', methods=['POST'])
def update_transcript(username, program_id):
# Check user permissions
user = User.get_or_none(User.username == username)
if user is None:
abort(404)
if user != g.current_user and not g.current_user.isAdmin:
abort(403)

# Get the data sent from the client-side JavaScript
data = request.json

# Retrieve removeFromTranscript value from the request data
removeFromTranscript = data.get('removeFromTranscript')

# Update the ProgramBan object matching the program_id and username
try:
program_ban = ProgramBan.get((ProgramBan.program == program_id) & (ProgramBan.user == user))
program_ban.removeFromTranscript = removeFromTranscript
program_ban.save()
gahimbaref marked this conversation as resolved.
Show resolved Hide resolved
return jsonify({'status': 'success'})
except ProgramBan.DoesNotExist:
return jsonify({'status': 'error', 'message': 'ProgramBan not found'})


@main_bp.route('/searchUser/<query>', methods = ['GET'])
def searchUser(query):

Expand All @@ -474,12 +516,12 @@ def getDietInfo():
dietaryInfo = request.form
user = dietaryInfo["user"]
dietInfo = dietaryInfo["dietInfo"]

if (g.current_user.username == user) or g.current_user.isAdmin:
updateDietInfo(user, dietInfo)
userInfo = User.get(User.username == user)
userInfo = User.get(User.username == user)
if len(dietInfo) > 0:
createAdminLog(f"Updated {userInfo.fullName}'s dietary restrictions to {dietInfo}.") if dietInfo.strip() else None
createAdminLog(f"Updated {userInfo.fullName}'s dietary restrictions to {dietInfo}.") if dietInfo.strip() else None
else:
createAdminLog(f"Deleted all {userInfo.fullName}'s dietary restrictions dietary restrictions.")

Expand Down
165 changes: 88 additions & 77 deletions app/logic/transcript.py
Original file line number Diff line number Diff line change
@@ -1,77 +1,88 @@
from peewee import fn

from app.models.course import Course
from app.models.courseParticipant import CourseParticipant
from app.models.program import Program
from app.models.courseInstructor import CourseInstructor
from app.models.user import User
from app.models.term import Term
from app.models.eventParticipant import EventParticipant
from app.models.event import Event

def getProgramTranscript(username):
"""
Returns a Program query object containing all the programs for
current user.
"""
# Add up hours earned in a term for each program they've participated in

EventData = (Event.select(Event, fn.SUM(EventParticipant.hoursEarned).alias("hoursEarned"))
.join(EventParticipant)
.where(EventParticipant.user == username)
.group_by(Event.program, Event.term)
.order_by(Event.term)
.having(fn.SUM(EventParticipant.hoursEarned > 0)))
transcriptData = {}
for event in EventData:
if event.program in transcriptData:
transcriptData[event.program].append([event.term.description, event.hoursEarned])
else:
transcriptData[event.program] = [[event.term.description, event.hoursEarned]]
return transcriptData

def getSlCourseTranscript(username):
"""
Returns a SLCourse query object containing all the training events for
current user.
"""

slCourses = (Course.select(Course, fn.SUM(CourseParticipant.hoursEarned).alias("hoursEarned"))
.join(CourseParticipant, on=(Course.id == CourseParticipant.course))
.where(CourseParticipant.user == username)
.group_by(Course.courseName, Course.term))

return slCourses

def getTotalHours(username):
"""
Get the toal hours from events and courses combined.
"""
eventHours = (EventParticipant.select(fn.SUM(EventParticipant.hoursEarned))
.where(EventParticipant.user == username)).scalar()
courseHours = (CourseParticipant.select(fn.SUM(CourseParticipant.hoursEarned))
.where(CourseParticipant.user == username)).scalar()

allHours = {"totalEventHours": (eventHours or 0),
"totalCourseHours": (courseHours or 0),
"totalHours": (eventHours or 0) + (courseHours or 0)}
return allHours

def getStartYear(username):
"""
Returns the users start term for participation in the CELTS organization
"""

startDate = (EventParticipant.select(Term.year)
.join(Event)
.join(Term).where(EventParticipant.user == username)
+ CourseParticipant.select(Term.year)
.join(Course)
.join(Term)
.where(CourseParticipant.user == username)
).order_by(Event.term.year).first()

if startDate:
return startDate.event.term.year

return "N/A"
from peewee import fn

from app.models.course import Course
from app.models.courseParticipant import CourseParticipant
from app.models.program import Program
from app.models.programBan import ProgramBan
from app.models.courseInstructor import CourseInstructor
from app.models.user import User
from app.models.term import Term
from app.models.eventParticipant import EventParticipant
from app.models.event import Event

def getProgramTranscript(username):
"""
Returns a Program query object containing all the programs for
the current user.
"""
# Add up hours earned in a term for each program they've participated in

EventData = (Event.select(Event, fn.SUM(EventParticipant.hoursEarned).alias("hoursEarned"))
.join(EventParticipant)
.where(EventParticipant.user == username)
.group_by(Event.program, Event.term)
.order_by(Event.term)
.having(fn.SUM(EventParticipant.hoursEarned > 0)))

# Fetch all ProgramBan objects for the user
BannedProgramsForParticipant = ProgramBan.select().where(ProgramBan.user == username)

gahimbaref marked this conversation as resolved.
Show resolved Hide resolved
# Create a set of program IDs to remove from transcript
programsToremoveFromTranscript = {bannedProgram.program_id for bannedProgram in BannedProgramsForParticipant if bannedProgram.removeFromTranscript}
transcriptData = {}
gahimbaref marked this conversation as resolved.
Show resolved Hide resolved

# Iterate through EventData and populate transcriptData
for event in EventData:
if event.program.id not in programsToremoveFromTranscript: # Check if program is not in programs to be removed from transcript
if event.program in transcriptData:
transcriptData[event.program].append([event.term.description, event.hoursEarned])
else:
transcriptData[event.program] = [[event.term.description, event.hoursEarned]]

gahimbaref marked this conversation as resolved.
Show resolved Hide resolved
return transcriptData

gahimbaref marked this conversation as resolved.
Show resolved Hide resolved
def getSlCourseTranscript(username):
"""
Returns a SLCourse query object containing all the training events for
current user.
"""

slCourses = (Course.select(Course, fn.SUM(CourseParticipant.hoursEarned).alias("hoursEarned"))
.join(CourseParticipant, on=(Course.id == CourseParticipant.course))
.where(CourseParticipant.user == username)
.group_by(Course.courseName, Course.term))

return slCourses

def getTotalHours(username):
"""
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We talked about this in person but I noticed that when programs are removed from the transcript, their hours are still displayed in the sum total of hours at the bottom of the page. The culprit is this function. You just need to filter out the programs that are set to be removed from the transcript.

Get the toal hours from events and courses combined.
"""
eventHours = (EventParticipant.select(fn.SUM(EventParticipant.hoursEarned))
.where(EventParticipant.user == username)).scalar()
courseHours = (CourseParticipant.select(fn.SUM(CourseParticipant.hoursEarned))
.where(CourseParticipant.user == username)).scalar()

allHours = {"totalEventHours": (eventHours or 0),
"totalCourseHours": (courseHours or 0),
"totalHours": (eventHours or 0) + (courseHours or 0)}
return allHours

def getStartYear(username):
"""
Returns the users start term for participation in the CELTS organization
"""

startDate = (EventParticipant.select(Term.year)
.join(Event)
.join(Term).where(EventParticipant.user == username)
+ CourseParticipant.select(Term.year)
.join(Course)
.join(Term)
.where(CourseParticipant.user == username)
).order_by(Event.term.year).first()

if startDate:
return startDate.event.term.year

return "N/A"
1 change: 1 addition & 0 deletions app/logic/users.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from app.models.note import Note
from app.models.user import User
from app.models.profileNote import ProfileNote
from app.models.programBan import ProgramBan
from app.models.backgroundCheck import BackgroundCheck
from app.models.backgroundCheckType import BackgroundCheckType
from app.logic.volunteers import addUserBackgroundCheck
Expand Down
3 changes: 3 additions & 0 deletions app/models/programBan.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,6 @@ class ProgramBan(baseModel):
endDate = DateField(null=True)
banNote = ForeignKeyField(Note, null=False)
unbanNote = ForeignKeyField(Note, null=True)
removeFromTranscript = BooleanField(default=False)