Coverage for app/logic/utils.py: 71%
65 statements
« prev ^ index » next coverage.py v7.10.2, created at 2026-10-10 20:46 +0000
« prev ^ index » next coverage.py v7.10.2, created at 2026-10-10 20:46 +0000
1from datetime import datetime
2import collections.abc as collections
4from flask import session
5from peewee import DoesNotExist
7from app.models.term import Term
9def selectSurroundingTerms(currentTerm, prevTerms=2, summerOnly=False):
10 """
11 Returns a list of term objects around the provided Term object for the current term.
12 Chooses the previous terms according to the prevTerms parameter (defaulting to 2),
13 and then chooses terms for the next two years after the current term.
15 To get only the current and future terms, pass prevTerms=0.
16 """
17 # Find the starting term
18 startOrder = currentTerm.termOrder
19 while(prevTerms > 0):
20 orderPieces = startOrder.split('-')
21 if(orderPieces[1] == "1"):
22 orderPieces[0] = int(orderPieces[0]) - 1
23 orderPieces[1] = 3
24 else:
25 orderPieces[1] = int(orderPieces[1]) - 1
26 startOrder = f"{orderPieces[0]}-{orderPieces[1]}"
28 prevTerms -= 1
30 surroundingTerms = (Term.select()
31 .where(Term.termOrder >= startOrder, Term.year <= currentTerm.year + 2)
32 .order_by(Term.termOrder))
34 if summerOnly:
35 surroundingTerms = surroundingTerms.where(Term.isSummer)
37 return surroundingTerms
39def selectAllSummerTerms(currentTerm, student):
40 """
41 Selects the summer terms during which a CCE Minor student could be enrolled.
42 """
44 # The year when the student was admitted is inferred from their current class level.
45 classYears = {
46 "Freshman": 1,
47 "Sophomore": 2,
48 "Junior": 3,
49 "Senior": 4,
50 "Graduating": 4 # "Graduating" students are seniors graduating at the end of the current term.
51 }
53 if student.hasGraduated or student.rawClassLevel not in classYears:
54 return []
56 classYear = classYears[student.rawClassLevel]
58 isSpring = currentTerm.description.startswith("Spring")
59 isGraduating = student.rawClassLevel == "Graduating"
61 # First summer the student can request
62 if isSpring or isGraduating:
63 firstSummer = currentTerm.year - classYear + 1
64 else:
65 firstSummer = currentTerm.year - classYear + 2
67 # Last summer the student can request
68 if isSpring and isGraduating:
69 lastSummer = currentTerm.year - 1
70 else:
71 lastSummer = currentTerm.year
73 return (Term.select()
74 .where(Term.isSummer,
75 Term.year >= firstSummer,
76 Term.year <= lastSummer)
77 .order_by(Term.termOrder))
79def getStartofCurrentAcademicYear(currentTerm):
80 if ("Summer" in currentTerm.description) or ("Spring" in currentTerm.description):
81 fallTerm = Term.select().where(Term.year==currentTerm.year-1, Term.description == f"Fall {currentTerm.year-1}").get()
82 return fallTerm
83 return currentTerm
85def format24HourTime(unformattedTime):
86 """
87 Turns a time string or datetime object into a string with a time in 24 hour format
88 unformattedTime: expects a string with format HH:mm AM/PM or HH:mm OR a datetime object
89 returns: a string in 24 hour format HH:mm
90 """
91 if type(unformattedTime) == str:
92 try:
93 formattedTime = datetime.strptime(unformattedTime, "%I:%M %p").strftime("%H:%M") # Converts string to datetime then back to string and formats correctly
94 return formattedTime
95 except ValueError:
96 # calling strptime here to explicitly raise an exception if it wasn't properly in 24 hour format
97 formattedTime = datetime.strptime(unformattedTime, "%H:%M")
98 return unformattedTime
99 else:
100 formattedTime = unformattedTime.strftime("%H:%M")
101 return formattedTime
103def getUsernameFromEmail(email):
104 return email.split("@")[0]
106def getFilesFromRequest(request):
107 attachmentFiles = request.files.getlist("attachmentObject")
108 fileDoesNotExist = attachmentFiles[0].content_type == "application/octet-stream"
109 if fileDoesNotExist:
110 attachmentFiles = None
112 return attachmentFiles
114def getRedirectTarget(popTarget=False):
115 """
116 This function returns a string with the URL or route to a page in the Application
117 saved with setRedirectTarget() and is able to pop the value from the session
118 to make it an empty value
119 popTarget: expects a bool value to determine whether or not to reset
120 redirectTarget to an emtpy value
121 return: a string with the URL or route to a page in the application that was
122 saved in setRedirectTarget()
123 """
124 if "redirectTarget" not in session:
125 return ''
127 target = session["redirectTarget"]
128 if popTarget:
129 session.pop("redirectTarget")
130 return target
132def setRedirectTarget(target):
133 """
134 This function saves the target URL in the session for future redirection
135 to said page
136 target: expects a string that is a URL or a route to a page in the application
137 return: None
138 """
139 session["redirectTarget"] = target