From c8848114646e470313ea7d477edb79f7ecb8efd0 Mon Sep 17 00:00:00 2001 From: zhytkovd Date: Thu, 6 Aug 2026 14:02:33 -0400 Subject: [PATCH 1/6] Added 2026 allocation data and new 202600 term --- database/demo_data.py | 55 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/database/demo_data.py b/database/demo_data.py index b7a59297..a9b117e7 100644 --- a/database/demo_data.py +++ b/database/demo_data.py @@ -637,6 +637,16 @@ "adjustmentCutOff": f"2025-09-01", "isBreak": 1, }, + { + "termCode": f"202600", + "termName": f"AY 2026-2027", + "termStart": f"2026-08-01", + "termEnd": f"2027-05-01", + "termState": 0, + "primaryCutOff": f"2026-09-01", + "adjustmentCutOff": f"2026-09-01", + "isBreak": 0, + }, ] Term.insert_many(terms).on_conflict_replace().execute() @@ -1181,6 +1191,51 @@ "secondary_10": 1, "breakHours": 900, }, + { + "termCode": 202600, + "department": 5, + "isFinal": True, + "approvedOn": None, + "approvedBy": None, + "justification": "Due to rapid department growth, we need to hire more students to help with the increased workload", + "primary_10": 8, + "primary_12": 10, + "primary_15": 7, + "primary_20": 4, + "secondary_5": 5, + "secondary_10": 1, + "breakHours": 900, + }, + { + "termCode": 202600, + "department": 4, + "isFinal": True, + "approvedOn": None, + "approvedBy": None, + "justification": "Due to rapid department growth, we need to hire more students to help with the increased workload", + "primary_10": 8, + "primary_12": 10, + "primary_15": 7, + "primary_20": 4, + "secondary_5": 5, + "secondary_10": 1, + "breakHours": 900, + }, + { + "termCode": 202600, + "department": 5, + "isFinal": True, + "approvedOn": None, + "approvedBy": None, + "justification": "Due to rapid department growth, we need to hire more students to help with the increased workload", + "primary_10": 8, + "primary_12": 10, + "primary_15": 7, + "primary_20": 4, + "secondary_5": 5, + "secondary_10": 1, + "breakHours": 900, + }, ] Allocation.insert_many(allocations).on_conflict_replace().execute() From 0b0861c0f38203a647590f672e4c49beb8f13703 Mon Sep 17 00:00:00 2001 From: zhytkovd Date: Thu, 6 Aug 2026 14:07:45 -0400 Subject: [PATCH 2/6] added data for the Requested Allocations for the AY26-27 --- database/demo_data.py | 188 +++++++++++++++++++++++++++++++++--------- 1 file changed, 147 insertions(+), 41 deletions(-) diff --git a/database/demo_data.py b/database/demo_data.py index a9b117e7..38da8a51 100644 --- a/database/demo_data.py +++ b/database/demo_data.py @@ -1192,51 +1192,157 @@ "breakHours": 900, }, { - "termCode": 202600, - "department": 5, - "isFinal": True, - "approvedOn": None, - "approvedBy": None, - "justification": "Due to rapid department growth, we need to hire more students to help with the increased workload", - "primary_10": 8, - "primary_12": 10, - "primary_15": 7, - "primary_20": 4, - "secondary_5": 5, - "secondary_10": 1, - "breakHours": 900, - }, + "termCode": 202600, + "department": 5, + "isFinal": True, + "approvedOn": None, + "approvedBy": None, + "justification": "Due to rapid department growth, we need to hire more students to help with the increased workload", + "primary_10": 8, + "primary_12": 10, + "primary_15": 7, + "primary_20": 4, + "secondary_5": 5, + "secondary_10": 1, + "breakHours": 900, + }, + { + "termCode": 202600, + "department": 4, + "isFinal": True, + "approvedOn": None, + "approvedBy": None, + "justification": "Due to rapid department growth, we need to hire more students to help with the increased workload", + "primary_10": 8, + "primary_12": 10, + "primary_15": 7, + "primary_20": 4, + "secondary_5": 5, + "secondary_10": 1, + "breakHours": 900, + }, + { + "termCode": 202600, + "department": 3, + "isFinal": True, + "approvedOn": None, + "approvedBy": None, + "justification": "Due to rapid department growth, we need to hire more students to help with the increased workload", + "primary_10": 8, + "primary_12": 10, + "primary_15": 7, + "primary_20": 4, + "secondary_5": 5, + "secondary_10": 1, + "breakHours": 900, + }, + { + "termCode": 202600, + "department": 2, + "isFinal": True, + "approvedOn": None, + "approvedBy": None, + "justification": "Due to rapid department growth, we need to hire more students to help with the increased workload", + "primary_10": 8, + "primary_12": 10, + "primary_15": 7, + "primary_20": 4, + "secondary_5": 5, + "secondary_10": 1, + "breakHours": 900, + }, + { + "termCode": 202600, + "department": 1, + "isFinal": True, + "approvedOn": None, + "approvedBy": None, + "justification": "Due to rapid department growth, we need to hire more students to help with the increased workload", + "primary_10": 8, + "primary_12": 10, + "primary_15": 7, + "primary_20": 4, + "secondary_5": 5, + "secondary_10": 1, + "breakHours": 900, + }, + + # Requested Allocations for 2026-2027 (isFinal = False) { - "termCode": 202600, - "department": 4, - "isFinal": True, - "approvedOn": None, - "approvedBy": None, - "justification": "Due to rapid department growth, we need to hire more students to help with the increased workload", - "primary_10": 8, - "primary_12": 10, - "primary_15": 7, - "primary_20": 4, - "secondary_5": 5, - "secondary_10": 1, - "breakHours": 900, + "termCode": 202600, + "department": 5, + "isFinal": False, + "approvedOn": None, + "approvedBy": None, + "justification": "Due to rapid department growth, we need to hire more students to help with the increased workload", + "primary_10": 1, + "primary_12": 2, + "primary_15": 3, + "primary_20": 4, + "secondary_5": 1, + "secondary_10": 1, + "breakHours": 100, }, { - "termCode": 202600, - "department": 5, - "isFinal": True, - "approvedOn": None, - "approvedBy": None, - "justification": "Due to rapid department growth, we need to hire more students to help with the increased workload", - "primary_10": 8, - "primary_12": 10, - "primary_15": 7, - "primary_20": 4, - "secondary_5": 5, - "secondary_10": 1, - "breakHours": 900, + "termCode": 202600, + "department": 4, + "isFinal": False, + "approvedOn": None, + "approvedBy": None, + "justification": "Due to rapid department growth, we need to hire more students to help with the increased workload", + "primary_10": 1, + "primary_12": 2, + "primary_15": 3, + "primary_20": 4, + "secondary_5": 1, + "secondary_10": 1, + "breakHours": 100, + }, + { + "termCode": 202600, + "department": 3, + "isFinal": False, + "approvedOn": None, + "approvedBy": None, + "justification": "Due to rapid department growth, we need to hire more students to help with the increased workload", + "primary_10": 1, + "primary_12": 2, + "primary_15": 3, + "primary_20": 4, + "secondary_5": 1, + "secondary_10": 1, + "breakHours": 100, + }, + { + "termCode": 202600, + "department": 2, + "isFinal": False, + "approvedOn": None, + "approvedBy": None, + "justification": "Due to rapid department growth, we need to hire more students to help with the increased workload", + "primary_10": 1, + "primary_12": 2, + "primary_15": 3, + "primary_20": 4, + "secondary_5": 1, + "secondary_10": 1, + "breakHours": 100, + }, + { + "termCode": 202600, + "department": 1, + "isFinal": False, + "approvedOn": None, + "approvedBy": None, + "justification": "Due to rapid department growth, we need to hire more students to help with the increased workload", + "primary_10": 1, + "primary_12": 2, + "primary_15": 3, + "primary_20": 4, + "secondary_5": 1, + "secondary_10": 1, + "breakHours": 100, }, - ] Allocation.insert_many(allocations).on_conflict_replace().execute() From 6c9835d39c6eacaa5dce589bc79de790426956fe Mon Sep 17 00:00:00 2001 From: zhytkovd Date: Thu, 6 Aug 2026 21:43:57 -0400 Subject: [PATCH 3/6] Polished demodata for the allocations --- database/demo_data.py | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/database/demo_data.py b/database/demo_data.py index 38da8a51..13128f7c 100644 --- a/database/demo_data.py +++ b/database/demo_data.py @@ -1115,10 +1115,12 @@ ############################ # Allocation Dummy Data: ########################### + +# Active Allocations for 2025 allocations = [ { "termCode": 202500, - "department": 3, + "department": 1, "isFinal": False, "approvedOn": None, "approvedBy": None, @@ -1148,7 +1150,7 @@ }, { "termCode": 202500, - "department": 1, + "department": 3, "isFinal": True, "approvedOn": None, "approvedBy": None, @@ -1164,7 +1166,7 @@ { "termCode": 202500, "department": 4, - "isFinal": False, + "isFinal": True, "approvedOn": None, "approvedBy": None, "justification": "Downscaling the number of students in the department due to budget cuts", @@ -1191,6 +1193,8 @@ "secondary_10": 1, "breakHours": 900, }, + + # Active Allocations for 2026 { "termCode": 202600, "department": 5, @@ -1276,12 +1280,12 @@ "approvedBy": None, "justification": "Due to rapid department growth, we need to hire more students to help with the increased workload", "primary_10": 1, - "primary_12": 2, + "primary_12": 22, "primary_15": 3, "primary_20": 4, "secondary_5": 1, "secondary_10": 1, - "breakHours": 100, + "breakHours": 89, }, { "termCode": 202600, @@ -1290,13 +1294,13 @@ "approvedOn": None, "approvedBy": None, "justification": "Due to rapid department growth, we need to hire more students to help with the increased workload", - "primary_10": 1, + "primary_10": 11, "primary_12": 2, "primary_15": 3, "primary_20": 4, "secondary_5": 1, "secondary_10": 1, - "breakHours": 100, + "breakHours": 293, }, { "termCode": 202600, @@ -1306,12 +1310,12 @@ "approvedBy": None, "justification": "Due to rapid department growth, we need to hire more students to help with the increased workload", "primary_10": 1, - "primary_12": 2, + "primary_12": 23, "primary_15": 3, "primary_20": 4, "secondary_5": 1, "secondary_10": 1, - "breakHours": 100, + "breakHours": 999, }, { "termCode": 202600, @@ -1320,13 +1324,13 @@ "approvedOn": None, "approvedBy": None, "justification": "Due to rapid department growth, we need to hire more students to help with the increased workload", - "primary_10": 1, + "primary_10": 10, "primary_12": 2, "primary_15": 3, - "primary_20": 4, + "primary_20": 13, "secondary_5": 1, - "secondary_10": 1, - "breakHours": 100, + "secondary_10": 19, + "breakHours": 1000, }, { "termCode": 202600, From 53a4f353a391b451fb274325ed0457f8acb3dbc7 Mon Sep 17 00:00:00 2001 From: zhytkovd Date: Thu, 6 Aug 2026 21:46:04 -0400 Subject: [PATCH 4/6] Changed backend logic by implementing a dictionary with the objects --- .../admin_routes/manageDepartments.py | 36 +++------- app/logic/manageDepartments.py | 68 ++++++++++++++----- app/templates/admin/manageDepartments.html | 64 ++++++++++------- 3 files changed, 99 insertions(+), 69 deletions(-) diff --git a/app/controllers/admin_routes/manageDepartments.py b/app/controllers/admin_routes/manageDepartments.py index c202513a..ec9ce2f5 100644 --- a/app/controllers/admin_routes/manageDepartments.py +++ b/app/controllers/admin_routes/manageDepartments.py @@ -17,7 +17,7 @@ from app.logic.manageDepartments import * - +from playhouse.shortcuts import model_to_dict @admin.route('/admin/manageDepartments/', methods=['GET']) def manageDepartments(academicYear = None): @@ -25,7 +25,6 @@ def manageDepartments(academicYear = None): Returns the Manage Departments page, which allows the admin to view all the departments and their allocations. """ - # Checking Admin Rights currentUser = require_login() if not currentUser: # If the current user is not logged in @@ -36,42 +35,25 @@ def manageDepartments(academicYear = None): elif currentUser.supervisor: return render_template('errors/403.html'), 403 - - # The condition below may be deleted if the routing to the Manage Departments page is changed. - if academicYear == None: - academicYear = g.openTerm.termCode - else: - academicYear = int(academicYear) - - - currentAY, nextAY = generateAdjacentYears(academicYear) - chosenAY = Term.get(Term.termCode == academicYear) - - breakHoursByDepartment = {row["department"]: str(row["totalHours"] or 0) for row in getUsedBreakHours(chosenAY)} - - activeDepartments = getActiveDepartmentsWithAllocation(chosenAY) - inactiveDepartments = Department.select().where(Department.isActive == False) + currentAY, nextAY = generateAdjacentYears(g.openTerm.termCode) - allocationStatus = { - department.departmentID: getAllocationStatus(chosenAY, department) - for department in activeDepartments - } + inactiveDepartments = Department.select().where(Department.isActive == False) + allSupervisors = Supervisor.select().order_by(Supervisor.LAST_NAME) - allSupervisors= Supervisor.select().order_by(Supervisor.LAST_NAME) + breakHoursByDepartment = {row["department"]: str(row["totalHours"] or 0) for row in getUsedBreakHours(currentAY)} + + activeDepartmentsAllocations = getActiveDepartmentsAllocations(currentAY,nextAY) return render_template( 'admin/manageDepartments.html', - activeDepartments = activeDepartments, + activeDepartmentsAllocations = activeDepartmentsAllocations, inactiveDepartments = inactiveDepartments, - allSupervisors = allSupervisors, + allSupervisors = allSupervisors, currentAY = currentAY, nextAY = nextAY, - academicYear = chosenAY.termName, breakHoursByDepartment = breakHoursByDepartment, - allocationStatus = allocationStatus ) - @admin.route('/admin/complianceStatus', methods=['POST']) def complianceStatusCheck(): """ diff --git a/app/logic/manageDepartments.py b/app/logic/manageDepartments.py index 4f3fbb9d..6feeec2a 100644 --- a/app/logic/manageDepartments.py +++ b/app/logic/manageDepartments.py @@ -12,17 +12,17 @@ from app.login_manager import require_login +from playhouse.shortcuts import model_to_dict + def generateAdjacentYears(academicYearTermCode=None): """ - Generates the current, the previous, and the following academic years. + Generates the current, and the following academic years. """ - currentYear = g.openTerm.termCode // 100 nextYear = currentYear + 1 - currentAYCode = currentYear * 100 nextAYCode = nextYear * 100 @@ -50,9 +50,6 @@ def generateAdjacentYears(academicYearTermCode=None): # Everything below this line will eventually be deleted - - - def getUsedBreakHours(term): """ Returns the total number of break hours used by each department for a given term. @@ -109,7 +106,7 @@ def getLSFCountSecondaries(currentTerm, department): -def getActiveDepartmentsWithAllocation(term): +def getActiveDepartmentsWithAllocation(term,isFinal = True): """ Returns a list of active departments with allocations for the given term. """ @@ -118,24 +115,61 @@ def getActiveDepartmentsWithAllocation(term): # activeDepartments = Department.select().where(Department.isActive == True) # allAllocations = Allocation.select().where(Allocation.termCode == currentAY) - activeDepartments = (Department + activeDepartments = (Allocation .select(Department, Allocation) - .join(Allocation) + .join(Department) .where( Department.isActive == True, - Allocation.termCode == term.termCode - ) + Allocation.termCode == term.termCode, + Allocation.isFinal == isFinal, + ) ) - for dept in activeDepartments: - dept.totalPrimaries = (dept.allocation.primary_10 + dept.allocation.primary_12 + dept.allocation.primary_15 + dept.allocation.primary_20) - dept.totalSecondaries = (dept.allocation.secondary_5 + dept.allocation.secondary_10) + + for allocation in activeDepartments: + allocation.totalPrimaries = (allocation.primary_10 + allocation.primary_12 + allocation.primary_15 + allocation.primary_20) + allocation.totalSecondaries = (allocation.secondary_5 + allocation.secondary_10) + + if isFinal: # do not need to count them for requested allocations + allocation.lsfCountPrimaries = getLSFCountPrimaries(term, allocation.department) + allocation.lsfCountSecondaries = getLSFCountSecondaries(term, allocation.department) + + return activeDepartments - dept.lsfCountPrimaries = getLSFCountPrimaries(term, dept) - dept.lsfCountSecondaries = getLSFCountSecondaries(term, dept) - return activeDepartments +def getActiveDepartmentsAllocations(term,nextTerm): + """ + This function gets active departments, active allocations for the current AY and future AY. + It returns a dictionary which contains three objects grouped by the departmentID + """ + + activeDepartments = Department.select().where(Department.isActive == True) + + allocations = getActiveDepartmentsWithAllocation(term) + + allocByDeptId = {} + + # index allocations by department ID + for alloc in allocations: + allocByDeptId[alloc.department.departmentID] = alloc + requestedAllocations = getActiveDepartmentsWithAllocation(nextTerm, False) + + # index requested allocations by department ID + reqAllocByDeptId = {} + for alloc in requestedAllocations: + reqAllocByDeptId[alloc.department.departmentID] = alloc + + # build combined dictionary for active departments + activeDepartmentsAllocations = {} + + for dept in activeDepartments: + activeDepartmentsAllocations[dept.departmentID] = { + "department": dept, + "allocation": allocByDeptId.get(dept.departmentID), # None if no allocation + "requestedAllocation": reqAllocByDeptId.get(dept.departmentID), # None if no requested allocation + } + return activeDepartmentsAllocations def getAllocationStatus(term, department): diff --git a/app/templates/admin/manageDepartments.html b/app/templates/admin/manageDepartments.html index 88fcf297..04c87db3 100755 --- a/app/templates/admin/manageDepartments.html +++ b/app/templates/admin/manageDepartments.html @@ -91,63 +91,70 @@

Manage Departments

Department - Status - Current Allocations
({{ academicYear }}) + Current Allocations
({{ currentAY.termName }}) Requested Allocations
({{ nextAY.termName }}) Actions - {% for department in activeDepartments %} + {% for entry in activeDepartmentsAllocations.values() %} - {{department.DEPT_NAME}}
({{department.ORG}}, - {{department.ACCOUNT}}) + {{entry.department.DEPT_NAME}}
({{entry.department.ORG}}, + {{entry.department.ACCOUNT}}) - - + + {% if entry.allocation %} Primary: - {{department.lsfCountPrimaries}} of {{department.totalPrimaries}} + {{entry.allocation.lsfCountPrimaries}} of {{entry.allocation.totalPrimaries}}
+ Secondary: - {{department.lsfCountSecondaries}} of {{department.totalSecondaries}} + {{entry.allocation.lsfCountSecondaries}} of {{entry.allocation.totalSecondaries}}
- Break: {{ breakHoursByDepartment.get(department.departmentID, 0) }} of {{ - department.allocation.breakHours }} hours + Break: {{ breakHoursByDepartment.get(entry.department.departmentID, 0) }} of + {{entry.allocation.breakHours }} hours + {% else %} + No current allocation + {% endif %} Primary: - {{department.lsfCountPrimaries}} of {{department.totalPrimaries}} + {{entry.requestedAllocation.totalPrimaries}}
Secondary: - {{department.lsfCountSecondaries}} of {{department.totalSecondaries}} + {{entry.requestedAllocation.totalSecondaries}}
- Break: {{ breakHoursByDepartment.get(department.departmentID, 0) }} of {{ department.allocation.breakHours }} hours + Break: {{ entry.requestedAllocation.breakHours }} hours @@ -162,19 +169,26 @@

Manage Departments

+ + + - {% endfor %} + {%endfor%} From 2e7520744b76ec9f83561eb56ec3a77431c62ed3 Mon Sep 17 00:00:00 2001 From: zhytkovd Date: Sat, 8 Aug 2026 19:41:47 -0400 Subject: [PATCH 5/6] Finished surface testing of the functions --- app/templates/admin/manageDepartments.html | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/templates/admin/manageDepartments.html b/app/templates/admin/manageDepartments.html index 04c87db3..e1bb7b26 100755 --- a/app/templates/admin/manageDepartments.html +++ b/app/templates/admin/manageDepartments.html @@ -142,6 +142,7 @@

Manage Departments

+ {% if entry.allocation %} Primary: @@ -156,6 +157,9 @@

Manage Departments

Break: {{ entry.requestedAllocation.breakHours }} hours + {% else %} + No current allocation + {% endif %} From 3fa1daf761ca6ebf69f2518b684595f7c8502535 Mon Sep 17 00:00:00 2001 From: zhytkovd Date: Sat, 8 Aug 2026 19:50:25 -0400 Subject: [PATCH 6/6] Fixed minor datatable bug realted to jinja rendering --- app/templates/admin/manageDepartments.html | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/app/templates/admin/manageDepartments.html b/app/templates/admin/manageDepartments.html index e1bb7b26..abb4db22 100755 --- a/app/templates/admin/manageDepartments.html +++ b/app/templates/admin/manageDepartments.html @@ -142,8 +142,9 @@

Manage Departments

- {% if entry.allocation %} + + {% if entry.allocation %} Primary: {{entry.requestedAllocation.totalPrimaries}} @@ -163,8 +164,6 @@

Manage Departments

- -