Skip to content

Commit 4e465a2

Browse files
committed
Merge branch 'laborReleaseFormAdmin' of https://github.com/BCStudentSoftwareDevTeam/lsf into laborReleaseFormAdmin
2 parents 55d8ae7 + 8fd5c6f commit 4e465a2

19 files changed

+389
-230
lines changed

app/controllers/admin_routes/adminManagement.py

Lines changed: 38 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from app.models.student import Student
99
from app.logic.tracy import Tracy
1010
from app.logic.userInsertFunctions import createStudentFromTracy, createSupervisorFromTracy, createUser
11-
from app.logic.adminManagement import searchForAdmin, getUser, addAdmin, removeAdmin
11+
from app.logic.adminManagement import searchForAdmin, getUser
1212
from app.logic.utils import adminFlashMessage
1313

1414

@@ -25,7 +25,9 @@ def admin_Management():
2525
elif currentUser.supervisor:
2626
return render_template('errors/403.html'), 403
2727

28-
users = User.select()
28+
users = (User.select(User,Supervisor,Student)
29+
.join(Supervisor,join_type=JOIN.LEFT_OUTER).switch()
30+
.join(Student,join_type=JOIN.LEFT_OUTER))
2931
return render_template( 'admin/adminManagement.html',
3032
title=('Admin Management'),
3133
users = users
@@ -47,35 +49,43 @@ def adminSearch():
4749

4850
@admin.route("/adminManagement/userInsert", methods=['POST'])
4951
def manageLaborAdmin():
50-
if request.form.get("addAdmin"):
51-
newAdmin = getUser('addAdmin')
52-
addAdmin(newAdmin, 'labor')
53-
adminFlashMessage(newAdmin, 'added', 'Labor')
52+
actionMap = {
53+
"addLaborAdmin": {"selectPickerID": "addAdmin", "type": "Labor", "action": "add", "pretty": "Labor"},
54+
"removeLaborAdmin": {"selectPickerID": "removeAdmin", "type": "Labor", "action": "remove", "pretty": "Labor"},
55+
"addFinAidAdmin": {"selectPickerID": "addFinancialAidAdmin", "type": "FinancialAid", "action": "add", "pretty": "Financial Aid"},
56+
"removeFinAidAdmin": {"selectPickerID": "removeFinancialAidAdmin", "type": "FinancialAid", "action": "remove", "pretty": "Financial Aid"},
57+
"addSaasAdmin": {"selectPickerID": "addSAASAdmin", "type": "Saas", "action": "add", "pretty": "SAAS"},
58+
"removeSaasAdmin": {"selectPickerID": "removeSAASAdmin", "type": "Saas", "action": "remove", "pretty": "SAAS"},
59+
}
5460

55-
elif request.form.get("removeAdmin"):
56-
oldAdmin = getUser('removeAdmin')
57-
removeAdmin(oldAdmin, 'labor')
58-
adminFlashMessage(oldAdmin, 'removed', 'Labor')
61+
key = request.form.get('action')
62+
meta = actionMap[key]
63+
user = getUser(actionMap[key]['selectPickerID'])
5964

60-
elif request.form.get("addFinancialAidAdmin"):
61-
newAdmin = getUser('addFinancialAidAdmin')
62-
addAdmin(newAdmin, 'finAid')
63-
adminFlashMessage(newAdmin, 'added', 'Financial Aid')
64-
65-
elif request.form.get("removeFinancialAidAdmin"):
66-
oldAdmin = getUser('removeFinancialAidAdmin')
67-
removeAdmin(oldAdmin, 'finAid')
68-
adminFlashMessage(oldAdmin, 'removed', 'Financial Aid')
65+
# pick addAdmin or removeAdmin dynamically
66+
if meta['action'] == 'add':
67+
addAdmin(user, meta['type'])
68+
else:
69+
removeAdmin(user, meta['type'])
70+
71+
flashMessage(user,
72+
'added' if meta["action"] == "add" else 'removed',
73+
meta["pretty"])
74+
75+
return redirect(url_for('admin.admin_Management'))
6976

70-
elif request.form.get("addSAASAdmin"):
71-
newAdmin = getUser('addSAASAdmin')
72-
addAdmin(newAdmin, 'saas')
73-
adminFlashMessage(newAdmin, 'added', 'SAAS')
77+
def addAdmin(user, adminType):
78+
setattr(user, f"is{adminType}Admin", True)
79+
user.save()
7480

75-
elif request.form.get("removeSAASAdmin"):
76-
oldAdmin = getUser('removeSAASAdmin')
77-
removeAdmin(oldAdmin, 'saas')
78-
adminFlashMessage(oldAdmin, 'removed', 'SAAS')
81+
def removeAdmin(user, adminType):
82+
setattr(user, f"is{adminType}Admin", False)
83+
user.save()
7984

80-
return redirect(url_for('admin.admin_Management'))
85+
def flashMessage(user, action, adminType):
86+
message = "{} has been {} as a {} Admin".format(user.fullName, action, adminType)
8187

88+
if action == 'added':
89+
flash(message, "success")
90+
elif action == 'removed':
91+
flash(message, "danger")

app/controllers/admin_routes/allPendingForms.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,7 @@ def finalUpdateStatus(raw_status):
317317
print("Unknown status: ", raw_status)
318318
return jsonify({"success": False})
319319

320+
flash("Forms have been successfully updated.", "success")
320321
form_ids = eval(request.data.decode("utf-8"))
321322
return saveStatus(new_status, form_ids, currentUser)
322323

@@ -496,7 +497,6 @@ def modalFormUpdate():
496497
conn = Banner()
497498
save_form_status = conn.insert(historyForm)
498499

499-
500500
# if we are able to save
501501
if save_form_status:
502502
# This try is to handle Overload Forms

app/controllers/admin_routes/emailTemplateController.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ def getEmailArray():
3232
"audience": template.audience,
3333
"formType": template.formType,
3434
"action": template.action
35-
} for template in EmailTemplate.select()])
35+
} for template in templates])
3636

3737
@admin.route('/admin/emailTemplates/getPurpose/<fieldsDictSTR>', methods=['GET'])
3838

app/controllers/main_routes/laborHistory.py

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,34 @@ def laborhistory(id):
5757
if len(authorizedForms) == 0:
5858
return render_template('errors/403.html'), 403
5959

60-
6160
authorizedForms = Term.order_by_term(list(authorizedForms.objects()), reverse=True)
6261
downloadId = saveFormSearchResult("Labor History", authorizedForms, "studentHistory")
6362

6463
laborStatusFormList = ','.join([str(form.formID.laborStatusFormID) for form in studentForms])
64+
# modify status display for overload and release forms
65+
formIds = [form.formID for form in authorizedForms]
66+
67+
relatedForms = (FormHistory.select().where(
68+
(FormHistory.formID.in_(formIds)) &
69+
((FormHistory.releaseForm.is_null(False)) | (FormHistory.overloadForm.is_null(False)) | (FormHistory.adjustedForm.is_null(False)))
70+
))
71+
72+
formMap = {form.formID.laborStatusFormID: form for form in authorizedForms}
73+
74+
# initialize displayStatus with each form's base status
75+
for form in authorizedForms:
76+
form.displayStatus = str(form.status)
77+
# iterate once over relatedForms and update each form displayStatus
78+
for related in relatedForms:
79+
form = formMap.get(related.formID.laborStatusFormID)
80+
81+
if related.overloadForm:
82+
form.displayStatus = "Overload " + str(related.status)
83+
if related.adjustedForm:
84+
form.displayStatus = "Adjustment " + str(related.status)
85+
if related.releaseForm:
86+
form.displayStatus = "Release Pending" if str(related.status) == "Pending" else "Released"
87+
6588
return render_template('main/formHistory.html',
6689
title=('Labor History'),
6790
student = student,

app/controllers/main_routes/laborReleaseForm.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ def laborReleaseForm(laborStatusKey):
2424
if not currentUser.isLaborAdmin: # Not an admin
2525
if currentUser.student and not currentUser.supervisor:
2626
return redirect('/laborHistory/' + currentUser.student.ID)
27-
2827
forms = LaborStatusForm.select().distinct().where(LaborStatusForm.laborStatusFormID == laborStatusKey)
2928
laborAdmins = (User.select(User, Supervisor).join(Supervisor)
3029
.where(User.isLaborAdmin == True)
@@ -58,6 +57,7 @@ def laborReleaseForm(laborStatusKey):
5857
email.laborReleaseFormSubmitted(releaseContactUsername, releaseContactFullName)
5958

6059

60+
6161
# Once all the forms are created, the user gets redirected to the
6262
# home page and gets a flash message telling them the forms were
6363
# submiteds

app/controllers/main_routes/main_routes.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,4 @@ def submitToBanner(formHistoryId):
127127
if save_form_status:
128128
return "Form successfully submitted to Banner.", 200
129129
else:
130-
return "Submitting to Banner failed.", 500
131-
132-
130+
return "Submitting to Banner failed.", 500

app/logic/emailHandler.py

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ def __init__(self, formHistoryKey):
3232
self.date = self.laborStatusForm.startDate.strftime("%m/%d/%Y")
3333
self.weeklyHours = str(self.laborStatusForm.weeklyHours)
3434
self.contractHours = str(self.laborStatusForm.contractHours)
35-
35+
self.adminName = ""
3636
self.positions = LaborStatusForm.select().where(LaborStatusForm.termCode == self.term, LaborStatusForm.studentSupervisee == self.student)
3737
self.supervisors = []
3838
for position in self.positions:
@@ -102,7 +102,6 @@ def send(self, message: Message):
102102
message.recipients = [app.config['MAIL_OVERRIDE_ALL']]
103103

104104
message.reply_to = app.config["REPLY_TO_ADDRESS"]
105-
# print("Debugging emailHandler.py: ", app.config)
106105
self.mail.send(message)
107106

108107
elif app.config['ENV'] == 'testing':
@@ -138,6 +137,43 @@ def laborStatusFormSubmitted(self):
138137
self.checkRecipient("Labor Status Form Submitted For Student",
139138
"Primary Position Labor Status Form Submitted")
140139

140+
def statusResendEmail(self):
141+
"""
142+
Sends email to labor supervisor and student when LSF is expired.
143+
"""
144+
145+
lsfID = self.laborStatusForm.laborStatusFormID
146+
expired = self.laborStatusForm.isExpired
147+
if not expired:
148+
return
149+
supervisorTemplate = EmailTemplate.get_or_none(
150+
EmailTemplate.purpose == "Email when Labor Status Form is expired to Supervisor"
151+
)
152+
studentTemplate = EmailTemplate.get_or_none(
153+
EmailTemplate.purpose == "Email when Labor Status Form is expired to Student"
154+
)
155+
if not supervisorTemplate or not studentTemplate:
156+
return
157+
try:
158+
Presentday = date.today()
159+
already_sent = (EmailTracker
160+
.select()
161+
.where(
162+
(EmailTracker.formID == lsfID) &
163+
((EmailTracker.subject == supervisorTemplate.subject) | (EmailTracker.subject == studentTemplate.subject)) &
164+
(EmailTracker.date == Presentday)
165+
)
166+
.exists())
167+
if already_sent:
168+
return
169+
except Exception as e:
170+
print(f"Check failed for LSF{lsfID}: {e}. Proceeding to send.")
171+
self.checkRecipient(
172+
studentEmailPurpose=studentTemplate.purpose,
173+
emailPurpose=supervisorTemplate.purpose,
174+
secondaryEmailPurpose=None
175+
)
176+
141177
def laborStatusFormApproved(self):
142178
if self.laborStatusForm.jobType == 'Secondary':
143179
if self.term.isBreak:
@@ -173,7 +209,7 @@ def laborStatusFormAdjusted(self, newSupervisor=False):
173209
def laborReleaseFormSubmitted(self, adminUserName=None, adminName=None):
174210
self.adminName = adminName
175211
self.adminEmail = adminUserName + "@berea.edu"
176-
emailTemplate = EmailTemplate.get(EmailTemplate.purpose == "Labor Release Form Admin Notification")
212+
emailTemplate = EmailTemplate.get(EmailTemplate.purpose == "Labor Release Form Admin Notification")
177213
self.checkRecipient("Labor Release Form Submitted For Student",
178214
"Labor Release Form Submitted For Supervisor")
179215
self.sendEmail(emailTemplate, "admin")

app/logic/getTableData.py

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,11 @@ def getDatatableData(request):
6262
for field, value in fieldValueMap.items():
6363
if value != "" and value:
6464
if type(value) is list:
65-
clauses.append(field.in_(value))
65+
if field == FormHistory.historyType:
66+
if "Labor Status Form" not in value:
67+
clauses.append(field.in_(value)) # if "original" is selected, we include all forms, so no need to filter by historyType
68+
else:
69+
clauses.append(field.in_(value))
6670
elif field is StudentLaborEvaluation.ID:
6771
sleJoin=value[0]
6872
else:
@@ -126,18 +130,16 @@ def getFormattedData(filteredSearchResults, view ='simple'):
126130
'''
127131
if view == "simple":
128132
formattedData = {}
129-
todaysDate = date.today()
130133
filteredSearchResults.order_by(FormHistory.formID.startDate.desc())
131134
isMostCurrent = False
132135
for form in filteredSearchResults:
133-
startDate = form.formID.startDate
134-
endDate = form.formID.endDate
136+
createdDate = form.createdDate
135137
bNumber = form.formID.studentSupervisee.ID
136138
if bNumber not in formattedData:
137139
absentInFormatting = True
138140
else:
139141
absentInFormatting = False
140-
isMostCurrent = (startDate > formattedData[bNumber][1]) or (startDate <= todaysDate <= endDate)
142+
isMostCurrent = (createdDate > formattedData[bNumber][1])
141143
if absentInFormatting or isMostCurrent:
142144

143145
# html fields
@@ -148,20 +150,31 @@ def getFormattedData(filteredSearchResults, view ='simple'):
148150
departmentName = form.formID.department.DEPT_NAME
149151
statusFormId = form.formID.laborStatusFormID
150152

153+
# determine display status for each student
154+
formStatus = str(form.status)
155+
displayStatus = formStatus
156+
157+
if form.adjustedForm is not None:
158+
displayStatus = "Adjustment " + formStatus
159+
if form.overloadForm is not None:
160+
displayStatus = "Overload " + formStatus
161+
if form.releaseForm is not None:
162+
displayStatus = "Release Pending" if formStatus == "Pending" else "Released"
163+
151164
html = f"""
152165
<a href="/laborHistory/{bNumber}">
153166
<span class="h4">{firstName} {lastName} ({bNumber})</span>
154167
</a>
155-
<span class="pushRight">{form.status}</span>
168+
<span class="pushRight">{displayStatus}</span>
156169
<br>
157170
<span class="pushLeft h6">
158171
{term} - <a><span onclick=loadFormHistoryModal({statusFormId})>{positionTitle} ({jobType})</span></a> - {departmentName}
159172
</span>
160173
"""
161174

162-
formattedData[bNumber] = (html, startDate, endDate)
163-
164-
formattedDataList = [[value] for value, _, _ in formattedData.values()]
175+
formattedData[bNumber] = (html, createdDate)
176+
177+
formattedDataList = [[value] for value, _S in formattedData.values()]
165178

166179
return formattedDataList
167180

app/logic/utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,6 @@ def adminFlashMessage(user, action, adminType):
2727
elif action == 'removed':
2828
flash(message, "danger")
2929

30-
# This function calculates the expiration date for a student confirmation and the total date is 30 days from now at 11:59:59 PM
30+
# This function calculates the expiration date for a student confirmation and the total date based on the number of days set in the secret config from now at 11:59:59 PM
3131
def calculateExpirationDate():
3232
return datetime.combine(datetime.now() + timedelta(app.config["student_confirmation_days"]),time(23, 59, 59))

0 commit comments

Comments
 (0)