From d09be82381a39d9164f170d6e7d35e8612197544 Mon Sep 17 00:00:00 2001 From: Hila Manalai Date: Wed, 17 Feb 2021 09:23:05 -0500 Subject: [PATCH] added the two new files --- app/logic/formManagement.py | 233 ++++++++++++++++++++++++++++++ tests/code/test_formManagement.py | 45 ++++++ 2 files changed, 278 insertions(+) create mode 100644 app/logic/formManagement.py create mode 100644 tests/code/test_formManagement.py diff --git a/app/logic/formManagement.py b/app/logic/formManagement.py new file mode 100644 index 00000000..f588d206 --- /dev/null +++ b/app/logic/formManagement.py @@ -0,0 +1,233 @@ +from flask_login import login_required +from app.controllers.main_routes import * +from app.models.user import * +from app.models.status import * +from app.models.laborStatusForm import * +from app.models.overloadForm import * +from app.models.formHistory import* +from app.models.historyType import * +from app.models.term import * +from app.models.student import Student +from app.models.supervisor import Supervisor +from app.models.department import * +from flask import json, jsonify +from flask import request +from datetime import datetime, date +from flask import Flask, redirect, url_for, flash +from app import cfg +from app.logic.emailHandler import emailHandler +from app.logic.tracy import Tracy, InvalidQueryException +from peewee import DoesNotExist +from functools import reduce +import operator + +def createLaborStatusForm(studentID, primarySupervisor, department, term, rspFunctional): + """ + Creates a labor status form with the appropriate data passed from userInsert() in laborStatusForm.py + studentID: student's primary ID in the database AKA their B# + primarySupervisor: primary supervisor of the student + department: department the position is a part of + term: term when the position will happen + rspFunctional: a dictionary containing all the data submitted in the LSF page + returns the laborStatusForm object just created for later use in laborStatusForm.py + """ + # Changes the dates into the appropriate format for the table + startDate = datetime.strptime(rspFunctional['stuStartDate'], "%m/%d/%Y").strftime('%Y-%m-%d') + endDate = datetime.strptime(rspFunctional['stuEndDate'], "%m/%d/%Y").strftime('%Y-%m-%d') + # Creates the labor Status form + lsf = LaborStatusForm.create(termCode_id = term, + studentSupervisee_id = studentID, + supervisor_id = primarySupervisor, + department_id = department, + jobType = rspFunctional["stuJobType"], + WLS = rspFunctional["stuWLS"], + POSN_TITLE = rspFunctional["stuPosition"], + POSN_CODE = rspFunctional["stuPositionCode"], + contractHours = rspFunctional.get("stuContractHours", None), + weeklyHours = rspFunctional.get("stuWeeklyHours", None), + startDate = startDate, + endDate = endDate, + supervisorNotes = rspFunctional["stuNotes"], + laborDepartmentNotes = rspFunctional["stuLaborNotes"], + studentName = rspFunctional["stuName"] + ) + + return lsf + + +def createOverloadFormAndFormHistory(rspFunctional, lsf, creatorID, status): + """ + Creates a 'Labor Status Form' and then if the request needs an overload we create + a 'Labor Overload Form'. Emails are sent based on whether the form is an 'Overload Form' + rspFunctional: a dictionary containing all the data submitted in the LSF page + lsf: stores the new instance of a labor status form + creatorID: id of the user submitting the labor status form + status: status of the labor status form (e.g. Pending, etc.) + """ + # We create a 'Labor Status Form' first, then we check to see if a 'Labor Overload Form' + # needs to be created + if rspFunctional.get("isItOverloadForm") == "True": + status = Status.get(Status.statusName == "Pre-Student Approval") + overloadHistoryType = HistoryType.get(HistoryType.historyTypeName == "Labor Overload Form") + 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 = overloadHistoryType.historyTypeName, + overloadForm = newLaborOverloadForm.overloadFormID, + createdBy = creatorID, + createdDate = date.today(), + status = status.statusName) + email = emailHandler(formOverload.formHistoryID) + email.LaborOverLoadFormSubmitted('http://{0}/'.format(request.host) + 'studentOverloadApp/' + str(formOverload.formHistoryID)) + historyType = HistoryType.get(HistoryType.historyTypeName == "Labor Status Form") + formHistory = FormHistory.create( formID = lsf.laborStatusFormID, + historyType = historyType.historyTypeName, + overloadForm = None, + createdBy = creatorID, + createdDate = date.today(), + status = status.statusName) + if not formHistory.formID.termCode.isBreak: + email = emailHandler(formHistory.formHistoryID) + email.laborStatusFormSubmitted() + return formHistory + + +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() + +def checkForSecondLSFBreak(termCode, student): + """ + Checks if a student has more than one labor status form submitted for them during a break term, and sends emails accordingly. + """ + positions = LaborStatusForm.select().where(LaborStatusForm.termCode == termCode, LaborStatusForm.studentSupervisee == student) + isMoreLSFDict = {} + storeLSFFormsID = [] + previousSupervisorNames = [] + if len(list(positions)) >= 1: # If student has one or more than one lsf + isMoreLSFDict["showModal"] = True # show modal when the student has one or more than one lsf + + for item in positions: + previousSupervisorNames.append(item.supervisor.FIRST_NAME + " " + item.supervisor.LAST_NAME) + isMoreLSFDict["studentName"] = item.studentSupervisee.FIRST_NAME + " " + item.studentSupervisee.LAST_NAME + isMoreLSFDict['previousSupervisorNames'] = previousSupervisorNames + + if len(list(positions)) == 1: # if there is only one labor status form then send email to the supervisor and student + laborStatusFormID = positions[0].laborStatusFormID + formHistoryID = FormHistory.get(FormHistory.formID == laborStatusFormID) + isMoreLSFDict["formHistoryID"] = formHistoryID.formHistoryID + + else: # if there are more lsfs then send email to student, supervisor and all previous supervisors + for item in positions: # add all the previous lsf ID's + storeLSFFormsID.append(item.laborStatusFormID) # store all of the previous labor status forms for break + laborStatusFormID = storeLSFFormsID.pop() #save all the previous lsf ID's except the one currently created. Pop removes the one created right now. + formHistoryID = FormHistory.get(FormHistory.formID == laborStatusFormID) + isMoreLSFDict['formHistoryID'] = formHistoryID.formHistoryID + isMoreLSFDict["lsfFormID"] = storeLSFFormsID + else: + isMoreLSFDict["showModal"] = False # Do not show the modal when there's not previous lsf + return json.dumps(isMoreLSFDict) + +def checkForPrimaryPosition(termCode, student, currentUser): + """ Checks if a student has a primary supervisor (which means they have primary position) in the selected term. """ + rsp = (request.data).decode("utf-8") # This turns byte data into a string + rspFunctional = json.loads(rsp) + term = Term.get(Term.termCode == termCode) + + termYear = termCode[:-2] + shortCode = termCode[-2:] + clauses = [] + if shortCode == '00': + fallTermCode = termYear + '11' + springTermCode = termYear + '12' + clauses.extend([FormHistory.formID.termCode == fallTermCode, + FormHistory.formID.termCode == springTermCode, + FormHistory.formID.termCode == termCode]) + else: + ayTermCode = termYear + '00' + clauses.extend([FormHistory.formID.termCode == ayTermCode, + FormHistory.formID.termCode == termCode]) + expression = reduce(operator.or_, clauses) # This expression creates SQL OR operator between the conditions added to 'clauses' list + + try: + lastPrimaryPosition = FormHistory.select()\ + .join_from(FormHistory, LaborStatusForm)\ + .join_from(FormHistory, HistoryType)\ + .where((expression) & + (FormHistory.formID.studentSupervisee == student) & + (FormHistory.historyType.historyTypeName == "Labor Status Form") & + (FormHistory.formID.jobType == "Primary"))\ + .order_by(FormHistory.formHistoryID.desc())\ + .get() + except DoesNotExist: + lastPrimaryPosition = None + + if not lastPrimaryPosition: + approvedRelease = None + else: + try: + approvedRelease = FormHistory.select()\ + .where(FormHistory.formID == lastPrimaryPosition.formID, + FormHistory.historyType == "Labor Release Form", + FormHistory.status == "Approved")\ + .order_by(FormHistory.formHistoryID.desc())\ + .get() + except DoesNotExist: + approvedRelease = None + + finalStatus = {} + if not term.isBreak: + if lastPrimaryPosition and not approvedRelease: + if rspFunctional == "Primary": + if lastPrimaryPosition.status.statusName == "Denied": + finalStatus["status"] = "hire" + else: + finalStatus["status"] = "noHire" + finalStatus["term"] = lastPrimaryPosition.formID.termCode.termName + finalStatus["primarySupervisor"] = lastPrimaryPosition.formID.supervisor.FIRST_NAME + " " +lastPrimaryPosition.formID.supervisor.LAST_NAME + finalStatus["department"] = lastPrimaryPosition.formID.department.DEPT_NAME + " (" + lastPrimaryPosition.formID.department.ORG + "-" + lastPrimaryPosition.formID.department.ACCOUNT+ ")" + finalStatus["position"] = lastPrimaryPosition.formID.POSN_CODE +" - "+lastPrimaryPosition.formID.POSN_TITLE + " (" + lastPrimaryPosition.formID.WLS + ")" + finalStatus["hours"] = lastPrimaryPosition.formID.jobType + " (" + str(lastPrimaryPosition.formID.weeklyHours) + ")" + finalStatus["isLaborAdmin"] = currentUser.isLaborAdmin + if lastPrimaryPosition.status.statusName == "Approved" or lastPrimaryPosition.status.statusName == "Approved Reluctantly": + finalStatus["approvedForm"] = True + else: + if lastPrimaryPosition.status.statusName in ["Approved", "Approved Reluctantly", "Pending"]: + lastPrimaryPositionTermCode = str(lastPrimaryPosition.formID.termCode.termCode)[-2:] + # if selected term is AY and student has an approved/pending LSF in spring or fall + if shortCode == '00' and lastPrimaryPositionTermCode in ['11', '12']: + finalStatus["status"] = "noHireForSecondary" + else: + finalStatus["status"] = "hire" + else: + finalStatus["status"] = "noHireForSecondary" + + elif lastPrimaryPosition and approvedRelease: + if rspFunctional == "Primary": + finalStatus["status"] = "hire" + else: + finalStatus["status"] = "noHireForSecondary" + else: + if rspFunctional == "Primary": + finalStatus["status"] = "hire" + else: + finalStatus["status"] = "noHireForSecondary" + else: + finalStatus["status"] = "hire" + return json.dumps(finalStatus) diff --git a/tests/code/test_formManagement.py b/tests/code/test_formManagement.py new file mode 100644 index 00000000..50b3f64f --- /dev/null +++ b/tests/code/test_formManagement.py @@ -0,0 +1,45 @@ +import pytest +from app.logic.formManagement import * + +@pytest.mark.integration +def test_createLaborStatusForm(): + student = "B00730361" + supervisor = "B12361006" + dept = "" + term = "" + formData = { + "stuStartDate":"" + } + new_lsf = createLaborStatusForm(student, supervisor, dept, term, formData) + + # Test success conditions + supervisor = createSupervisorFromTracy(username="heggens", bnumber="B12361006") + assert supervisor.FIRST_NAME == "Scott" + + supervisor = createSupervisorFromTracy(username="", bnumber="B12361006") + assert supervisor.FIRST_NAME == "Scott" + + supervisor = createSupervisorFromTracy(bnumber="B12361006") + assert supervisor.FIRST_NAME == "Scott" + + supervisor = createSupervisorFromTracy(username="heggens") + assert supervisor.FIRST_NAME == "Scott" + + supervisor = createSupervisorFromTracy(username="heggens", bnumber="") + assert supervisor.FIRST_NAME == "Scott" + + supervisor = createSupervisorFromTracy("heggens") + assert supervisor.FIRST_NAME == "Scott" + + # Tests getting a supervisor from TRACY that does not exist in the supervisor table + supervisor = createSupervisorFromTracy(username="hoffmanm", bnumber="B1236237") + assert supervisor.FIRST_NAME == "Megan" + supervisor.delete_instance() + + supervisor = createSupervisorFromTracy(username="", bnumber="B1236237") + assert supervisor.FIRST_NAME == "Megan" + supervisor.delete_instance() + + supervisor = createSupervisorFromTracy(username="hoffmanm") + assert supervisor.FIRST_NAME == "Megan" + supervisor.delete_instance()