diff --git a/app/controllers/admin_routes/adminManagement.py b/app/controllers/admin_routes/adminManagement.py index 68590cd70..6efb28e0f 100644 --- a/app/controllers/admin_routes/adminManagement.py +++ b/app/controllers/admin_routes/adminManagement.py @@ -76,7 +76,7 @@ def manageLaborAdmin(): def addAdmin(user, adminType): setattr(user, f"is{adminType}Admin", True) - user.save() + user.save() def removeAdmin(user, adminType): setattr(user, f"is{adminType}Admin", False) diff --git a/app/controllers/main_routes/laborStatusForm.py b/app/controllers/main_routes/laborStatusForm.py index dc794952d..3857c1e68 100755 --- a/app/controllers/main_routes/laborStatusForm.py +++ b/app/controllers/main_routes/laborStatusForm.py @@ -3,6 +3,7 @@ from app.controllers.main_routes import * from app.login_manager import require_login from app.models.user import * +from app.models import mainDB from app.models.status import * from app.models.laborStatusForm import * from app.models.overloadForm import * @@ -73,31 +74,22 @@ def userInsert(): rspFunctional = json.loads(rsp) all_forms = [] for i in range(len(rspFunctional)): - - # Get a student record for the given bnumber - try: - student = getOrCreateStudentRecord(bnumber=rspFunctional[i]['stuBNumber']) - supervisor = createSupervisorFromTracy(bnumber=rspFunctional[i]['stuSupervisorID']) - except InvalidUserException as e: - print(e) - return "", 500 - - department, created = Department.get_or_create(DEPT_NAME = rspFunctional[i]['stuDepartment']) - term, created = Term.get_or_create(termCode = rspFunctional[i]['stuTermCode']) try: - lsf = createLaborStatusForm(student, supervisor.ID, department.departmentID, term, rspFunctional[i]) - createOverloadFormAndFormHistory(rspFunctional[i], lsf, currentUser, host=request.host) - try: + with mainDB.atomic(): + # Get a student record for the given bnumber + student = getOrCreateStudentRecord(bnumber=rspFunctional[i]['stuBNumber']) + supervisor = createSupervisorFromTracy(bnumber=rspFunctional[i]['stuSupervisorID']) + department, created = Department.get_or_create(DEPT_NAME = rspFunctional[i]['stuDepartment']) + term, created = Term.get_or_create(termCode = rspFunctional[i]['stuTermCode']) + lsf = createLaborStatusForm(student, supervisor.ID, department.departmentID, term, rspFunctional[i]) + createOverloadFormAndFormHistory(rspFunctional[i], lsf, currentUser, host=request.host) emailDuringBreak(checkForSecondLSFBreak(term.termCode, student.ID), term) - except Exception as e: - print("Error when sending emails during break: " + str(e)) - + all_forms.append(True) except Exception as e: + print("ERROR on creating Labor Status Form/Overload Form" + str(e)) all_forms.append(False) - print("ERROR on creating Labor Status Form/Overload Form" + str(e)) - flash("Form(s) submitted successfully! They will be eligible for approval in one business day.", "success") return jsonify(all_forms) @main_bp.route("/laborstatusform/getDate/", methods=['GET']) diff --git a/app/logic/emailHandler.py b/app/logic/emailHandler.py index 1de8ef492..fbd043302 100644 --- a/app/logic/emailHandler.py +++ b/app/logic/emailHandler.py @@ -16,7 +16,7 @@ from app import app import os from datetime import datetime, date - +from app.logic.utils import makeThirdPartyLink class emailHandler(): def __init__(self, formHistoryKey): diff --git a/app/logic/statusFormFunctions.py b/app/logic/statusFormFunctions.py index 4694bad63..0dd170b2f 100644 --- a/app/logic/statusFormFunctions.py +++ b/app/logic/statusFormFunctions.py @@ -57,41 +57,43 @@ def createOverloadFormAndFormHistory(rspFunctional, lsf, creatorID, host=None): """ # We create a 'Labor Status Form' first, then we check to see if a 'Labor Overload Form' # needs to be created - isOverload = rspFunctional.get("isItOverloadForm") == "True" - if isOverload: - newLaborOverloadForm = OverloadForm.create( studentOverloadReason = None, - financialAidApproved = None, - financialAidApprover = None, - financialAidReviewDate = None, - SAASApproved = None, - SAASApprover = None, - SAASReviewDate = None, - laborApproved = None, - laborApprover = None, - laborReviewDate = None) - formOverload = FormHistory.create( formID = lsf.laborStatusFormID, - historyType = "Labor Overload Form", - overloadForm = newLaborOverloadForm.overloadFormID, - createdBy = creatorID, - createdDate = date.today(), - status = "Pre-Student Approval") - email = emailHandler(formOverload.formHistoryID) - link = makeThirdPartyLink("student", host, formOverload.formHistoryID) - email.LaborOverLoadFormSubmitted(link) - - formHistory = FormHistory.create( formID = lsf.laborStatusFormID, - historyType = "Labor Status Form", - overloadForm = None, - createdBy = creatorID, - createdDate = date.today(), - status = "Pre-Student Approval") + try: + isOverload = rspFunctional.get("isItOverloadForm") == "True" + if isOverload: + newLaborOverloadForm = OverloadForm.create( studentOverloadReason = None, + financialAidApproved = None, + financialAidApprover = None, + financialAidReviewDate = None, + SAASApproved = None, + SAASApprover = None, + SAASReviewDate = None, + laborApproved = None, + laborApprover = None, + laborReviewDate = None) + formOverload = FormHistory.create( formID = lsf.laborStatusFormID, + historyType = "Labor Overload Form", + overloadForm = newLaborOverloadForm.overloadFormID, + createdBy = creatorID, + createdDate = date.today(), + status = "Pre-Student Approval") + email = emailHandler(formOverload.formHistoryID) + link = makeThirdPartyLink("student", host, formOverload.formHistoryID) + email.LaborOverLoadFormSubmitted(link) - if not formHistory.formID.termCode.isBreak and not isOverload: - email = emailHandler(formHistory.formHistoryID) - email.laborStatusFormSubmitted() + formHistory = FormHistory.create( formID = lsf.laborStatusFormID, + historyType = "Labor Status Form", + overloadForm = None, + createdBy = creatorID, + createdDate = date.today(), + status = "Pre-Student Approval") - return formHistory + if not formHistory.formID.termCode.isBreak and not isOverload: + email = emailHandler(formHistory.formHistoryID) + return formHistory + except Exception as e: + print("Error creating overload form:", e) + raise def checkForSecondLSFBreak(termCode, student): @@ -223,13 +225,18 @@ def emailDuringBreak(secondLSFBreak, term): """ Sending emails during break period """ - if term.isBreak: - isOneLSF = json.loads(secondLSFBreak) - formHistory = FormHistory.get(FormHistory.formHistoryID == isOneLSF['formHistoryID']) - email = emailHandler(formHistory.formHistoryID) - email.laborStatusFormSubmitted() - if(len(isOneLSF["previousSupervisorNames"]) > 1): #Student has more than one lsf. Send email to both supervisors and student - email.notifyAdditionalLaborStatusFormSubmittedForBreak() + try: + if term.isBreak: + isOneLSF = json.loads(secondLSFBreak) + formHistory = FormHistory.get(FormHistory.formHistoryID == isOneLSF['formHistoryID']) + email = emailHandler(formHistory.formHistoryID) + email.laborStatusFormSubmitted() + if(len(isOneLSF["previousSupervisorNames"]) > 1): #Student has more than one lsf. Send email to both supervisors and student + email.notifyAdditionalLaborStatusFormSubmittedForBreak() + except Exception as e: + print("Error sending email during break:", e) + raise + def createOverloadForm(newWeeklyHours, lsf, currentUser, adjustedForm=None, formHistories=None, host=None): diff --git a/app/models/__init__.py b/app/models/__init__.py index 73750b36d..cc58248fa 100755 --- a/app/models/__init__.py +++ b/app/models/__init__.py @@ -1,8 +1,9 @@ +from app import app import os - from peewee import * +from flask_sqlalchemy import SQLAlchemy +db = SQLAlchemy(app) -from app import app def getMySQLDB(): if os.environ.get("USING_CONTAINER", False): diff --git a/app/static/js/laborStatusForm.js b/app/static/js/laborStatusForm.js index ff9b252a9..e6c2e9cff 100755 --- a/app/static/js/laborStatusForm.js +++ b/app/static/js/laborStatusForm.js @@ -2,18 +2,18 @@ var globalArrayOfStudents = []; var display_failed = []; var laborStatusFormNote = null; -$(document).ready(function(){ - if($("#selectedDepartment").val()){ // prepopulates position on redirect from rehire button and checks whether department is in compliance. +$(document).ready(function () { + if ($("#selectedDepartment").val()) { // prepopulates position on redirect from rehire button and checks whether department is in compliance. checkCompliance($("#selectedDepartment")); getDepartment($("#selectedDepartment")); } - if($("#jobType").val()){ // fills hours per week selectpicker with correct information from laborstatusform. This is triggered on redirect from form history. + if ($("#jobType").val()) { // fills hours per week selectpicker with correct information from laborstatusform. This is triggered on redirect from form history. var value = $("#selectedHoursPerWeek").val(); $("#selectedHoursPerWeek").val(value); fillHoursPerWeek("fillhours"); } var cookies = document.cookie; - if (cookies){ + if (cookies) { parsedArrayOfStudentCookies = JSON.parse(cookies); document.cookie = parsedArrayOfStudentCookies + ";max-age=28800;"; for (i in parsedArrayOfStudentCookies) { @@ -29,36 +29,36 @@ $(document).ready(function(){ } }); -$("#laborStatusForm").submit(function(event) { +$("#laborStatusForm").submit(function (event) { event.preventDefault(); }); -$("#calendarIcon1").click(function() { - $("#dateTimePicker1").datepicker('show') // Shows the start date datepicker when glyphicon is clicked +$("#calendarIcon1").click(function () { + $("#dateTimePicker1").datepicker('show') // Shows the start date datepicker when glyphicon is clicked }); -$("#calendarIcon2").click(function() { - $("#dateTimePicker2").datepicker('show') // Shows the end date datepicker when glyphicon is clicked +$("#calendarIcon2").click(function () { + $("#dateTimePicker2").datepicker('show') // Shows the end date datepicker when glyphicon is clicked }); $(document).on("keyup", "input[name=contractHours]", function () { // sets contract hours minimum value - var _this = $(this); - var min = parseInt(_this.attr("min")) || 1; // if min attribute is not defined, 1 is default - var val = parseInt(_this.val()) || (min - 1); // if input char is not a number the value will be (min - 1) so first condition will be true - if(val < min) { - _this.val( min ); - } + var _this = $(this); + var min = parseInt(_this.attr("min")) || 1; // if min attribute is not defined, 1 is default + var val = parseInt(_this.val()) || (min - 1); // if input char is not a number the value will be (min - 1) so first condition will be true + if (val < min) { + _this.val(min); + } }); -$("#jobType").change(function(){ // Pops up a modal for Seconday Postion +$("#jobType").change(function () { // Pops up a modal for Seconday Postion //this is just getting the value that is selected var jobType = $(this).val(); if (jobType == "Secondary") { - $("#warningModal").modal("show"); - $("#warningModalTitle").html("Warning"); //Maybe change the wording here. - $("#warningModalText").html("The labor student and the supervisor of this secondary position should obtain permission from the primary supervisor before submitting this labor status form."); - } - }); + $("#warningModal").modal("show"); + $("#warningModalTitle").html("Warning"); //Maybe change the wording here. + $("#warningModalText").html("The labor student and the supervisor of this secondary position should obtain permission from the primary supervisor before submitting this labor status form."); + } +}); function checkIfFreshman() { var jobType = $("#jobType").val(); @@ -78,24 +78,24 @@ function checkIfFreshman() { function disableTermSupervisorDept() { // disables term, supervisor and department select pickers when add student button is clicked - $("#selectedTerm").prop("disabled", "disabled"); - $("#termInfo").show(); - $("#selectedTerm").selectpicker("refresh"); - $("#selectedSupervisor").prop("disabled", "disabled"); - $("#supervisorInfo").show(); - $("#selectedSupervisor").selectpicker("refresh"); - $("#selectedDepartment").prop("disabled", "disabled"); - $("#departmentInfo").show(); - $("#selectedDepartment").selectpicker("refresh"); + $("#selectedTerm").prop("disabled", "disabled"); + $("#termInfo").show(); + $("#selectedTerm").selectpicker("refresh"); + $("#selectedSupervisor").prop("disabled", "disabled"); + $("#supervisorInfo").show(); + $("#selectedSupervisor").selectpicker("refresh"); + $("#selectedDepartment").prop("disabled", "disabled"); + $("#departmentInfo").show(); + $("#selectedDepartment").selectpicker("refresh"); } -function preFilledDate(obj){ // get term start date and end date +function preFilledDate(obj) { // get term start date and end date var termCode = $(obj).val(); $.ajax({ url: "/laborstatusform/getDate/" + termCode, dataType: "json", - success: function (response){ - fillDates(response); + success: function (response) { + fillDates(response); } }); } @@ -106,37 +106,37 @@ function fillDates(response) { // prefill term start and term end $("#primary-cutoff-date").text(""); $("#addMoreStudent").show(); - $("#selectedTerm").on("change", function(){ + $("#selectedTerm").on("change", function () { $("#jobType").val(''); }); - for (var key in response){ + for (var key in response) { var start = response[key]["Start Date"]; var end = response[key]["End Date"]; var primaryCutOff = response[key]["Primary Cut Off"]; // disabling primary position if cut off date is before today's date var today = new Date(); - var date = ("0"+(today.getMonth()+1)).slice(-2)+"/"+("0"+today.getDate()).slice(-2)+"/"+today.getFullYear(); + var date = ("0" + (today.getMonth() + 1)).slice(-2) + "/" + ("0" + today.getDate()).slice(-2) + "/" + today.getFullYear(); var isBreak = response[key]["isBreak"]; var isSummer = response[key]["isSummer"]; - if (primaryCutOff){ - if (isBreak){ - if (Date.parse(date) > Date.parse(primaryCutOff)){ - msgFlash("The deadline to add break positions has ended.", "fail"); - $("#break-cutoff-warning").show(); - $("#break-cutoff-date").text(primaryCutOff); - $("#addMoreStudent").hide(); + if (primaryCutOff) { + if (isBreak) { + if (Date.parse(date) > Date.parse(primaryCutOff)) { + msgFlash("The deadline to add break positions has ended.", "fail"); + $("#break-cutoff-warning").show(); + $("#break-cutoff-date").text(primaryCutOff); + $("#addMoreStudent").hide(); } } - else{ - if (Date.parse(date) > Date.parse(primaryCutOff)){ - $("#jobType option[value='Primary']").attr("disabled", true ); + else { + if (Date.parse(date) > Date.parse(primaryCutOff)) { + $("#jobType option[value='Primary']").attr("disabled", true); $('.selectpicker').selectpicker('refresh'); msgFlash("Disabling primary position because cut off date is before today's date", "fail"); $("#primary-cutoff-warning").show(); $("#primary-cutoff-date").text(primaryCutOff); } - else{ - $("#jobType option[value='Primary']").attr("disabled", false ); + else { + $("#jobType option[value='Primary']").attr("disabled", false); $('.selectpicker').selectpicker('refresh'); } } @@ -160,30 +160,30 @@ function fillDates(response) { // prefill term start and term end $("#dateTimePicker2").datepicker("option", "maxDate", new Date(yearEnd, monthEnd1, dayEnd1)); $("#dateTimePicker2").datepicker("option", "minDate", new Date(yearStart, monthStart1, dayStart1)); $("#dateTimePicker1").datepicker({ - beforeShowDay: function(d) { + beforeShowDay: function (d) { - if(d.getTime() < startd.getTime()){ + if (d.getTime() < startd.getTime()) { return [false, 'datePicker', 'Before Term Start']; } else if (d.getTime() > endd.getTime()) { return [false, 'datePicker', 'After Term End']; - }else{ - return [true, '', 'Available']; + } else { + return [true, '', 'Available']; } - }, - }); + }, + }); $("#dateTimePicker2").datepicker({ - beforeShowDay: function(d) { + beforeShowDay: function (d) { - if(d.getTime() > endd.getTime()){ + if (d.getTime() > endd.getTime()) { return [false, 'datePicker', 'After Term End']; } else if (d.getTime() < startd.getTime()) { return [false, 'datePicker', 'Before Term Start']; - }else{ - return [true, '', 'Available']; + } else { + return [true, '', 'Available']; } - }, + }, }); } } @@ -192,98 +192,98 @@ function updateDate(obj) { // updates max and min dates of the datepickers as th var dateToChange = new Date($(obj).val()); var newMonth = dateToChange.getMonth(); var newYear = dateToChange.getFullYear(); - if(obj.id == "dateTimePicker2"){ + if (obj.id == "dateTimePicker2") { var newDay = dateToChange.getDate() - 1; - $("#dateTimePicker1").datepicker({maxDate: new Date(newYear, newMonth, newDay)}); + $("#dateTimePicker1").datepicker({ maxDate: new Date(newYear, newMonth, newDay) }); $("#dateTimePicker1").datepicker("option", "maxDate", new Date(newYear, newMonth, newDay)); } - if(obj.id == "dateTimePicker1"){ + if (obj.id == "dateTimePicker1") { var newDay = dateToChange.getDate() + 1; - $("#dateTimePicker2").datepicker({minDate: new Date(newYear, newMonth, newDay)}); - $("#dateTimePicker2").datepicker( "option", "minDate", new Date(newYear, newMonth, newDay)); + $("#dateTimePicker2").datepicker({ minDate: new Date(newYear, newMonth, newDay) }); + $("#dateTimePicker2").datepicker("option", "minDate", new Date(newYear, newMonth, newDay)); } } -function getDepartment(object, stopSelectRefresh="") { // get department from select picker - var departmentOrg = $(object).val(); - var departmentAcct = $(object).find('option:selected').attr('value-account'); - var url = "/laborstatusform/getPositions/" + departmentOrg + "/" + departmentAcct; - $.ajax({ - url: url, - dataType: "json", - success: function (response){ +function getDepartment(object, stopSelectRefresh = "") { // get department from select picker + var departmentOrg = $(object).val(); + var departmentAcct = $(object).find('option:selected').attr('value-account'); + var url = "/laborstatusform/getPositions/" + departmentOrg + "/" + departmentAcct; + $.ajax({ + url: url, + dataType: "json", + success: function (response) { - fillPositions(response, stopSelectRefresh); - } - }); - } + fillPositions(response, stopSelectRefresh); + } + }); +} - function fillPositions(response, stopSelectRefresh="") { // prefill Position select picker with the positions of the selected department - var selectedPositions = $("#position"); - $("#position").empty(); - for (var key in response) { - selectedPositions.append( - $("