Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
113 commits
Select commit Hold shift + click to select a range
9fbcccf
We created the back button for create event tab pages
DanielRukwasha Jun 18, 2026
9f32827
Back button added to student search and create event
DanielRukwasha Jun 18, 2026
edd1c0a
back button fix
DanielRukwasha Jun 18, 2026
0cbe105
Back button centered
DanielRukwasha Jun 18, 2026
62be9a5
Merge branch 'development' into daniel_back_buttom
MImran2002 Jun 18, 2026
27c2eb0
Fix back button: replace javascript href with explicit routes, center…
DanielRukwasha Jun 19, 2026
f1825cd
Remove btn-sm from back button to match save button size
DanielRukwasha Jun 19, 2026
0c03375
Add CCE Minor Note tag to user profile Notes section
munsakad Jun 19, 2026
3702f32
Show back button on expired and incomplete events
DanielRukwasha Jun 22, 2026
e640625
Merge branch 'development' into daniel_back_buttom
MImran2002 Jun 22, 2026
e3ce770
Merge branch 'development' into dee_and_bright_CCE_Minor_Note_feature
MImran2002 Jun 23, 2026
3cac955
Merge branch 'development' into daniel_back_buttom
MImran2002 Jun 23, 2026
f4e3773
Removed of back button on create event
DanielRukwasha Jun 23, 2026
63e72f3
Merge branch 'daniel_back_buttom' of https://github.com/BCStudentSoft…
DanielRukwasha Jun 23, 2026
05215b0
error fixed
nahom70 Jun 23, 2026
b813b54
adjusted code position of back button on userprofile
nahom70 Jun 23, 2026
2b6ab23
Merge branch 'development' into dee_and_bright_CCE_Minor_Note_feature
MImran2002 Jul 6, 2026
2587f49
solved issue service hours not being displayed in participation history
conwelld Jul 16, 2026
2d0f90b
fixed pr request changes
conwelld Jul 16, 2026
a08d6f3
fixed pr changes
conwelld Jul 17, 2026
c484dcb
Merge branch 'development' into display_service_hours
MImran2002 Jul 20, 2026
662b15d
removed the laborhisotry dict not being changed multiple times becaus…
MImran2002 Jul 22, 2026
1ac554a
any wild card and any prefix and ambiguity problem in search is fix
MImran2002 Jul 27, 2026
b75ca4e
access controlled added and as neillz is not longer listed as iscelts…
MImran2002 Jul 27, 2026
dfd1031
test case added ascending order fixed
MImran2002 Jul 27, 2026
b064440
remove print statment
MImran2002 Jul 27, 2026
6bfc7fc
Added CCE Minor support to profile notes
brightfietsop-ux Aug 3, 2026
34078cb
Changed wording of Manage Proposals to My Proposals if the user is a …
ACBerea Jul 16, 2026
eed0397
Fixed edge case when switching profiles between students causing the …
ACBerea Jul 16, 2026
7b589dc
Fixed redunancy in checks user identity checks when changing Manage P…
ACBerea Jul 16, 2026
829e1f6
Separate zero-hour events into Education and Training section
BhushanSah Jul 16, 2026
b98d30c
Initial commit
BhushanSah Jul 16, 2026
f92d2cc
Changed the dropdown to individual buttons
BhushanSah Jul 16, 2026
09e51c5
Removed the id categoryDropdown
BhushanSah Jul 16, 2026
34e5421
changed the title of 'Edit Volunteer Information' -> 'Edit Personal...'
fritzj2 Jul 16, 2026
6781a43
Fix volunteer spreadsheet tests for term and senior results
BhushanSah Jul 17, 2026
b2c8354
Updated profile note tests for CCE Minor support hence fixing the tes…
brightfietsop-ux Aug 3, 2026
f9c1f31
Merge branch 'development' into dee_and_bright_CCE_Minor_Note_feature
brightfietsop-ux Aug 3, 2026
ebe595f
refactored the page
brightfietsop-ux Aug 4, 2026
228b943
added some try except cases and user check before a note is added
brightfietsop-ux Aug 4, 2026
4f2a9bd
fixed the broken test
brightfietsop-ux Aug 4, 2026
4b9c91a
reformatted the code
brightfietsop-ux Aug 4, 2026
89f5edd
fixed the format of the code
brightfietsop-ux Aug 4, 2026
36cd7d0
fixed the layout of the page
brightfietsop-ux Aug 4, 2026
c7099d0
Revert local database reset changes
brightfietsop-ux Aug 4, 2026
717d933
Merge branch 'development' into dee_and_bright_CCE_Minor_Note_feature
MImran2002 Aug 4, 2026
190c30e
Address profile note review feedback and restore flash messages
brightfietsop-ux Aug 4, 2026
0f42d62
pulled origin into my branch
brightfietsop-ux Aug 4, 2026
e903a81
resolved merge conflict
brightfietsop-ux Aug 4, 2026
746ca30
fixed the bug under the bonner note Accordion and the made sure the t…
brightfietsop-ux Aug 5, 2026
ca1b620
fixed a bug on the bonner accordion
brightfietsop-ux Aug 5, 2026
cfef289
fixed exception cases
brightfietsop-ux Aug 5, 2026
42add87
added badges nest to the notes
brightfietsop-ux Aug 6, 2026
6498e4e
added a badge to the notes
brightfietsop-ux Aug 6, 2026
13c9d6e
changed the colors of the badges
brightfietsop-ux Aug 6, 2026
9adaa96
resolved merge conflicts brought in from developmemt
brightfietsop-ux Aug 7, 2026
4e1c344
fixed a wrong import statement
brightfietsop-ux Aug 7, 2026
338c62b
Merge branch 'development' into CELTSLaborAPI
MImran2002 Aug 13, 2026
bbddd85
search query click fix, search query prefix, suffix fixed, report dow…
MImran2002 Aug 13, 2026
2fac600
test spreadsheet labor attendance fixed
MImran2002 Aug 24, 2026
4cbbe15
Merge branch 'development' into CELTSLaborAPI
MImran2002 Aug 24, 2026
012998d
graduation filter added for rosters
MImran2002 Aug 25, 2026
c862bed
Interested students added now only shows users who are current studne…
MImran2002 Aug 26, 2026
3ba3dbe
Merge branch 'development' into daniel_back_buttom
fritzj2 Aug 27, 2026
5dd2d33
fixed back button centering on the userProfile
fritzj2 Aug 27, 2026
4d8920c
Merge branch 'development' into daniel_back_buttom
MImran2002 Aug 27, 2026
0f588af
implemented peewee query for term instead of cache
MImran2002 Aug 27, 2026
77ba60c
updated g.current_term
MImran2002 Aug 27, 2026
2554dee
remove exception and update comment
MImran2002 Aug 27, 2026
3ecd2f7
Merge branch 'development' into dee_and_bright_CCE_Minor_Note_feature
bakobagassas Aug 28, 2026
485455b
altered the profilenote table to include the new CCEminor note column
bakobagassas Aug 28, 2026
eab33ca
Delete tmp-backups/2026-08-05-backup.sql
MImran2002 Sep 1, 2026
a974af2
Delete tmp-backups/2026-08-13-backup.sql
MImran2002 Sep 1, 2026
fa1f475
imported all
bakobagassas Sep 1, 2026
464faa0
ACT added as part of AVT
MImran2002 Sep 2, 2026
55058cb
added the back button to the event view page
fritzj2 Sep 3, 2026
0e2bf82
bug fixed for the rosters marking attended when rsvp
MImran2002 Sep 3, 2026
2e0bbb2
spreadsheet tests from Celts API
bakobagassas Sep 3, 2026
a26aa8c
Merge branch 'development' into CELTSLaborAPI
bakobagassas Sep 3, 2026
691f0e6
spreadsheet
bakobagassas Sep 4, 2026
6e67fbe
test cases updated
MImran2002 Sep 4, 2026
0088e56
Merge pull request #1737 from BCStudentSoftwareDevTeam/dee_and_bright…
MImran2002 Sep 4, 2026
65bda24
Merge branch 'development' into rosterGraduatedHF
MImran2002 Sep 4, 2026
2ec9479
Merge branch 'development' into termCacheHF
MImran2002 Sep 4, 2026
64b8183
Merge branch 'development' into rosterTrainingsHF
MImran2002 Sep 4, 2026
8909a21
test case implemented
MImran2002 Sep 4, 2026
336f7b9
resolve merge conflict
MImran2002 Sep 4, 2026
517514b
resolve merge conflict
MImran2002 Sep 4, 2026
249eee3
Merge branch 'development' into CELTSLaborAPI
MImran2002 Sep 4, 2026
9d9de06
Merge branch 'development' into daniel_back_buttom
fritzj2 Sep 4, 2026
336f7af
search making it more flexible and considered edge case at the same t…
MImran2002 Sep 4, 2026
43a2ac0
Merge branch 'CELTSLaborAPI' of https://github.com/BCStudentSoftwareD…
MImran2002 Sep 4, 2026
e80df1f
test fix
MImran2002 Sep 4, 2026
d878bda
changes made
MImran2002 Sep 7, 2026
2624bb3
Merge pull request #1802 from BCStudentSoftwareDevTeam/rosterTrainingsHF
BrianRamsay Sep 8, 2026
c65a5bf
Merge branch 'development' into termCacheHF
BrianRamsay Sep 8, 2026
1a91204
Merge branch 'development' into rosterGraduatedHF
BrianRamsay Sep 8, 2026
2a1ce71
Merge pull request #1801 from BCStudentSoftwareDevTeam/termCacheHF
BrianRamsay Sep 8, 2026
30538dc
Merge branch 'development' into rosterGraduatedHF
BrianRamsay Sep 8, 2026
6794048
Merge pull request #1799 from BCStudentSoftwareDevTeam/rosterGraduatedHF
BrianRamsay Sep 8, 2026
53602a7
Show service hours only for isService events
BrianRamsay Sep 9, 2026
49641e9
Resolve merge conflicts
BrianRamsay Sep 9, 2026
8c66155
Included hours earned in the output of participated events function
BrianRamsay Sep 9, 2026
6bbefec
Fix service hour display bug on profile
BrianRamsay Sep 9, 2026
b9d9635
Remove unnecessary query
BrianRamsay Sep 9, 2026
8ca38c5
Merge pull request #1765 from BCStudentSoftwareDevTeam/display_servic…
BrianRamsay Sep 9, 2026
7fd8312
Simplify logic in displaying CELTS labor positions
BrianRamsay Sep 9, 2026
b27eddf
Merge branch 'development' into CELTSLaborAPI
BrianRamsay Sep 9, 2026
d8b2d68
Merge pull request #1771 from BCStudentSoftwareDevTeam/CELTSLaborAPI
BrianRamsay Sep 9, 2026
cc133f8
Merge branch 'production' into development
BrianRamsay Sep 9, 2026
349a672
Adding missing </div> from somewhere
BrianRamsay Sep 9, 2026
9509aa2
Merge pull request #1735 from BCStudentSoftwareDevTeam/daniel_back_bu…
BrianRamsay Sep 9, 2026
f1b05d9
Move note tags to note content
BrianRamsay Sep 10, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 2 additions & 7 deletions app/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,13 +77,8 @@ def load_user():
from app.logic.loginManager import getCurrentTerm
@app.before_request
def load_currentTerm():
# An exception handles both current_term not being set and a mismatch between models
try:
g.current_term = dict_to_model(Term, session['current_term'])
except Exception as e:
term = getCurrentTerm()
session['current_term'] = model_to_dict(term)
g.current_term = term
# Query the current term from the database on each request to avoid stale session data
g.current_term = getCurrentTerm()

import datetime
@app.before_request
Expand Down
2 changes: 2 additions & 0 deletions app/config/default.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ support_email_contact: "support@bereacollege.onmicrosoft.com"
show_queries: True
test_entry: "Default"

lsf_url: "USE local-override.yml"

db:
name: "celts"
host: "db"
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/admin/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,7 @@ def eventDisplay(eventId):

currentEventRsvpAmount = getEventRsvpCount(event.id)

userParticipatedTrainingEvents = getParticipationStatusForTrainings(eventData['program'], [g.current_user], g.current_term)
userParticipatedTrainingEvents = getParticipationStatusForTrainings(eventData['program'], [g.current_user], g.current_term, includeFutureEvents = False)

return render_template("events/eventView.html",
eventData=eventData,
Expand Down
41 changes: 26 additions & 15 deletions app/controllers/main/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
from app.models.programManager import ProgramManager
from app.models.backgroundCheck import BackgroundCheck
from app.models.emergencyContact import EmergencyContact
from app.models.eventParticipant import EventParticipant
from app.models.courseInstructor import CourseInstructor
from app.models.backgroundCheckType import BackgroundCheckType

Expand All @@ -39,7 +38,7 @@
from app.logic.landingPage import getManagerProgramDict, getActiveEventTab
from app.logic.minor import toggleMinorInterest, declareMinorInterest, getCommunityEngagementByTerm, getEngagementTotal
from app.logic.participants import hasGoneToTraining, unattendedRequiredEvents, getParticipationStatusForTrainings, checkUserRsvp, addPersonToEvent
from app.logic.users import addUserInterest, isBannedFromEvent, removeUserInterest, banUser, unbanUser, isEligibleForProgram, getUserBGCheckHistory, addProfileNote, deleteProfileNote, updateDietInfo, trainedParticipants
from app.logic.users import *

@main_bp.route('/logout', methods=['GET'])
def redirectToLogout():
Expand Down Expand Up @@ -234,8 +233,8 @@ def viewUsersProfile(username):
managersProgramDict = getManagerProgramDict(g.current_user)
managersList = [id[1] for id in managersProgramDict.items()]
totalSustainedEngagements = getEngagementTotal(getCommunityEngagementByTerm(volunteer))
handbookOverdue = getHandbookStatus(volunteer)

handbookOverdue = getHandbookStatus(volunteer)
training = hasGoneToTraining(g.current_user, g.current_term)

return render_template ("/main/userProfile.html",
Expand Down Expand Up @@ -390,22 +389,34 @@ def eventTravelForm(eventID):
userList = userList,
)

@main_bp.route('/profile/addNote', methods=['POST'])
@main_bp.route("/profile/addNote", methods=["POST"])
def addNote():
"""
This function adds a note to the user's profile.
"""
postData = request.form
try:
note = addProfileNote(postData["visibility"], postData["bonner"] == "yes", postData["noteTextbox"], postData["username"])
noteData = getProfileNoteData(
request.form,
includeUsername=True,
)
addProfileNote(**noteData)
flash("Successfully added profile note", "success")
return redirect(url_for("main.viewUsersProfile", username=postData["username"]))
except Exception as e:
print("Error adding note", e)
except Exception as error:
print("Error adding profile note:", error)
flash("Failed to add profile note", "danger")
return "Failed to add profile note", 500


return str(error), 500
return "success"
@main_bp.route("/<username>/editNote", methods=["POST"])
def editProfileNote(username):
try:
noteData = getProfileNoteData( request.form, includeId=True, )
profileNote = ProfileNote.get_by_id(noteData["profileNoteID"] )
if (profileNote.user.username != username or (profileNote.note.createdBy != g.current_user and not g.current_user.isCeltsAdmin) ):
abort(403)
updateProfileNote(**noteData)
flash("Successfully updated profile note", "success")
except Exception as error:
print("Error updating profile note:", error)
flash("Failed to update profile note", "danger")
return str(error), 500
return "success"
@main_bp.route('/<username>/deleteNote', methods=['POST'])
def deleteNote(username):
"""
Expand Down
3 changes: 3 additions & 0 deletions app/controllers/minor/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ def viewCceMinor(username):
"""
Load minor management page with community engagements and summer experience
"""
if not (g.current_user.isAdmin or g.current_user.username == username or g.current_user.isCeltsStudentStaff):
return abort(403)

sustainedEngagementByTerm = getCommunityEngagementByTerm(username)

activeTab = request.args.get("tab", "sustainedCommunityEngagements")
Expand Down
20 changes: 11 additions & 9 deletions app/logic/celtsLabor.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,13 +97,16 @@ def refreshCeltsLaborRecords(laborDict):
for positionTitle, termNames in value.items():
for term in termNames:
termTableMatch = Term.select()
if term[0].isalpha():
isAcademicYear = False

if term[0].isalpha(): # Fall, Spring, Summer
termTableMatch = termTableMatch.where(Term.description == term)
else:
else: # e.g., 2025-2026
termTableMatch = termTableMatch.where(Term.academicYear == term, Term.description % "Fall%")
isAcademicYear = True

try:
laborTerm = termTableMatch.get()
isAcademicYear = not laborTerm.isSummer
celtsLabor.append({"user": key,
"positionTitle": positionTitle,
"term": laborTerm,
Expand All @@ -117,14 +120,13 @@ def refreshCeltsLaborRecords(laborDict):
def getCeltsLaborHistory(volunteer):

laborHistoryList = list(CeltsLabor.select(CeltsLabor.positionTitle,
CeltsLabor.id,
CeltsLabor.isAcademicYear,
Term.description,
Term.academicYear,
Term.isSummer)
.join(Term, on=(CeltsLabor.term == Term.id))
.where(CeltsLabor.user == volunteer))

laborHistoryDict= {}
for position in laborHistoryList:
laborHistoryDict[position.positionTitle] = position.term.description if position.term.isSummer else position.term.academicYear
.where(CeltsLabor.user == volunteer)
.order_by(Term.termOrder.asc()))

return laborHistoryDict
return [(p.positionTitle, f"AY {p.term.academicYear}" if p.isAcademicYear else p.term.description) for p in laborHistoryList]
24 changes: 17 additions & 7 deletions app/logic/events.py
Original file line number Diff line number Diff line change
Expand Up @@ -411,22 +411,32 @@ def getParticipatedEventsForUser(user):
:return: A list of Event objects
"""

# Does this handle labor only and/or includes labor events?
participatedEvents = (Event.select(Event, Program.programName, Case(None, (
((Event.allowsLabor | Event.name.contains("Labor")) & Event.isService, "Labor & Volunteer"),
((Event.allowsLabor | Event.isLaborOnly | Event.name.contains("Labor")), "Labor"),
(Event.isService, "Volunteer")), "Attendee").alias("participatedType"))
eventName = fn.LOWER(Event.name)
checkIfLaborMeeting = eventName.contains("labor meeting")

participatedEvents = (Event.select(Event,
Program.programName,
Case(None,
(
((Event.allowsLabor | Event.name.contains("Labor")) & Event.isService, "Labor & Volunteer"),
((Event.allowsLabor | Event.isLaborOnly | Event.name.contains("Labor")), "Labor"),
(Event.isService, "Volunteer")
),
"Attendee").alias("participatedType"),
EventParticipant.hoursEarned
)
.join(Program, JOIN.LEFT_OUTER).switch()
.join(EventParticipant)
.where(EventParticipant.user == user,
Event.isAllVolunteerTraining == False, Event.deletionDate == None, Event.isCeltsTraining == False)
.order_by(Event.startDate, Event.name))
allVolunteer = (Event.select(Event, "", Value("Volunteer").alias("participatedType"))

allVolunteer = (Event.select(Event, "", Value("Volunteer").alias("participatedType"), Value(0).alias("hoursEarned"))
.join(EventParticipant)
.where(Event.isAllVolunteerTraining == True,
EventParticipant.user == user))
union = participatedEvents.union_all(allVolunteer)
unionParticipationWithVolunteer = list(union.select_from(union.c.id, union.c.programName, union.c.startDate, union.c.name, union.c.participatedType).order_by(union.c.startDate, union.c.name).execute())
unionParticipationWithVolunteer = list(union.select_from(union.c.id, union.c.isService, union.c.programName, union.c.startDate, union.c.name, union.c.participatedType, union.c.hoursEarned).order_by(union.c.startDate, union.c.name).execute())
return unionParticipationWithVolunteer

def validateNewEventData(data):
Expand Down
18 changes: 12 additions & 6 deletions app/logic/participants.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ def getEventParticipants(event):

return [p for p in eventParticipants]

def getParticipationStatusForTrainings(program, userList, term, returnStr = True):
def getParticipationStatusForTrainings(program, userList, term, includeFutureEvents = True):
"""
This function returns a dictionary of all trainings for a program and
whether the current user participated in them.
Expand All @@ -130,7 +130,10 @@ def getParticipationStatusForTrainings(program, userList, term, returnStr = True
.join(EventRsvp, JOIN.LEFT_OUTER).switch()
.join(Term)
.where(isRelevantTraining, (Event.isCanceled != True)).order_by(Event.startDate))

if not includeFutureEvents:
programTrainings = programTrainings.where(
(Event.startDate < datetime.now().date()) |
((Event.startDate == datetime.now().date()) & (Event.timeStart <= datetime.now().time())))
# Create a dictionary where the keys are trainings and values are a set of those who attended
trainingData = defaultdict(set)
for training in programTrainings:
Expand All @@ -151,7 +154,7 @@ def getParticipationStatusForTrainings(program, userList, term, returnStr = True
for user in userList:
if training.name not in userParticipationStatus[user.username] or user.username in attendeeList:
userParticipationStatus[user.username][training.name] = [training, user.username in attendeeList]
if returnStr:
if includeFutureEvents:
return {user.username: list(userParticipationStatus[user.username].values()) for user in userList}
else:
return {user: list(userParticipationStatus[user.username].values()) for user in userList}
Expand All @@ -178,7 +181,7 @@ def getTrainingsForInterestedParticipants(programID, interestedUsers):

Gracefully handles multiple trainings of the same type (e.g., two All Volunteers Trainings)
"""
trainedUsers = getParticipationStatusForTrainings(programID, interestedUsers, g.current_term, returnStr = False)
trainedUsers = getParticipationStatusForTrainings(programID, interestedUsers, g.current_term, includeFutureEvents = False)
now = datetime.now()
bannedUsers = list(User
.select(User.username)
Expand Down Expand Up @@ -207,7 +210,7 @@ def getTrainingsForInterestedParticipants(programID, interestedUsers):
for event in trainedUsers[interestedUser]:
if not event[1]: # they didn't attend this training
continue
elif event[0].isAllVolunteerTraining: # They attended AVT
elif event[0].isAllVolunteerTraining or event[0].isCeltsTraining: # They attended AVT or ACT
trainedAndInterested[interestedUser.username]["allVolunteer"] = True
elif event[0].isTraining: # They attended the Program-specific training
trainedAndInterested[interestedUser.username]["programSpecific"] = True
Expand Down Expand Up @@ -241,7 +244,10 @@ def getParticipantsForProgramForAY(program, academicYear):
.where(Program.id == program,
Term.academicYear == academicYear,
User.hasGraduated == False,
EventParticipant.hoursEarned > 0)
EventParticipant.hoursEarned > 0,
# Only include currently enrolled undergraduate students.
# This prevents alumni and past participants from appearing in the older reports.
User.rawClassLevel.in_(["Freshman", "Sophomore", "Junior", "Senior"]))
.distinct()
)
return participants
Expand Down
32 changes: 23 additions & 9 deletions app/logic/searchUsers.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from peewee import fn
from playhouse.shortcuts import model_to_dict
from app.models.user import User
def searchUsers(query, category=None):
Expand All @@ -6,15 +7,19 @@ def searchUsers(query, category=None):

MySQL LIKE is case insensitive
'''
# add wildcards to each piece of the query
splitSearch = query.strip().split()
firstName = splitSearch[0] + "%"
lastName = " ".join(splitSearch[1:]) +"%"

if len(splitSearch) == 1: # search for query in first OR last name
searchWhere = (User.firstName ** firstName | User.lastName ** firstName | User.username ** splitSearch)
else: # search for first AND last name
searchWhere = (User.firstName ** firstName & User.lastName ** lastName)
if not splitSearch:
return User.select().where(False)
searchWhere = None
for namePart in splitSearch:
nameSearch = namePart + "%"
# This individual search term can match the user's first name, last name, or username.
namePartWhere = (User.firstName.contains(namePart) | User.lastName.contains(namePart) | User.username.contains(namePart))
# For the first search term, initialize the WHERE condition.
if searchWhere is None:
searchWhere = namePartWhere
else:
searchWhere &= namePartWhere # Require every search term to match at least one of the first name, last name, or username fields.

if category == "instructor":
userWhere = (User.isFaculty | User.isStaff)
Expand All @@ -26,12 +31,21 @@ def searchUsers(query, category=None):
userWhere = (User.isCeltsOperationsTeam)
elif category == "celtsLinkAdmin":
userWhere = (User.isFaculty | User.isStaff | User.isCeltsStudentStaff | User.isCeltsOperationsTeam)
elif category == "currentStudents":
userWhere = (User.rawClassLevel.in_(["Freshman", "Sophomore", "Junior", "Senior"]))
elif category == "all":
userWhere = (True)
else:
userWhere = (User.isStudent)

fullSearchText = " ".join(splitSearch)
# Combine into query
searchResults = User.select().where(searchWhere, userWhere)
searchResults = User.select().where(searchWhere, userWhere).order_by(
fn.CONCAT(User.firstName, " ", User.lastName).contains(fullSearchText).desc(),
User.firstName.startswith(fullSearchText).desc(),
User.lastName.startswith(fullSearchText).desc(),
User.lastName,
User.firstName
)

return { user.username : model_to_dict(user) for user in searchResults }
54 changes: 41 additions & 13 deletions app/logic/users.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ def getProgramInterest(program):
Parameters:
program: Program object
"""
return User.select().join(Interest).where(Interest.program == program)
return User.select().join(Interest).where(Interest.program == program, User.rawClassLevel.in_(["Freshman", "Sophomore", "Junior", "Senior"]))

def getBannedUsers(program):
"""
Expand Down Expand Up @@ -196,20 +196,48 @@ def getUserBGCheckHistory(username):
for row in allBackgroundChecks:
bgHistory[row.type_id].append(row)
return bgHistory

def addProfileNote(visibility, bonner, noteTextbox, username):
def getProfileNoteData(formData, includeUsername=False, includeId=False):
noteData = {
"visibility": int(formData.get("visibility", 1)),
"bonner": formData.get("bonner") == "yes",
"cceMinor": formData.get("cceMinor") == "yes",
"noteTextbox": formData.get("noteTextbox", "").strip(),
}
if not noteData["noteTextbox"]:
raise ValueError("Note cannot be empty")
if includeUsername:
noteData["username"] = formData.get("username")
if not noteData["username"]:
raise ValueError("Missing username")
if includeId:
noteData["profileNoteID"] = formData.get("id")
if not noteData["profileNoteID"]:
raise ValueError("Missing profile note ID")
return noteData

def addProfileNote(visibility, bonner, cceMinor, noteTextbox, username):
user = User.get(User.username == username)
visibility = int(visibility)
if bonner:
visibility = 1 # bonner notes are always admins and the student
visibility = 1

noteForDb = Note.create(createdBy = g.current_user,
createdOn = datetime.datetime.now(),
noteContent = noteTextbox,
noteType = "profile")
createProfileNote = ProfileNote.create(user = User.get(User.username == username),
note = noteForDb,
isBonnerNote = bonner,
viewTier = visibility)
return createProfileNote
noteForDb = Note.create( createdBy=g.current_user, createdOn=datetime.datetime.now(), noteContent=noteTextbox, noteType="profile" )
profileNote = ProfileNote.create( user=user, note=noteForDb, isBonnerNote=bonner, isCCEMinorNote=cceMinor, viewTier=visibility, )
return profileNote

def updateProfileNote( profileNoteID, visibility, bonner, cceMinor, noteTextbox):
profileNote = ProfileNote.get_by_id(profileNoteID)
visibility = int(visibility)
if bonner:
visibility = 1
note = profileNote.note
note.noteContent = noteTextbox
note.save()
profileNote.viewTier = visibility
profileNote.isBonnerNote = bonner
profileNote.isCCEMinorNote = cceMinor
profileNote.save()
return profileNote

def deleteProfileNote(noteId):
return ProfileNote.delete().where(ProfileNote.id == noteId).execute()
Expand Down
2 changes: 1 addition & 1 deletion app/logic/volunteerSpreadsheet.py
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ def makeDataXls(sheetName, sheetData, workbook, sheetDesc=None):
if type(dataRows) == list:
for row, rowData in enumerate(dataRows):
col_idx = 0
for column, value in rowData.items():
for value in rowData:
# dates and times should use their text representation
if isinstance(value, (datetime, date, time)):
value = str(value)
Expand Down
Loading
Loading