-
Notifications
You must be signed in to change notification settings - Fork 0
Adding an Allocation Review & an Allocation Request Pages #668
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
base: dep_portal_ad_ManageDepartments
Are you sure you want to change the base?
Changes from 17 commits
51d34b8
e19a298
09132b1
fc21863
4d1bd2e
f3e0339
37e6fbb
aa78f71
e4c0d29
f3833f7
083e556
73b3ac4
5585ef0
e4c7895
582a393
d8a6635
731ab49
5a24ad2
1fef151
dd23662
3727d18
0e217b9
677adc0
3e83e9d
14b9365
215aa5b
ca967a1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,9 +1,9 @@ | ||
| import os | ||
|
|
||
| from flask import Flask | ||
| from flask_restful import Api | ||
| from datetime import date | ||
| from flask import Flask, g, request, session | ||
| from flask_bootstrap import Bootstrap | ||
| from playhouse.shortcuts import model_to_dict, dict_to_model | ||
| from flask_restful import Api | ||
| from playhouse.shortcuts import dict_to_model, model_to_dict | ||
|
|
||
|
|
||
| app = Flask(__name__) | ||
|
|
@@ -55,17 +55,27 @@ def new_execute(*args, **kwargs): | |
| from app.controllers.api_routes.routes import initializeApiRoutes | ||
| initializeApiRoutes(api) | ||
|
|
||
| from flask import g | ||
| from app.models.user import User | ||
| from app.login_manager import require_login | ||
| from app.login_manager import getUsernameFromEnv, require_login | ||
| @app.before_request | ||
| def load_user(): | ||
| try: | ||
| g.currentUser = dict_to_model(User, session['currentUser']) | ||
| requestUsername = getUsernameFromEnv(request.environ) | ||
| try: | ||
| cachedUser = session['currentUser'] | ||
|
|
||
| if cachedUser.get('username') == requestUsername: | ||
| g.currentUser = dict_to_model(User, cachedUser) | ||
| return | ||
|
|
||
| session.pop('currentUser', None) | ||
| session.pop('username', None) | ||
|
|
||
| except Exception as e: | ||
| user = require_login() | ||
| session['currentUser'] = model_to_dict(user) | ||
| g.currentUser = user | ||
| pass | ||
|
|
||
| user = require_login() | ||
| session['currentUser'] = model_to_dict(user) | ||
| g.currentUser = user | ||
|
|
||
| from app.models.term import Term | ||
| from app.login_manager import getOpenTerm | ||
|
|
@@ -79,6 +89,20 @@ def load_openTerm(): | |
| session['openTerm'] = model_to_dict(term) | ||
| g.openTerm = term | ||
|
|
||
| def getCurrentYear(): | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. getCurrentAY as this is grabbing academic year not just current year |
||
| today = date.today() | ||
| year = today.year | ||
|
|
||
| if today.month < 7: | ||
| return year - 1, year | ||
|
|
||
| return year, year + 1 | ||
|
|
||
| @app.before_request | ||
| def load_currentYear(): | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. load_currentAY |
||
| g.currentYear = getCurrentYear() | ||
|
|
||
|
|
||
| @app.context_processor | ||
| def inject_environment(): | ||
| return dict(env=app.config['ENV']) | ||
|
|
@@ -87,4 +111,3 @@ def inject_environment(): | |
| def queryCount(): | ||
| if session: | ||
| session['querycount'] = 0 | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,6 @@ | ||
| from datetime import date | ||
|
|
||
| from flask import g, request, redirect, jsonify, abort | ||
| from flask import g, request, redirect, jsonify, abort, flash | ||
|
|
||
| from app.controllers.admin_routes import * | ||
| from app.login_manager import require_login | ||
|
|
@@ -16,6 +16,12 @@ | |
| from app.models.laborStatusForm import * | ||
|
|
||
| from app.logic.manageDepartments import * | ||
| from app.logic.allocationManager import allocationExists | ||
| from app.logic.academicYearManager import getCurrentAndNextAY | ||
|
|
||
|
|
||
|
|
||
| ### MANAGE DEPARTMENTS PAGE ################################################################################### | ||
|
|
||
|
|
||
|
|
||
|
|
@@ -93,19 +99,25 @@ def complianceStatusCheck(): | |
|
|
||
|
|
||
|
|
||
| ### ALLOCATION REVIEW PAGE #################################################################################### | ||
|
|
||
|
|
||
|
|
||
| @admin.route('/admin/manageDepartments/<org>/<account>/allocationReview', methods=['GET']) | ||
| def allocationReview(org=None, account=None): | ||
| """ | ||
| Returns the Allocation Review page/form, which can only be accessed through | ||
| the Manage Departments page. | ||
| """ | ||
|
|
||
| # Retrieving the departments based on the org and account numbers | ||
|
|
||
| # getting the name of the currently chosen department (based on the org and account numbers) | ||
| try: | ||
| dept = Department.get(Department.ORG == org, Department.ACCOUNT == account) | ||
| except (NameError, DoesNotExist): | ||
| abort(404) | ||
|
|
||
|
|
||
| # Checking admin rights | ||
| currentUser = require_login() | ||
| if not currentUser: # If the current user is not logged in | ||
|
|
@@ -116,9 +128,66 @@ def allocationReview(org=None, account=None): | |
| elif currentUser.supervisor: | ||
| return render_template('errors/403.html'), 403 | ||
|
|
||
| # Retrieving the next year | ||
| # DON'T DELETE THE UNDERSCORES | ||
| _, _, nextAY = generateAdjacentYears() | ||
| # The generateAdjacentYears() function returns a tuple of three elements, and we only need the third value | ||
|
|
||
| return render_template('admin/allocationReview.html', department = dept, nextAY = nextAY) | ||
| # Retrieving the current and following academic years | ||
| currentAY, nextAY = getCurrentAndNextAY() | ||
|
|
||
|
|
||
| # checking if the allocation has already been approved | ||
| if allocationExists(nextAY.termCode, dept, isFinal=True): | ||
| flash("You cannot reapprove an allocation request.", "danger") | ||
| return redirect('/admin/manageDepartments/') | ||
|
|
||
|
|
||
| # checking if the department has requested any allocation review | ||
| if not allocationExists(nextAY.termCode, dept, isFinal=False): | ||
| flash(f"The {dept.DEPT_NAME} department has not requested an allocation review yet.", "danger") | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. a warning or an info as this is nothing related to error it cannot be danger but this is about informing so this is likely a warning or info |
||
| return redirect('/admin/manageDepartments/') | ||
|
|
||
|
|
||
| # getting the current and the requested allocations | ||
| currentAlloc = Allocation.get(Allocation.termCode == currentAY.termCode, Allocation.department == dept, Allocation.isFinal == True) | ||
| requestedAlloc = Allocation.get(Allocation.termCode == nextAY.termCode, Allocation.department == dept, Allocation.isFinal == False) | ||
|
|
||
|
|
||
| return render_template('admin/allocationReview.html', | ||
| department = dept, | ||
| nextAY = nextAY, | ||
| currentAlloc = currentAlloc, | ||
| requestedAlloc = requestedAlloc | ||
| ) | ||
|
|
||
|
|
||
|
|
||
| @admin.route('/admin/allocationReview/approve', methods=['POST']) | ||
| def approveAllocationReview(): | ||
|
|
||
| # Retrieving the current and following academic years | ||
| currentAY, nextAY = getCurrentAndNextAY() | ||
|
|
||
| # getting the name of the user who approves the request | ||
| approverID = require_login().supervisor | ||
|
|
||
| # getting the name of the requesting department | ||
| requester = request.form.get("requester", type=int, default=None) | ||
|
|
||
| # getting the current allocation (for default values) | ||
| currentAlloc = Allocation.get(Allocation.termCode == currentAY.termCode, Allocation.department == requester, Allocation.isFinal == True) | ||
|
|
||
| # saving the newly approved allocation | ||
| newApprovedAlloc = Allocation.create(termCode = nextAY.termCode, | ||
| department = requester, | ||
| isFinal = True, | ||
| approvedBy = approverID, | ||
| approvedOn = date.today(), | ||
| primary_10 = request.form.get("primary_10", type=int, default=currentAlloc.primary_10), | ||
| primary_12 = request.form.get("primary_12", type=int, default=currentAlloc.primary_12), | ||
| primary_15 = request.form.get("primary_15", type=int, default=currentAlloc.primary_15), | ||
| primary_20 = request.form.get("primary_20", type=int, default=currentAlloc.primary_20), | ||
| secondary_5 = request.form.get("secondary_5", type=int, default=currentAlloc.secondary_5), | ||
| secondary_10 = request.form.get("secondary_10", type=int, default=currentAlloc.secondary_10), | ||
| breakHours = request.form.get("breakHours", type=int, default=currentAlloc.breakHours) | ||
| ) | ||
| newApprovedAlloc.save() | ||
|
|
||
| return redirect("/admin/manageDepartments") | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,9 +1,61 @@ | ||
| from flask import render_template, g | ||
| from flask import render_template, g, request, redirect, flash | ||
| from app.login_manager import require_login | ||
| from app.controllers.main_routes import main_bp | ||
| from app.logic.getPositions import getPositions | ||
| from peewee import DoesNotExist | ||
| from app.models.department import Department | ||
| from app.models.allocation import Allocation | ||
| from app.models.supervisorDepartment import SupervisorDepartment | ||
| from app.logic.allocationRequest import getOrUpdateRequestedAllocation | ||
| from app.logic.allocationManager import allocationExists | ||
| from app.logic.academicYearManager import getCurrentAndNextAY | ||
|
|
||
|
|
||
| @main_bp.route('/department/<org>/<account>/allocations/request', methods=['GET']) | ||
|
MImran2002 marked this conversation as resolved.
|
||
| def allocationRequest(org, account): | ||
|
|
||
| # getting the name of the currently chosen department (based on the org and account numbers) | ||
| try: | ||
| dept = Department.get(Department.ORG == org, Department.ACCOUNT == account) | ||
| except DoesNotExist: | ||
| return render_template('errors/404.html'), 404 | ||
|
|
||
|
|
||
| # cheching if the user can visit this page | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. checking |
||
| if not g.currentUser.isLaborAdmin: | ||
| if not SupervisorDepartment.select().where( | ||
| (SupervisorDepartment.supervisor == g.currentUser.supervisor) & | ||
| (SupervisorDepartment.department == dept.departmentID) | ||
| ).exists(): | ||
| return render_template('errors/403.html'), 403 | ||
|
|
||
|
|
||
| # Retrieving the current and following academic years | ||
| currentAY, nextAY = getCurrentAndNextAY() | ||
|
|
||
|
|
||
| # checking if the allocation has already been approved (in other words, if an approved allocation exists) | ||
| if allocationExists(nextAY.termCode, dept, isFinal=True): | ||
| flash(f"The allocation for the {nextAY.termName.split(" ")[1]} academic year has already been approved; therefore, you can no longer resubmit it.", "danger") | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. bug f string error |
||
| return redirect('/admin/manageDepartments/') | ||
|
|
||
|
|
||
| # getting the current approved allocation | ||
| currentAlloc = Allocation.get(Allocation.termCode == currentAY.termCode, Allocation.department == dept, Allocation.isFinal == True) | ||
|
|
||
|
|
||
| return render_template('main/allocationRequest.html', | ||
| department = dept, | ||
| nextAY = nextAY, | ||
| currentAlloc = currentAlloc | ||
| ) | ||
|
|
||
|
|
||
| @main_bp.route('/allocationRequest/submit', methods=['POST']) | ||
| def submitAllocationRequest(): | ||
| getOrUpdateRequestedAllocation() | ||
| return redirect("/admin/manageDepartments") | ||
|
|
||
|
|
||
| @main_bp.route('/department/<org>/<account>/positions', methods=['GET']) | ||
| def managePositions(org, account): | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| from flask import g | ||
| from app.models.term import * | ||
|
|
||
| def getCurrentAndNextAY(): | ||
| """ | ||
| Returns two Term peewee objects: one is the current academic year, | ||
| and the other is the next academic year (note that a new academic year | ||
| begins from the start of July). | ||
| """ | ||
|
|
||
| currentYear = g.currentYear[0] | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| nextYear = currentYear + 1 | ||
|
|
||
| currentAYCode = currentYear * 100 | ||
| nextAYCode = nextYear * 100 | ||
|
|
||
| currentAY, _ = Term.get_or_create( | ||
| termCode=currentAYCode, | ||
| defaults={"termName": "AY {}-{}".format(currentYear, currentYear + 1), "isAcademicYear": True} | ||
| ) | ||
|
|
||
| nextAY, _ = Term.get_or_create( | ||
| termCode=nextAYCode, | ||
| defaults={"termName": "AY {}-{}".format(nextYear, nextYear + 1), "isAcademicYear": True} | ||
| ) | ||
|
|
||
| return (currentAY, nextAY) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| from flask import request, g | ||
| from app.models.allocation import Allocation | ||
| from app.logic.allocationManager import * | ||
| from app.logic.academicYearManager import getCurrentAndNextAY | ||
|
|
||
|
|
||
| def getOrUpdateRequestedAllocation(): | ||
| """ | ||
| Gets or updates the requested allocation (used for the Allocation Request page specificially). | ||
| """ | ||
| currentAY, nextAY = getCurrentAndNextAY() | ||
|
|
||
| requester = request.form.get("submitter", type=int, default=None) # the requesting department | ||
|
|
||
| # the list of the fields updated after submitting the allocation request | ||
| updatedFields = { | ||
| "termCode": nextAY, | ||
| "department": request.form.get("submitter", type=int, default=None), | ||
| "isFinal": False, | ||
| "justification": request.form.get("justification", default=""), | ||
| "primary_10": request.form.get("primary_10", type=int, default=None), | ||
| "primary_12": request.form.get("primary_12", type=int, default=None), | ||
| "primary_15": request.form.get("primary_15", type=int, default=None), | ||
| "primary_20": request.form.get("primary_20", type=int, default=None), | ||
| "secondary_5": request.form.get("secondary_5", type=int, default=None), | ||
| "secondary_10": request.form.get("secondary_10", type=int, default=None), | ||
| "breakHours": request.form.get("breakHours", type=int, default=None) | ||
| } | ||
|
|
||
| # saving the newly approved allocation | ||
| requestedAlloc, wasCreated = Allocation.get_or_create(termCode=nextAY, department=requester, isFinal=False, defaults={**updatedFields}) | ||
|
|
||
| if not wasCreated: # if the allocation has already existed (it is being resubmitted/updated) | ||
| for key, value in updatedFields.items(): | ||
| setattr(requestedAlloc, key, value) # updating all the fields based on updatedFields values | ||
|
|
||
| requestedAlloc.save() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove these as this would not be relevant for the issue at this point