diff --git a/app/controllers/admin_routes/manageDepartments.py b/app/controllers/admin_routes/manageDepartments.py index 238eb285..e03e3b70 100644 --- a/app/controllers/admin_routes/manageDepartments.py +++ b/app/controllers/admin_routes/manageDepartments.py @@ -19,15 +19,12 @@ from app.logic.allocationManager import allocationExists from app.logic.academicYearManager import getCurrentAndNextAY - - @admin.route('/admin/manageDepartments/', methods=['GET']) def manageDepartments(): """ 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 @@ -50,22 +47,19 @@ def manageDepartments(): department.departmentID: getAllocationStatus(chosenAY, department) for department in activeDepartments } - + activeDepartmentsAllocations = getActiveDepartmentsAllocations(currentAY,nextAY) allSupervisors= Supervisor.select().order_by(Supervisor.LAST_NAME) 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/controllers/main_routes/__init__.py b/app/controllers/main_routes/__init__.py index e8c4c6bb..52853db7 100755 --- a/app/controllers/main_routes/__init__.py +++ b/app/controllers/main_routes/__init__.py @@ -25,4 +25,4 @@ def injectGlobalData(): from app.controllers.main_routes import studentLaborEvaluation from app.controllers.main_routes import search from app.controllers.main_routes import studentResponse -from app.controllers.main_routes import departmentPortal +from app.controllers.main_routes import departmentPortal \ No newline at end of file diff --git a/app/controllers/main_routes/departmentPortal.py b/app/controllers/main_routes/departmentPortal.py index a4ffba8a..495e334e 100644 --- a/app/controllers/main_routes/departmentPortal.py +++ b/app/controllers/main_routes/departmentPortal.py @@ -4,8 +4,8 @@ from peewee import DoesNotExist from app.login_manager import require_login from app.controllers.main_routes import main_bp -from app.logic.download import makePositionDescriptionPDF -from app.logic.getPositions import getPosition, getPositions, getPositionDescriptionSections +from app.logic.getPositions import getPositions +from peewee import DoesNotExist from app.models.department import Department from app.models.positionHistory import PositionHistory from app.models.allocation import Allocation diff --git a/app/controllers/main_routes/main_routes.py b/app/controllers/main_routes/main_routes.py index cc6f3b86..0875988c 100755 --- a/app/controllers/main_routes/main_routes.py +++ b/app/controllers/main_routes/main_routes.py @@ -10,21 +10,18 @@ from app.models.laborStatusForm import LaborStatusForm from app.models.formHistory import FormHistory from app.models.term import Term -from app.models.allocation import Allocation from app.models.positionHistory import PositionHistory from app.controllers.admin_routes.allPendingForms import checkAdjustment from app.controllers.main_routes import main_bp -from app.logic.download import CSVMaker, saveFormSearchResult, retrieveFormSearchResult, makePositionDescriptionPDF +from app.logic.download import CSVMaker, saveFormSearchResult, retrieveFormSearchResult from app.logic.search import getDepartmentsForSupervisor, searchPerson, searchSupervisorPortal from app.login_manager import require_login, logout from app.logic.getTableData import getDatatableData from app.logic.banner import Banner from app.logic.getSupervisors import getSupervisors from app.logic.getPositions import getActivePositions -from app.logic.allocationManager import getBreakContracts, getContractedAllocations, getTotalAllocations -from app.logic.getTerms import getTerms, getCurrentSemester @main_bp.route('/logout', methods=['GET']) @@ -74,64 +71,17 @@ def departmentPortal(org=None,account=None): supervisors, laborCoordinators = getSupervisors(dept) - - currentAY, fallTerm, springTerm = getTerms() - allocationDict = getTotalAllocations(currentAY, dept) - currentSemester = getCurrentSemester() - contracts = getContractedAllocations(currentSemester, dept) - - positionsList, posURL = getActivePositions(dept) return render_template('main/departmentPortal.html', departments = departments, department = dept, - contracts = contracts, - allocation = allocationDict, - currentSemester = currentSemester.termName, supervisors = supervisors, laborCoordinators=laborCoordinators, currentUser=currentUser, positions = positionsList, posURL = posURL) -@main_bp.route('/department///allocations', methods=['GET']) -def allocationTable(org=None, account=None): - currentUser = g.currentUser - try: - dept = Department.get(Department.ORG == org, Department.ACCOUNT == account) - except (NameError, DoesNotExist): - return render_template('errors/404.html'), 404 - - if not currentUser.isLaborAdmin: - allowedDepartmentIds = [d.departmentID for d in getDepartmentsForSupervisor(currentUser)] - if dept.departmentID not in allowedDepartmentIds: - return render_template('errors/403.html'), 403 - - currentAY, fallTerm, springTerm = getTerms() - - allocationDict = getTotalAllocations(currentAY.termCode, dept) - fallContracts = getContractedAllocations(fallTerm.termCode, dept) - springContracts = getContractedAllocations(springTerm.termCode, dept) - - breakContracts = { - "total": 0, - "thanksgiving":getBreakContracts(currentAY.termCode + 1, dept), - "winter": getBreakContracts(currentAY.termCode + 2, dept), - "spring": getBreakContracts(currentAY.termCode + 3, dept), - "fall":getBreakContracts(currentAY.termCode + 4, dept), - "summer": getBreakContracts(currentAY.termCode + 13, dept) - } - breakContracts["total"] = sum(breakContracts.values()) - return render_template('main/allocationTable.html', - department = dept, - currentAY = currentAY, - allocations = allocationDict, - fallContracts = fallContracts, - springContracts = springContracts, - breakContracts = breakContracts) - - @main_bp.route('/supervisorPortal/download', methods=['POST']) def downloadSupervisorPortalResults(): ''' diff --git a/app/logic/allocationManager.py b/app/logic/allocationManager.py index 407d5359..889c18a7 100644 --- a/app/logic/allocationManager.py +++ b/app/logic/allocationManager.py @@ -27,9 +27,8 @@ def getTotalAllocations(termCode: int, dept: int): ''' This function returns a dictionary representation of the given department's allocation for the given term. ''' - try: - allocationObject = getAllocation(termCode, dept) - allocationDict = {"primary_10": allocationObject["primary_10"], + allocationObject = getAllocation(termCode, dept) + allocationDict = {"primary_10": allocationObject["primary_10"], "primary_12": allocationObject["primary_12"], "primary_15": allocationObject["primary_15"], "primary_20": allocationObject["primary_20"], @@ -39,49 +38,15 @@ def getTotalAllocations(termCode: int, dept: int): "totalPrimaries": (allocationObject["primary_10"] + allocationObject["primary_12"] + allocationObject["primary_15"] + allocationObject["primary_20"]), "totalSecondaries": (allocationObject["secondary_5"] + allocationObject["secondary_10"]), "totalAllocations": (allocationObject["primary_10"] + allocationObject["primary_12"] + allocationObject["primary_15"] + allocationObject["primary_20"] + allocationObject["secondary_5"] + allocationObject["secondary_10"] )} - except: - allocationDict = {"primary_10": "", - "primary_12": "", - "primary_15": "", - "primary_20": "", - "secondary_5": "", - "secondary_10": "", - "breakHours": "No Allocations Found", - "totalPrimaries": "", - "totalSecondaries": "", - "totalAllocations": "No Allocations Found"} return allocationDict -def countContracts(jobType: str, weeklyContractHours: int, termCode: int, dept: int, AYtermCode: int = None): +def countContracts(jobType: str, weeklyContractHours: int, termCode: int, dept: int): ''' This function counts the number of positions of a given type in a given department. For example, countContracts('secondary', 5, 202511, 1) returns the number of secondary 5-hour positions in the CS department for the 2025 Fall term. ''' academicYearCode = int(str(termCode)[:4] + "00") - - # This sets the date condition to determine whether the form is within the boundaries of the term - # Fall only contracts end before spring, spring contracts start after fall. - fallMonths = ["07","08","09","10","11","12"] - springMonths = ["01","02","03","04","05","06"] - if str(termCode).endswith("11"): - dateCondition = ( - (LaborStatusForm.endDate.month.in_(fallMonths)) | - (LaborStatusForm.startDate.month.in_(fallMonths) & # Reused check for year-long positions - LaborStatusForm.endDate.month.in_(springMonths)) - ) - elif str(termCode).endswith("12"): - dateCondition = ( - (LaborStatusForm.startDate.month.in_(springMonths)) | - (LaborStatusForm.startDate.month.in_(fallMonths) & - LaborStatusForm.endDate.month.in_(springMonths)) - ) - else: - dateCondition = ( - (LaborStatusForm.startDate.month.in_(fallMonths) & - LaborStatusForm.endDate.month.in_(springMonths)) - ) - lsfCountPositions = FormHistory.select( ).join(LaborStatusForm ).join(Department @@ -92,28 +57,41 @@ def countContracts(jobType: str, weeklyContractHours: int, termCode: int, dept: LaborStatusForm.jobType == jobType, # 'primary' or 'secondary' LaborStatusForm.weeklyHours == weeklyContractHours, # 5, 10, 12, 15, or 20 Department.departmentID == dept, - dateCondition, ).count() return lsfCountPositions def getContractedAllocations(termCode: int, dept: int): ''' - This function returns a dictionary with a breakdown of all types of contracts + This function returns a dictionary with a breakdown of all types of contracts for the given department and term in the form of a dictionary. ''' academicYearCode = int(str(termCode)[:4] + "00") - breakHoursTotal = ( - FormHistory.select(fn.SUM(LaborStatusForm.contractHours)) - .join(LaborStatusForm, on=(FormHistory.formID == LaborStatusForm.laborStatusFormID)) - .where( - FormHistory.historyType == "Labor Status Form", - FormHistory.status == "Approved", - LaborStatusForm.termCode.in_([termCode, academicYearCode]), - LaborStatusForm.department == dept, - ) - .scalar() - ) or 0 - + allocationObject = getAllocation(termCode, dept) + breakAllocation = FormHistory.select( + LaborStatusForm.department, + LaborStatusForm.termCode, + fn.SUM(LaborStatusForm.contractHours).alias('total_hours') + ).join( + LaborStatusForm, + on=(FormHistory.formID == LaborStatusForm.laborStatusFormID), + ).join( + Term, + on = (LaborStatusForm.termCode == Term.termCode ) + ).where( + (FormHistory.historyType == "Labor Status Form") & + (FormHistory.status == "Approved") & + (LaborStatusForm.termCode.in_([termCode,academicYearCode])) + ).group_by( + LaborStatusForm.department, + LaborStatusForm.termCode).dicts() + + breakSum = {"total_hours": 0} + if dept: + for row in breakAllocation: + if row["department"] == dept: + breakSum = row + break + # dictionary definition: usedPositions = { "used_10": countContracts("Primary", "10", termCode, dept), @@ -125,7 +103,7 @@ def getContractedAllocations(termCode: int, dept: int): "used_primaries": 0, "used_secondaries": 0, "used_total": 0, # all contracts with weekly hours, i.e. primaries + secondaries (not break contracts) - "break_hours": breakHoursTotal # all break hours contracted (but not necessarily worked) + "break_hours": breakSum["total_hours"] # all break hours contracted (but not necessarily worked) } usedPositions["used_primaries"] = sum(list(usedPositions.values())[:4]) usedPositions["used_secondaries"] = sum(list(usedPositions.values())[4:6]) diff --git a/app/logic/download.py b/app/logic/download.py index 50d040f5..b9532446 100644 --- a/app/logic/download.py +++ b/app/logic/download.py @@ -1,16 +1,13 @@ import csv -import io import json from flask import g -from fpdf import FPDF from peewee import ModelSelect from app.models.formHistory import * from app.controllers.main_routes.main_routes import * from app.models.studentLaborEvaluation import StudentLaborEvaluation from app.models.formSearchResult import FormSearchResult -from app.logic.getPositions import getPositionDescriptionSections def saveFormSearchResult(displayName, formList, formType): ids = [form.formHistoryID for form in formList] @@ -31,140 +28,6 @@ def retrieveFormSearchResult(formSearchResultId): return None -import html -import io - -from html.parser import HTMLParser -from fpdf import FPDF - - -class PDFHTMLTextExtractor(HTMLParser): - """ - Converts simple stored HTML into plain text suitable for FPDF. - """ - - blockTags = { - 'p','div','section','article','header','footer','h1','h2','h3','h4','h5','h6','li','ul','ol','br', - } - - def __init__(self): - super().__init__() - self.parts = [] - - def handle_starttag(self, tag, attrs): - tag = tag.lower() - - if tag == 'br': - self.parts.append('\n') - elif tag == 'li': - self.parts.append('\n• ') - - def handle_endtag(self, tag): - if tag.lower() in self.blockTags: - self.parts.append('\n') - - def handle_data(self, data): - self.parts.append(data) - - def getText(self): - text = ''.join(self.parts) - text = html.unescape(text) - - lines = [] - for line in text.splitlines(): - cleanedLine = ' '.join(line.split()) - - if cleanedLine: - lines.append(cleanedLine) - elif lines and lines[-1] != '': - lines.append('') - - return '\n'.join(lines).strip() - - -def removeHTML(value): - if value is None: - return '' - - parser = PDFHTMLTextExtractor() - parser.feed(str(value)) - parser.close() - - return parser.getText() - - -def makePositionDescriptionPDF(department, position): - """ - Builds a PDF of a position's description for the download button - on the individual position page. - """ - pdf = FPDF() - pdf.add_page() - - # Position title - pdf.set_font('Times', 'B', 16) - pdf.cell(0,10,removeHTML(position.positionTitle).encode('latin-1', 'replace').decode('latin-1'),ln=True) - pdf.ln(2) - - # Position metadata - fields = [ - ('Department Name', department.DEPT_NAME), - ('Position Code', position.positionCode), - ('WLS Level', position.wls), - ('Status', position.status), - ('Last Revision Date', position.revisionDate), - ('Revised By', position.revisedBy), - ] - - label_width = 45 - - for label, value in fields: - pdf.set_font('Times', 'B', 11) - pdf.cell(label_width, 8, f'{label}:', ln=False) - - plain_value = removeHTML(value).encode('latin-1', 'replace').decode('latin-1') - - pdf.set_font('Times', '', 11) - pdf.cell(0, 8, f' {plain_value}', ln=True) - - sections = getPositionDescriptionSections(position) - - pdf.ln(4) - - if sections: - for index, section in enumerate(sections): - title = removeHTML(section.sectionTitle).encode('latin-1', 'replace').decode('latin-1') - content = removeHTML(section.sectionContent).encode('latin-1', 'replace').decode('latin-1') - - # Horizontal rule before the description sections - if index == 0: - pdf.set_draw_color(180, 180, 180) - pdf.set_line_width(0.3) - y = pdf.get_y() - pdf.line(pdf.l_margin, y, pdf.w - pdf.r_margin, y) - pdf.ln(3) - - # Section heading - pdf.set_font('Times', 'B', 12) - pdf.multi_cell(0, 8, title) - - # Section content - pdf.set_font('Times', '', 11) - pdf.multi_cell(0, 5, content) - - pdf.ln(2) - - else: - pdf.set_font('Times', 'B', 12) - pdf.cell(0, 10, 'Description', ln=True) - - pdf.set_font('Times', '', 11) - pdf.multi_cell(0, 5, 'No description available.') - - pdf_bytes = pdf.output(dest='S').encode('latin-1', 'replace') - return io.BytesIO(pdf_bytes) - - class CSVMaker: ''' Create the CSV for the download bottons diff --git a/app/logic/getPositions.py b/app/logic/getPositions.py index 7410d7f7..67253f89 100644 --- a/app/logic/getPositions.py +++ b/app/logic/getPositions.py @@ -1,5 +1,4 @@ from app.models.positionHistory import PositionHistory -from app.models.positionDescriptionSection import PositionDescriptionSection def getActivePositions(dept): """ @@ -21,38 +20,8 @@ def getActivePositions(dept): return positionsList, posURL -def getPosition(dept, positionCode, revisionDate=None): - """ - Returns a single position for a given department, position code, and optional revision date. - If no revision date is provided, the most recent revision is returned. - """ - positionQuery = PositionHistory.select().where( - PositionHistory.department == dept, - PositionHistory.positionCode == positionCode - ) - - if revisionDate: - positionQuery = positionQuery.where(PositionHistory.revisionDate == revisionDate) - - return positionQuery.order_by(PositionHistory.revisionDate.desc()).first() - def getPositions(dept): - """ - Returns a list of all positions for a given department, ordered by position title. - """ return((PositionHistory.select() .where((PositionHistory.department == dept) & (PositionHistory.status == "Active")) - .order_by(PositionHistory.positionTitle.asc()))) - -def getPositionDescriptionSections(position): - """ - Returns the description sections for a given position, ordered for display. - """ - positionDescriptionSections = list(PositionDescriptionSection.select() - .where(PositionDescriptionSection.position == position) - .order_by(PositionDescriptionSection.order.asc())) - - return positionDescriptionSections - - + .order_by(PositionHistory.positionTitle.asc()))) \ No newline at end of file diff --git a/app/logic/getTerms.py b/app/logic/getTerms.py deleted file mode 100644 index 19df06ec..00000000 --- a/app/logic/getTerms.py +++ /dev/null @@ -1,47 +0,0 @@ -from app.models.term import Term -from datetime import datetime, date - -def getTerms(academicYear: str = None): - ''' - Gets 3 primary terms for the current/given Academic Year (AY) - This means it attempt to get an AY, fall term, and spring term - This returns all three objects individually for each of the terms. - Leaving no input variables means that it will check for the current year instead of a given one. - ''' - if academicYear: - # Uses only the first half of the AY since term codes are split by year. - # i.e. Fall 2026 -> 202611, while Spring 2027 -> 202612. - springTerm = Term.select().where(Term.termCode == int(academicYear[:4]) * 100 + 12).get() - currentAY = Term.select().where(Term.termCode == int(academicYear[:4]) * 100).get() - fallTerm = Term.select().where(Term.termCode == int(academicYear[:4]) * 100 + 11).get() - return currentAY, fallTerm, springTerm - - - else: - # If it is the spring semester, then the term code is 1 year behind. e.g. 2025-2026 term code is 202500. Thus the - 100 in the spring term. - # The (year * 100) turns the year into an AY term code, 2025 -> 202500. The + 12/11 turns it into a fall or spring term. - currentDate = date.today() - if currentDate.month <= 6: - springTerm = Term.select().where(Term.termCode == currentDate.year * 100 + 12 - 100).get() - currentAY = Term.select().where(Term.termCode == currentDate.year * 100 - 100).get() - fallTerm = Term.select().where(Term.termCode == currentDate.year * 100 + 11 - 100).get() - return currentAY, fallTerm, springTerm - - else: - fallTerm = Term.select().where(Term.termCode == currentDate.year * 100 + 11).get() - currentAY = Term.select().where(Term.termCode == currentDate.year * 100).get() - springTerm = Term.select().where(Term.termCode == currentDate.year * 100 + 12).get() - return currentAY, fallTerm, springTerm - -def getCurrentSemester(): - ''' - The difference between this function and the one above is that it gets just the current term - It does not get both Fall and Spring, it just gets one depending on the month. - ''' - currentDate = date.today() - if currentDate.month <= 6: - springTerm = Term.select().where(Term.termCode == currentDate.year * 100 + 12 - 100).get() - return springTerm - else: - fallTerm = Term.select().where(Term.termCode == currentDate.year * 100 + 11).get() - return fallTerm diff --git a/app/logic/manageDepartments.py b/app/logic/manageDepartments.py index 9f823c78..b6609276 100644 --- a/app/logic/manageDepartments.py +++ b/app/logic/manageDepartments.py @@ -13,6 +13,39 @@ from app.login_manager import require_login +def generateAdjacentYears(academicYearTermCode=None): + """ + Generates the current, and the following academic years. + """ + currentYear = g.openTerm.termCode // 100 + nextYear = currentYear + 1 + + currentAYCode = currentYear * 100 + nextAYCode = nextYear * 100 + + # Admins cannot view allocations for the years that are beyond the current, the previous, or the following academic year + if academicYearTermCode not in (None, currentAYCode, nextAYCode): + abort(400) + + + 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) + + + + +#################################################################################################################################### +# Everything below this line will eventually be deleted + def getUsedBreakHours(term): """ @@ -70,7 +103,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. """ @@ -79,24 +112,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/models/positionDescriptionSection.py b/app/models/positionDescriptionSection.py deleted file mode 100644 index 5488c315..00000000 --- a/app/models/positionDescriptionSection.py +++ /dev/null @@ -1,12 +0,0 @@ -from app.models import * -from app.models.positionHistory import PositionHistory - - -class PositionDescriptionSection (baseModel): - position = ForeignKeyField(PositionHistory) - sectionTitle = CharField() - sectionContent = TextField() - order = IntegerField() # Order of the sections in the position description - - - diff --git a/app/models/positionHistory.py b/app/models/positionHistory.py index fd38f26c..9a248aac 100644 --- a/app/models/positionHistory.py +++ b/app/models/positionHistory.py @@ -5,10 +5,10 @@ class PositionHistory(baseModel): positionTitle = CharField() positionCode = CharField() department = ForeignKeyField(Department) - status = CharField() # Active, Inactive, Requested + status = CharField() wls = IntegerField() revisionDate = DateField() - revisedBy = CharField() + description = TextField(default=None) class Meta: indexes = ( (('positionCode', 'revisionDate', 'status'), True), ) diff --git a/app/static/css/allocationTable.css b/app/static/css/allocationTable.css deleted file mode 100644 index ec248583..00000000 --- a/app/static/css/allocationTable.css +++ /dev/null @@ -1,65 +0,0 @@ -.grid-container { - display: grid; - grid-template-columns: 1fr 1fr; -} -.btn-success{ - align-self: center; - justify-self: end; -} -.card-header { - background-color: #efebeb; - margin-bottom: 7px; - height: 6rem; -} -.mb-0, .collapsed { - outline-color: none; - color: black; - font-size: 18px; - font-weight: 525; -} -.accordion{ - padding-left: 5%; - padding-right: 5%; -} -.table-striped { - table-layout:fixed; - width:100%; -} -.table-striped tbody tr:nth-of-type(odd) { - background-color: #f2f2f2; -} -.btn-info{ - justify-self:flex-end; - align-self: center; - margin-left: 4px -} -.accordion-arrow { - display: inline-block; - transition: transform 0.2s ease-in-out; -} -.btn.collapsed .accordion-arrow { - transform: rotate(-90deg); -} -.btn:not(.collapsed) .accordion-arrow { - transform: rotate(0deg); -} -.button-container { - display:flex; - justify-content:end; -} -.btn-block{ - align-items: center; - align-self: center; - text-align: left; - justify-content: center; - height: 100% -} -.termDisplay{ - margin-right:auto; -} -.bi-info-circle { - padding: 3px 3.5px 1.5px 3.5px; - font-size: 1.5rem; - vertical-align: middle; - color:#6e6e6e; -} \ No newline at end of file diff --git a/app/static/css/base.css b/app/static/css/base.css index 19b36fd2..a962b549 100755 --- a/app/static/css/base.css +++ b/app/static/css/base.css @@ -126,8 +126,8 @@ a { box-sizing: border-box; left: 280px; right: 0px; + width: calc(100vw - 280px); margin-right: 280px; - width: calc(100vw - 300px); } diff --git a/app/static/css/departmentPortal.css b/app/static/css/departmentPortal.css index cc67a896..d9acbba7 100644 --- a/app/static/css/departmentPortal.css +++ b/app/static/css/departmentPortal.css @@ -11,51 +11,36 @@ padding: 1rem; min-width: 100%; } -.bi-suitcase-lg-fill, -.bi-clock, -.bi-people-fill { - border: 1px solid #c0c0c0; - border-radius: 8px; - padding: 3px 3.5px 1.5px; - font-size: 3rem; - color: #6e6e6e; -} -.allocation-table-wrapper { - overflow-x: auto; - margin: 10px 0; -} -.allocation-summary { - display: flex; - flex-wrap: wrap; - justify-content: space-between; - align-items: baseline; - gap: 0 1rem; -} -.allocation-summary h4 { - margin: 10px 0; -} -.allocation-columns { - gap: 0 2rem; -} -.allocation-table { - border-collapse: collapse; - font-size: 1.05em; -} -.allocation-table th, -.allocation-table td { - text-align: left; - white-space: nowrap; - padding: 4px 0px; - line-height: 1.3; -} -.allocation-table th { - padding-top: 10px; +.members-icon { + display: inline-block; + border: 1px solid #c0c0c0; + border-radius: 8px; + padding: 3px 3.5px 1.5px; + font-size: 36px; + color: #6e6e6e; +} + margin-bottom: 20px; + min-height: 200px; +} +.bi-suitcase-lg-fill { /* Bootstrap Icon */ + border: 1px solid #c0c0c0; + border-radius: 8px; + padding: 3px 3.5px 1.5px 3.5px; + font-size: 3rem; + color:#6e6e6e; +} +.card-group { + gap: 1rem; } - .form-group { width: 50%; - margin: 0 auto; + margin-left: auto ; + margin-right:auto; +} +.card-body { + padding: 1rem 1rem; + min-width: 100% } .card-row { display: flex; @@ -67,15 +52,3 @@ flex-direction: column; } } - -/* Narrow card: stack Secondary below Primary, and the position count below the - term, rather than shrinking the text to keep them side by side. */ -@media (min-width: 1200px) and (max-width: 1450px), (max-width: 480px) { - .allocation-summary { - flex-direction: column; - gap: 0; - } - .allocation-columns .allocation-table { - flex-basis: 100%; - } -} diff --git a/app/static/css/individualPositions.css b/app/static/css/individualPositions.css deleted file mode 100644 index 9e22d584..00000000 --- a/app/static/css/individualPositions.css +++ /dev/null @@ -1,138 +0,0 @@ -/* Individual Positions page styles */ -/* Header */ -.department-header-container { - position: relative; -} - -.department-header { - text-align: center; - font-weight: 700; - margin-bottom: 5rem; -} - -.download-btn { - position: absolute; - top: 0; - right: 15px; -} - -.position-description div{ - width: 100%; - max-width: 100%; - box-sizing: border-box; -} -/* Metadata list (dt / dd spacing) */ -.position-information dl.row dt { - font-weight: 600; - color: #333; - text-align: left; - font-size: 2rem; -} -.position-information dl.row dd { - margin-bottom: 0.75rem; - color: #444; - text-align: left; - font-size: 2rem; -} - -h2.description-header { - font-weight: 600; - font-size: 2rem; -} - - -.position-description h3 { - font-size: 1.7rem; - font-weight: 600; - margin-top: 1.5rem; - margin-bottom: 0.5rem; -} - -.position-description h4 { - font-size: 1.25rem; - font-weight: 300; - margin-top: 1.25rem; - margin-bottom: 0.5rem; -} - -.position-description h5 { - font-size: 1.15rem; - font-weight: 600; - margin-top: 1rem; - margin-bottom: 0.35rem; -} - -.position-container { - margin: 2rem; -} - -.position-description { - text-align: left; - margin-top: 1rem; - margin-bottom: 2rem; - font-size: 1.25rem; - overflow-wrap: break-word; - word-wrap: break-word; -} - -.description-content { - margin: 0; - padding: 0; - width: 100%; - max-width: 100%; - box-sizing: border-box; - word-wrap: break-word; -} - -/* Individual description sections */ -.section-title { - margin-top: 20px; - margin-bottom: 10px; - font-weight: 700; - overflow-wrap: break-word; - word-wrap: break-word; -} - -.section-title:first-child { - margin-top: 0; -} - -/* Utility float class used across the app */ -.floatright { - float: right; - margin-left: 0.5rem; -} - -/* Mobile layout */ -@media (max-width: 750px) { - .download-btn { - position: static; - display: table; - max-width: 100%; - margin: 0 auto 20px; - white-space: normal; - } - - .department-header { - margin-bottom: 30px; - font-size: 28px; - } - - .position-information dl.row dt, - .position-information dl.row dd { - font-size: 1.6rem; - } - - .position-information dl.row dd { - margin-bottom: 15px; - } - - .position-description { - font-size: 1.2rem; - } - - .floatright { - float: none; - margin-left: 0; - } -} \ No newline at end of file diff --git a/app/static/css/sidebar.css b/app/static/css/sidebar.css index 8063dbf6..cb062a9f 100644 --- a/app/static/css/sidebar.css +++ b/app/static/css/sidebar.css @@ -65,7 +65,7 @@ .sidebar-push { left: 0 !important; - width: 95vw !important; + width: 100vw !important; margin-right: 0 !important; } diff --git a/app/static/js/allocationTable.js b/app/static/js/allocationTable.js deleted file mode 100644 index 8bda5cd1..00000000 --- a/app/static/js/allocationTable.js +++ /dev/null @@ -1,22 +0,0 @@ -$(document).ready( function(){ - function initTable(selector) { - return $(selector).DataTable({ - pageLength: 25, - info: false, - lengthChange: false, - searching: false, - paging: false, - order: [] - }); - } - - const fallTermPrimaries = initTable('#fallTermPrimaries'); - const fallTermSecondaries = initTable('#fallTermSecondaries'); - const springTermPrimaries = initTable('#springTermPrimaries'); - const springTermSecondaries = initTable('#springTermSecondaries'); - const breakTable = initTable('#breakTable'); -}); - -$(function () { - $('[data-toggle="tooltip"]').tooltip() -}) \ No newline at end of file diff --git a/app/static/js/departmentPortal.js b/app/static/js/departmentPortal.js index 856e4479..cb2023a3 100644 --- a/app/static/js/departmentPortal.js +++ b/app/static/js/departmentPortal.js @@ -3,4 +3,4 @@ $(document).ready(function() { deptData = $(this).find('option:selected').data(); window.location = `/department/${deptData.org}/${deptData.account}`; }); -}); \ No newline at end of file +}); diff --git a/app/templates/admin/manageDepartments.html b/app/templates/admin/manageDepartments.html index 88fcf297..abb4db22 100755 --- a/app/templates/admin/manageDepartments.html +++ b/app/templates/admin/manageDepartments.html @@ -91,69 +91,79 @@

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 %} + + {% if entry.allocation %} 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 + {% else %} + No current allocation + {% endif %} - - + - {% endfor %} + {%endfor%} diff --git a/app/templates/main/allocationTable.html b/app/templates/main/allocationTable.html deleted file mode 100644 index e7ccafcb..00000000 --- a/app/templates/main/allocationTable.html +++ /dev/null @@ -1,257 +0,0 @@ -{% extends "base.html" %} -{% block styles %} - {{super()}} - - -{% endblock %} - -{% block scripts %} - {{super()}} - - - -{% endblock %} - -{% block app_content %} - -

{% if department %} {{department.DEPT_NAME}} Allocations {% else %} Choose a Department: {% endif %}

- -
-

Current Term: {{currentAY.termName}}

- Download Allocation History - Request Allocation -
- -
- - -
-
- - -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PrimariesContractedAllocated
10 Hour{{fallContracts["used_10"]}}{{allocations["primary_10"]}}
12 Hour{{fallContracts["used_12"]}}{{allocations["primary_12"]}}
15 Hour{{fallContracts["used_15"]}}{{allocations["primary_15"]}}
20 Hour{{fallContracts["used_20"]}}{{allocations["primary_20"]}}
Total Primaries{{fallContracts["used_primaries"]}}{{allocations["totalPrimaries"]}}
Total Contracts{{fallContracts["used_total"]}}{{allocations["totalAllocations"]}}
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SecondariesContractedAllocated
5 Hour{{fallContracts["used_5_sec"]}}{{allocations["secondary_5"]}}
10 Hour{{fallContracts["used_10_sec"]}}{{allocations["secondary_10"]}}
Total Secondaries{{fallContracts["used_secondaries"]}}{{allocations["totalSecondaries"]}}
Total Contracts{{fallContracts["used_total"]}}{{allocations["totalAllocations"]}}
-
-
- - -
-
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PrimariesContractedAllocated
10 Hour{{springContracts["used_10"]}}{{allocations["primary_10"]}}
12 Hour{{springContracts["used_12"]}}{{allocations["primary_12"]}}
15 Hour{{springContracts["used_15"]}}{{allocations["primary_15"]}}
20 Hour{{springContracts["used_20"]}}{{allocations["primary_20"]}}
Total Primaries{{springContracts["used_primaries"]}}{{allocations["totalPrimaries"]}}
Total Contracts{{springContracts["used_total"]}}{{allocations["totalAllocations"]}}
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SecondariesContractedAllocated
5 Hour{{springContracts["used_5_sec"]}}{{allocations["secondary_5"]}}
10 Hour{{springContracts["used_10_sec"]}}{{allocations["secondary_10"]}}
Total Secondaries{{springContracts["used_secondaries"]}}{{allocations["totalSecondaries"]}}
Total Contracts{{springContracts["used_total"]}}{{allocations["totalAllocations"]}}
-
-
- - -
-
- - -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PrimariesContractedAllocated
Fall Break{{breakContracts['fall']}}
Thanksgiving{{breakContracts['thanksgiving']}}
Winter Break{{breakContracts['winter']}}
Spring Break{{breakContracts['spring']}}
Summer Term{{breakContracts['summer']}}
Total Break Hours {{breakContracts['total']}}{{allocations["breakHours"]}}
-
-
- -
-{% endblock %} diff --git a/app/templates/main/departmentPortal.html b/app/templates/main/departmentPortal.html index dfdc5423..e7786c85 100644 --- a/app/templates/main/departmentPortal.html +++ b/app/templates/main/departmentPortal.html @@ -33,52 +33,10 @@

{% if department %} {{department.DEPT_NAME}} Portal {% e {% if department %}
-
-
-
-
- -
-
-

Current Allocations

-
- {% macro allocationRow(hours, used, allocated) -%} - {{ hours }} hr: {{ used }} contract{{ 's' if used != 1 else '' }} out of {{ allocated if allocated is integer else 0 }} allocation{{ 's' if allocated != 1 else '' }} - {%- endmacro %} -
-
-

{{ currentSemester }}

-

{{contracts["used_total"]}} contracted of {{allocation["totalAllocations"] if allocation["totalAllocations"] is integer else 0}} allocations

-
-
- - - - - - {{ allocationRow(10, contracts["used_10"], allocation["primary_10"]) }} - {{ allocationRow(12, contracts["used_12"], allocation["primary_12"]) }} - {{ allocationRow(15, contracts["used_15"], allocation["primary_15"]) }} - {{ allocationRow(20, contracts["used_20"], allocation["primary_20"]) }} - -
Primary
- - - - - - {{ allocationRow(5,contracts["used_5_sec"], allocation["secondary_5"]) }} - {{ allocationRow(10, contracts["used_10_sec"], allocation["secondary_10"]) }} - -
Secondary
-
-
-
-
+
+

Insert Allocations Card Here

diff --git a/app/templates/main/individualPositions.html b/app/templates/main/individualPositions.html deleted file mode 100644 index 87bd44ba..00000000 --- a/app/templates/main/individualPositions.html +++ /dev/null @@ -1,68 +0,0 @@ -{% extends "base.html" %} - -{% block scripts %} - {{ super() }} - - -{% endblock %} - -{% block app_content %} -
- - Download Description - -

{{ department.DEPT_NAME }}

-
- -
-
-
- -
-
-
Position Title:
-
{{ position.positionTitle }}
- -
Position Code:
-
{{ position.positionCode }}
- -
WLS Level:
-
{{ position.wls }}
- -
Status:
-
{{ position.status }}
- -
Last Revision Date:
-
{{ position.revisionDate }}
- -
Revised By:
-
{{ position.revisedBy }}
-
-
- -

Description:

-
- {%- if sections %} - {%- for section in sections %} -
{{ section.sectionTitle |safe }}
-
{{ section.sectionContent |safe }}
- {%- endfor %} - {%- else %} -

No description available.

- {%- endif %} -
- -
- -
- -
-
-
-{% endblock %} \ No newline at end of file diff --git a/app/templates/main/managePositions.html b/app/templates/main/managePositions.html index 81b139d4..1d6dd8c6 100644 --- a/app/templates/main/managePositions.html +++ b/app/templates/main/managePositions.html @@ -29,12 +29,11 @@

{{ department_name }} Positions

{% for position in positions %} - {{ position.positionTitle }} {{ position.positionCode }} + {{ position.positionTitle }} {{ position.positionCode }} {{ position.wls }} {{ position.revisionDate }} - View + diff --git a/database/demo_data.py b/database/demo_data.py index 50467da2..5358a7ba 100644 --- a/database/demo_data.py +++ b/database/demo_data.py @@ -14,13 +14,11 @@ from app.models.user import User from app.models.term import Term from app.models.laborStatusForm import LaborStatusForm -from app.models.laborReleaseForm import LaborReleaseForm from app.models.formHistory import FormHistory from app.models.notes import Notes from app.models.supervisorDepartment import SupervisorDepartment from app.models.allocation import Allocation from app.models.positionHistory import PositionHistory -from app.models.positionDescriptionSection import PositionDescriptionSection print("Inserting data for demo and testing purposes") @@ -42,37 +40,8 @@ "STU_CPO":"700", "LAST_POSN":"Media Technician", "LAST_SUP_PIDM":"7" - }, - { - "ID":"B00741361", - "PIDM":"99", - "FIRST_NAME":"Antonia", - "LAST_NAME":"Schmith", - "CLASS_LEVEL":"Freshman", - "ACADEMIC_FOCUS":"Computer Science", - "MAJOR":"Computer Science", - "PROBATION":"0", - "ADVISOR":"Scott Heggen", - "STU_EMAIL":"schmitha@berea.edu", - "STU_CPO":"777", - "LAST_POSN":"TA", - "LAST_SUP_PIDM":"7" - }, - { - "ID":"B00732363", - "PIDM":"58", - "FIRST_NAME":"Barbara", - "LAST_NAME":"Williams", - "CLASS_LEVEL":"Junior", - "ACADEMIC_FOCUS":"Computer Science", - "MAJOR":"Computer Science", - "PROBATION":"0", - "ADVISOR":"Jasmine Jones", - "STU_EMAIL":"williamsb@berea.edu", - "STU_CPO":"118", - "LAST_POSN":"TA", - "LAST_SUP_PIDM":"7" }, + { "ID":"B00730361", "PIDM":"1", @@ -135,26 +104,7 @@ "LAST_POSN":"Student Manager", "LAST_SUP_PIDM":"7" }, - {"ID": "B00811617", "legal_name": "Chris Georgiev", "isActive": True, "PIDM": "8", "FIRST_NAME": "Chris", "LAST_NAME": "Georgiev"}, - {"ID": "B00815474", "legal_name": "Julius Fritz", "isActive": True, "PIDM": "9", "FIRST_NAME": "Julius", "LAST_NAME": "Fritz"}, - {"ID": "B12345223", "legal_name": "Subaru Natsuki", "isActive": True, "PIDM": "10", "FIRST_NAME": "Subaru", "LAST_NAME": "Natsuki"}, - {"ID": "B12345003", "legal_name": "Hatsune Miku", "isActive": True, "PIDM": "11", "FIRST_NAME": "Hatsune", "LAST_NAME": "Miku"}, - {"ID": "B12345772", "legal_name": "Michael Jackson", "isActive": True, "PIDM": "12", "FIRST_NAME": "Michael", "LAST_NAME": "Jackson"}, - {"ID": "B12345756", "legal_name": "Genji Overwatch", "isActive": True, "PIDM": "13", "FIRST_NAME": "Genji", "LAST_NAME": "Overwatch"}, - {"ID": "B12345759", "legal_name": "Mister Marlowe", "isActive": True, "PIDM": "14", "FIRST_NAME": "Mister", "LAST_NAME": "Marlowe"}, - {"ID": "B11231123", "legal_name": "Mister Thanksgiving", "isActive": True, "PIDM": "15", "FIRST_NAME": "Mister", "LAST_NAME": "Thanksgiving"}, - {"ID": "B12345762", "legal_name": "Alex Carter", "isActive": True, "PIDM": "16", "FIRST_NAME": "Alex", "LAST_NAME": "Carter"}, - {"ID": "B12345763", "legal_name": "Morgan Hayes", "isActive": True, "PIDM": "17", "FIRST_NAME": "Morgan", "LAST_NAME": "Hayes"}, - {"ID": "B12345764", "legal_name": "Jordan Brooks", "isActive": True, "PIDM": "18", "FIRST_NAME": "Jordan", "LAST_NAME": "Brooks"}, - {"ID": "B12345765", "legal_name": "Taylor Morgan", "isActive": True, "PIDM": "19", "FIRST_NAME": "Taylor", "LAST_NAME": "Morgan"}, - {"ID": "B12345766", "legal_name": "Casey Turner", "isActive": True, "PIDM": "20", "FIRST_NAME": "Casey", "LAST_NAME": "Turner"}, - {"ID": "B12345767", "legal_name": "Jamie Foster", "isActive": True, "PIDM": "21", "FIRST_NAME": "Jamie", "LAST_NAME": "Foster"}, - {"ID": "B12345768", "legal_name": "Riley Cooper", "isActive": True, "PIDM": "22", "FIRST_NAME": "Riley", "LAST_NAME": "Cooper"}, - {"ID": "B12345769", "legal_name": "Drew Bennett", "isActive": True, "PIDM": "23", "FIRST_NAME": "Drew", "LAST_NAME": "Bennett"}, - {"ID": "B12345770", "legal_name": "Logan Price", "isActive": True, "PIDM": "24", "FIRST_NAME": "Logan", "LAST_NAME": "Price"}, - {"ID": "B12345771", "legal_name": "Avery Sullivan", "isActive": True, "PIDM": "25", "FIRST_NAME": "Avery", "LAST_NAME": "Sullivan"}, - - ] + ] tracyStudents = [ { "ID":"B00785329", @@ -511,22 +461,6 @@ "isSaasAdmin": None }, { - "student": "B00741361", - "supervisor": None, - "username": "schmitha", - "isLaborAdmin": None, - "isFinancialAidAdmin": None, - "isSaasAdmin": None - }, - { - "student": "B00732363", - "supervisor": None, - "username": "williamsb", - "isLaborAdmin": None, - "isFinancialAidAdmin": None, - "isSaasAdmin": None - }, - { "student": "B00730361", "supervisor": None, "username": "jamalie", @@ -821,90 +755,107 @@ "createdDate": f"2025-04-14", "status_id": "Pending" }]).on_conflict_replace().execute() + LaborStatusForm.insert([{ - "laborStatusFormID": 11, + "laborStatusFormID": 3, "termCode_id": f"202500", - "studentName": "Antonia Schmith", - "studentSupervisee_id": "B00741361", + "studentName": "Test Taker", + "studentSupervisee_id": "B12345773", "supervisor_id": "B12361006", - "department_id": 1, + "department_id": 5, "jobType": "Primary", "WLS": 1, - "POSN_TITLE": "Student Programmer", - "POSN_CODE": "S61407", + "POSN_TITLE": "Labor Workers", + "POSN_CODE": "S61409", "weeklyHours": 10, - "startDate": f"2026-04-01", - "endDate": f"2026-09-01", - "studentConfirmation": True + "startDate": f"2025-04-01", + "endDate": "2025-09-01" }]).on_conflict_replace().execute() FormHistory.insert([{ - "formHistoryID": 11, - "formID_id": "11", + "formHistoryID": 3, + "formID_id": "3", "historyType_id": "Labor Status Form", "createdBy_id": 1, "createdDate": f"2025-04-14", - "status": "Approved" + "status_id": "Approved" }]).on_conflict_replace().execute() + +############################# +# Create Active Labor Status Form for the Break Term +############################# + +# cs department + LaborStatusForm.insert([{ - "laborStatusFormID": 12, + "laborStatusFormID": 6, "termCode_id": f"202500", - "studentName": "Barbara Williams", - "studentSupervisee_id": "B00732363", + "studentName": "Pizza Taker", + "studentSupervisee_id": "B12345773", "supervisor_id": "B12361006", "department_id": 1, "jobType": "Primary", "WLS": 1, - "POSN_TITLE": "Student Programmer", - "POSN_CODE": "S61407", - "weeklyHours": 10, - "startDate": f"2027-04-01", - "endDate": f"2029-09-01", - "studentConfirmation": True + "POSN_TITLE": "Media Technician", + "POSN_CODE": "S61409", + "contractHours": 15, + "startDate": f"2025-04-01", + "endDate": "2025-09-01" }]).on_conflict_replace().execute() FormHistory.insert([{ - "formHistoryID": 12, - "formID_id": "12", + "formHistoryID": 6, + "formID_id": "6", "historyType_id": "Labor Status Form", "createdBy_id": 1, "createdDate": f"2025-04-14", - "status": "Approved" - }]).on_conflict_replace().execute() + "status_id": "Approved" + }]).on_conflict_replace().execute() -LaborReleaseForm.insert([{ - "laborReleaseFormID": 10, - "conditionAtRelease": "unsatisfactory", - "releaseDate": f"2025-04-14", - "reasonForRelease": "Smoking Cigarettes in the Programmers' space." - }]).on_conflict_replace().execute() +LaborStatusForm.insert([{ + "laborStatusFormID": 7, + "termCode_id": f"202500", + "studentName": "Elaheh Jamali", + "studentSupervisee_id": "B00730361", + "supervisor_id": "B12361006", + "department_id": 1, + "jobType": "Primary", + "WLS": 1, + "POSN_TITLE": "Media Technician", + "POSN_CODE": "S61409", + "contractHours": 3, + "startDate": f"2025-04-01", + "endDate": "2025-09-01" + }]).on_conflict_replace().execute() FormHistory.insert([{ - "formHistoryID": 13, - "formID_id": "12", - "historyType_id": "Labor Release Form", - "releaseForm": 10, + "formHistoryID": 7, + "formID_id": "7", + "historyType_id": "Labor Status Form", "createdBy_id": 1, "createdDate": f"2025-04-14", - "status": "Approved" - }]).on_conflict_replace().execute() + "status_id": "Approved" + }]).on_conflict_replace().execute() + + +# labor department LaborStatusForm.insert([{ "laborStatusFormID": 4, "termCode_id": f"202500", - "studentName": "Elaleh Jamali", + "studentName": "Elaheh Jamali", "studentSupervisee_id": "B00730361", "supervisor_id": "B12361006", - "department_id": 1, + "department_id": 5, "jobType": "Secondary", "WLS": 1, - "POSN_TITLE": "Labor Workers", - "POSN_CODE": "S61419", - "weeklyHours": 10, - "startDate": f"2027-04-01", - "endDate": "2027-09-01" - }]).on_conflict_replace().execute() + "POSN_TITLE": "Media Technician", + "POSN_CODE": "S61409", + "contractHours": 5, + "startDate": f"2025-04-01", + "endDate": "2025-09-01" + }]).on_conflict_replace().execute() FormHistory.insert([{ "formHistoryID": 4, @@ -912,24 +863,24 @@ "historyType_id": "Labor Status Form", "createdBy_id": 1, "createdDate": f"2025-04-14", - "status": "Approved" - }]).on_conflict_replace().execute() + "status_id": "Approved" + }]).on_conflict_replace().execute() LaborStatusForm.insert([{ "laborStatusFormID": 5, "termCode_id": f"202500", - "studentName": "Oluwagbayi Makinde", - "studentSupervisee_id": "B00791326", - "supervisor_id": "B12365892", - "department_id": 1, - "jobType": "Primary", + "studentName": "Elaheh Jamali", + "studentSupervisee_id": "B00730361", + "supervisor_id": "B12361006", + "department_id": 5, + "jobType": "Secondary", "WLS": 1, - "POSN_TITLE": "Labor Workers", - "POSN_CODE": "S61429", - "weeklyHours": 10, + "POSN_TITLE": "Media Technician", + "POSN_CODE": "S61409", + "contractHours": 5, "startDate": f"2025-04-01", - "endDate": "2029-09-01" - }]).on_conflict_replace().execute() + "endDate": "2025-09-01" + }]).on_conflict_replace().execute() FormHistory.insert([{ "formHistoryID": 5, @@ -937,50 +888,52 @@ "historyType_id": "Labor Status Form", "createdBy_id": 1, "createdDate": f"2025-04-14", - "status": "Approved" - }]).on_conflict_replace().execute() + "status_id": "Approved" + }]).on_conflict_replace().execute() + +# Biology Department LaborStatusForm.insert([{ - "laborStatusFormID": 3, + "laborStatusFormID": 8, "termCode_id": f"202500", - "studentName": "Test Taker", - "studentSupervisee_id": "B12345773", + "studentName": "Elaheh Jamali", + "studentSupervisee_id": "B00730361", "supervisor_id": "B12361006", - "department_id": 5, + "department_id": 4, "jobType": "Primary", "WLS": 1, - "POSN_TITLE": "Labor Workers", + "POSN_TITLE": "Media Technician", "POSN_CODE": "S61409", - "weeklyHours": 10, + "contractHours": 5, "startDate": f"2025-04-01", "endDate": "2025-09-01" - }]).on_conflict_replace().execute() + }]).on_conflict_replace().execute() FormHistory.insert([{ - "formHistoryID": 3, - "formID_id": "3", + "formHistoryID": 8, + "formID_id": "8", "historyType_id": "Labor Status Form", "createdBy_id": 1, "createdDate": f"2025-04-14", "status_id": "Approved" - }]).on_conflict_replace().execute() + }]).on_conflict_replace().execute() + LaborStatusForm.insert([{ - "laborStatusFormID": 9, "termCode_id": f"202500", - "studentName": "Genji Overwatch", - "studentSupervisee_id": "B12345756", + "studentName": "Elaheh Jamali", + "studentSupervisee_id": "B00730361", "supervisor_id": "B12361006", - "department_id": 1, - "jobType": "Primary", + "department_id": 4, + "jobType": "Secondary", "WLS": 1, - "POSN_TITLE": "overwtahc guy", - "POSN_CODE": "S61410", - "contractHours": 15, + "POSN_TITLE": "Media Technician", + "POSN_CODE": "S61409", + "contractHours": 5, "startDate": f"2025-04-01", "endDate": "2025-09-01" - }]).on_conflict_replace().execute() + FormHistory.insert([{ "formHistoryID": 9, "formID_id": "9", @@ -988,757 +941,631 @@ "createdBy_id": 1, "createdDate": f"2025-04-14", "status_id": "Approved" - }]).on_conflict_replace().execute() -LaborStatusForm.insert([{ + }]).on_conflict_replace().execute() - "laborStatusFormID": 60, +# Mathematics Department + +LaborStatusForm.insert([{ + "laborStatusFormID": 10, "termCode_id": f"202500", - "studentName": "Mister Marlowe", - "studentSupervisee_id": "B12345759", + "studentName": "Elaheh Jamali", + "studentSupervisee_id": "B00730361", "supervisor_id": "B12361006", - "department_id": 1, + "department_id": 3, "jobType": "Primary", "WLS": 1, - "POSN_TITLE": "Break Worker", - "POSN_CODE": "S61412", - "contractHours": 400, + "POSN_TITLE": "Media Technician", + "POSN_CODE": "S61409", + "contractHours": 5, "startDate": f"2025-04-01", "endDate": "2025-09-01" - }]).on_conflict_replace().execute() + FormHistory.insert([{ - "formHistoryID": 60, - "formID_id": "60", + "formHistoryID": 10, + "formID_id": "10", "historyType_id": "Labor Status Form", "createdBy_id": 1, "createdDate": f"2025-04-14", "status_id": "Approved" - }]).on_conflict_replace().execute() -LaborStatusForm.insert([{ + }]).on_conflict_replace().execute() - "laborStatusFormID": 61, - "termCode_id": f"202501", - "studentName": "Mister Thanksgiving", - "studentSupervisee_id": "B11231123", +LaborStatusForm.insert([{ + "laborStatusFormID": 11, + "termCode_id": f"202500", + "studentName": "Elaheh Jamali", + "studentSupervisee_id": "B00730361", "supervisor_id": "B12361006", - "department_id": 1, - "jobType": "Primary", + "department_id": 3, + "jobType": "Secondary", "WLS": 1, - "POSN_TITLE": "Thanksgiving Worker", - "POSN_CODE": "S61412", - "contractHours": 50, - "startDate": f"2025-11-23", - "endDate": "2025-12-01" - + "POSN_TITLE": "Media Technician", + "POSN_CODE": "S61409", + "contractHours": 5, + "startDate": f"2025-04-01", + "endDate": "2025-09-01" }]).on_conflict_replace().execute() + FormHistory.insert([{ - "formHistoryID": 61, - "formID_id": "61", + "formHistoryID": 11, + "formID_id": "11", "historyType_id": "Labor Status Form", "createdBy_id": 1, - "createdDate": f"2025-11-01", + "createdDate": f"2025-04-14", "status_id": "Approved" - }]).on_conflict_replace().execute() - -LaborStatusForm.insert([{ - "laborStatusFormID": 62, - "termCode_id": "202611", - "studentName": "Alex Carter", - "studentSupervisee_id": "B12345762", - "supervisor_id": "B12361006", - "department_id": 1, - "jobType": "Primary", - "WLS": 1, - "POSN_TITLE": "Office Assistant", - "POSN_CODE": "S61413", - "weeklyHours": 10, - "startDate": "2026-08-15", - "endDate": "2026-12-15" -}]).on_conflict_replace().execute() - -FormHistory.insert([{ - "formHistoryID": 62, - "formID_id": "62", - "historyType_id": "Labor Status Form", - "createdBy_id": 1, - "createdDate": "2026-08-01", - "status_id": "Approved" -}]).on_conflict_replace().execute() + }]).on_conflict_replace().execute() +#Technology and Applied Design Department LaborStatusForm.insert([{ - "laborStatusFormID": 63, - "termCode_id": "202611", - "studentName": "Morgan Hayes", - "studentSupervisee_id": "B12345763", - "supervisor_id": "B12361006", - "department_id": 1, - "jobType": "Primary", - "WLS": 1, - "POSN_TITLE": "Computer Lab Assistant", - "POSN_CODE": "S61414", - "weeklyHours": 15, - "startDate": "2026-08-15", - "endDate": "2026-12-15" -}]).on_conflict_replace().execute() + "laborStatusFormID": 12, + "termCode_id": f"202500", + "studentName": "Elaheh Jamali", + "studentSupervisee_id": "B00730361", + "supervisor_id": "B12361006", + "department_id": 2, + "jobType": "Secondary", + "WLS": 1, + "POSN_TITLE": "Media Technician", + "POSN_CODE": "S61409", + "contractHours": 5, + "startDate": f"2025-04-01", + "endDate": "2025-09-01" + }]).on_conflict_replace().execute() FormHistory.insert([{ - "formHistoryID": 63, - "formID_id": "63", - "historyType_id": "Labor Status Form", - "createdBy_id": 1, - "createdDate": "2026-08-01", - "status_id": "Approved" -}]).on_conflict_replace().execute() - + "formHistoryID": 12, + "formID_id": "12", + "historyType_id": "Labor Status Form", + "createdBy_id": 1, + "createdDate": f"2025-04-14", + "status_id": "Approved" + }]).on_conflict_replace().execute() LaborStatusForm.insert([{ - "laborStatusFormID": 64, - "termCode_id": "202611", - "studentName": "Jordan Brooks", - "studentSupervisee_id": "B12345764", - "supervisor_id": "B12361006", - "department_id": 1, - "jobType": "Primary", - "WLS": 1, - "POSN_TITLE": "Help Desk Assistant", - "POSN_CODE": "S61415", - "weeklyHours": 20, - "startDate": "2026-08-15", - "endDate": "2026-12-15" -}]).on_conflict_replace().execute() - -FormHistory.insert([{ - "formHistoryID": 64, - "formID_id": "64", - "historyType_id": "Labor Status Form", - "createdBy_id": 1, - "createdDate": "2026-08-01", - "status_id": "Approved" -}]).on_conflict_replace().execute() - - -LaborStatusForm.insert([{ - "laborStatusFormID": 65, - "termCode_id": "202611", - "studentName": "Taylor Morgan", - "studentSupervisee_id": "B12345765", - "supervisor_id": "B12361006", - "department_id": 1, - "jobType": "Secondary", - "WLS": 0, - "POSN_TITLE": "Reception Assistant", - "POSN_CODE": "S61416", - "weeklyHours": 5, - "startDate": "2026-08-15", - "endDate": "2026-12-15" -}]).on_conflict_replace().execute() - -FormHistory.insert([{ - "formHistoryID": 65, - "formID_id": "65", - "historyType_id": "Labor Status Form", - "createdBy_id": 1, - "createdDate": "2026-08-01", - "status_id": "Approved" -}]).on_conflict_replace().execute() - - -LaborStatusForm.insert([{ - "laborStatusFormID": 66, - "termCode_id": "202611", - "studentName": "Casey Turner", - "studentSupervisee_id": "B12345766", - "supervisor_id": "B12361006", - "department_id": 1, - "jobType": "Secondary", - "WLS": 0, - "POSN_TITLE": "Library Assistant", - "POSN_CODE": "S61417", - "weeklyHours": 10, - "startDate": "2026-08-15", - "endDate": "2026-12-15" -}]).on_conflict_replace().execute() - -FormHistory.insert([{ - "formHistoryID": 66, - "formID_id": "66", - "historyType_id": "Labor Status Form", - "createdBy_id": 1, - "createdDate": "2026-08-01", - "status_id": "Approved" -}]).on_conflict_replace().execute() - -LaborStatusForm.insert([{ - "laborStatusFormID": 72, - "termCode_id": "202612", - "studentName": "Alex Carter", - "studentSupervisee_id": "B12345762", - "supervisor_id": "B12361006", - "department_id": 1, - "jobType": "Primary", - "WLS": 1, - "POSN_TITLE": "Office Assistant", - "POSN_CODE": "S61413", - "weeklyHours": 10, - "startDate": "2027-01-15", - "endDate": "2027-05-15" -}]).on_conflict_replace().execute() - -FormHistory.insert([{ - "formHistoryID": 72, - "formID_id": "72", - "historyType_id": "Labor Status Form", - "createdBy_id": 1, - "createdDate": "2027-01-05", - "status_id": "Approved" -}]).on_conflict_replace().execute() - - -LaborStatusForm.insert([{ - "laborStatusFormID": 73, - "termCode_id": "202612", - "studentName": "Morgan Hayes", - "studentSupervisee_id": "B12345763", - "supervisor_id": "B12361006", - "department_id": 1, - "jobType": "Primary", - "WLS": 1, - "POSN_TITLE": "Computer Lab Assistant", - "POSN_CODE": "S61414", - "weeklyHours": 15, - "startDate": "2027-01-15", - "endDate": "2027-05-15" -}]).on_conflict_replace().execute() - -FormHistory.insert([{ - "formHistoryID": 73, - "formID_id": "73", - "historyType_id": "Labor Status Form", - "createdBy_id": 1, - "createdDate": "2027-01-05", - "status_id": "Approved" -}]).on_conflict_replace().execute() - - -LaborStatusForm.insert([{ - "laborStatusFormID": 74, - "termCode_id": "202612", - "studentName": "Taylor Morgan", - "studentSupervisee_id": "B12345765", - "supervisor_id": "B12361006", - "department_id": 1, - "jobType": "Secondary", - "WLS": 0, - "POSN_TITLE": "Reception Assistant", - "POSN_CODE": "S61416", - "weeklyHours": 5, - "startDate": "2027-01-15", - "endDate": "2027-05-15" -}]).on_conflict_replace().execute() - -FormHistory.insert([{ - "formHistoryID": 74, - "formID_id": "74", - "historyType_id": "Labor Status Form", - "createdBy_id": 1, - "createdDate": "2027-01-05", - "status_id": "Approved" -}]).on_conflict_replace().execute() - - -# Student had a Fall-only position and receives a new Spring assignment. - -LaborStatusForm.insert([{ - "laborStatusFormID": 75, - "termCode_id": "202612", - "studentName": "Jordan Brooks", - "studentSupervisee_id": "B12345764", - "supervisor_id": "B12361006", - "department_id": 1, - "jobType": "Primary", - "WLS": 1, - "POSN_TITLE": "Technology Assistant", - "POSN_CODE": "S61423", - "weeklyHours": 12, - "startDate": "2027-01-15", - "endDate": "2027-05-15" -}]).on_conflict_replace().execute() - -FormHistory.insert([{ - "formHistoryID": 75, - "formID_id": "75", - "historyType_id": "Labor Status Form", - "createdBy_id": 1, - "createdDate": "2027-01-05", - "status_id": "Approved" -}]).on_conflict_replace().execute() - -LaborStatusForm.insert([{ - "laborStatusFormID": 76, - "termCode_id": "202600", - "studentName": "Jordan Brooks", - "studentSupervisee_id": "B12345764", - "supervisor_id": "B12361006", - "department_id": 1, - "jobType": "Secondary", - "WLS": 1, - "POSN_TITLE": "Technology Assistant", - "POSN_CODE": "S61423", - "weeklyHours": 10, - "startDate": "2027-01-15", - "endDate": "2027-05-15" -}]).on_conflict_replace().execute() - -FormHistory.insert([{ - "formHistoryID": 76, - "formID_id": "76", - "historyType_id": "Labor Status Form", - "createdBy_id": 1, - "createdDate": "2027-01-05", - "status_id": "Approved" -}]).on_conflict_replace().execute() - - -# Break Positions - -LaborStatusForm.insert([{ - "laborStatusFormID": 67, - "termCode_id": "202601", - "studentName": "Jamie Foster", - "studentSupervisee_id": "B12345767", - "supervisor_id": "B12361006", - "department_id": 1, - "jobType": "Primary", - "WLS": 1, - "POSN_TITLE": "Thanksgiving Worker", - "POSN_CODE": "S61418", - "contractHours": 40, - "startDate": "2026-11-22", - "endDate": "2026-11-29" -}]).on_conflict_replace().execute() - -LaborStatusForm.insert([{ - "laborStatusFormID": 68, - "termCode_id": "202602", - "studentName": "Riley Cooper", - "studentSupervisee_id": "B12345768", - "supervisor_id": "B12361006", - "department_id": 1, - "jobType": "Primary", - "WLS": 1, - "POSN_TITLE": "Christmas Worker", - "POSN_CODE": "S61419", - "contractHours": 120, - "startDate": "2026-12-20", - "endDate": "2027-01-03" -}]).on_conflict_replace().execute() - -LaborStatusForm.insert([{ - "laborStatusFormID": 69, - "termCode_id": "202603", - "studentName": "Drew Bennett", - "studentSupervisee_id": "B12345769", - "supervisor_id": "B12361006", - "department_id": 1, - "jobType": "Primary", - "WLS": 1, - "POSN_TITLE": "Spring Break Worker", - "POSN_CODE": "S61420", - "contractHours": 80, - "startDate": "2027-03-07", - "endDate": "2027-03-14" -}]).on_conflict_replace().execute() - -LaborStatusForm.insert([{ - "laborStatusFormID": 70, - "termCode_id": "202604", - "studentName": "Logan Price", - "studentSupervisee_id": "B12345770", - "supervisor_id": "B12361006", - "department_id": 1, - "jobType": "Primary", - "WLS": 1, - "POSN_TITLE": "Fall Break Worker", - "POSN_CODE": "S61421", - "contractHours": 24, - "startDate": "2026-10-11", - "endDate": "2026-10-18" -}]).on_conflict_replace().execute() - -LaborStatusForm.insert([{ - "laborStatusFormID": 71, - "termCode_id": "202613", - "studentName": "Avery Sullivan", - "studentSupervisee_id": "B12345771", - "supervisor_id": "B12361006", - "department_id": 1, - "jobType": "Primary", - "WLS": 1, - "POSN_TITLE": "Summer Worker", - "POSN_CODE": "S61422", - "contractHours": 320, - "startDate": "2027-05-15", - "endDate": "2027-08-01" -}]).on_conflict_replace().execute() - -FormHistory.insert([{ - "formHistoryID": 67, - "formID_id": "67", - "historyType_id": "Labor Status Form", - "createdBy_id": 1, - "createdDate": "2026-11-01", - "status_id": "Approved" -}]).on_conflict_replace().execute() - -FormHistory.insert([{ - "formHistoryID": 68, - "formID_id": "68", - "historyType_id": "Labor Status Form", - "createdBy_id": 1, - "createdDate": "2026-12-01", - "status_id": "Approved" -}]).on_conflict_replace().execute() - -FormHistory.insert([{ - "formHistoryID": 69, - "formID_id": "69", - "historyType_id": "Labor Status Form", - "createdBy_id": 1, - "createdDate": "2027-02-20", - "status_id": "Approved" -}]).on_conflict_replace().execute() - -FormHistory.insert([{ - "formHistoryID": 70, - "formID_id": "70", - "historyType_id": "Labor Status Form", - "createdBy_id": 1, - "createdDate": "2026-10-01", - "status_id": "Approved" -}]).on_conflict_replace().execute() - -FormHistory.insert([{ - "formHistoryID": 71, - "formID_id": "71", - "historyType_id": "Labor Status Form", - "createdBy_id": 1, - "createdDate": "2027-04-15", - "status_id": "Approved" -}]).on_conflict_replace().execute() -############################# -# Create Active Labor Status Form for the Break Term -############################# - -# cs department - -LaborStatusForm.insert([{ - "laborStatusFormID": 6, + "laborStatusFormID": 13, "termCode_id": f"202500", - "studentName": "Pizza Taker", - "studentSupervisee_id": "B12345773", + "studentName": "Elaheh Jamali", + "studentSupervisee_id": "B00730361", "supervisor_id": "B12361006", - "department_id": 1, + "department_id": 2, "jobType": "Primary", "WLS": 1, "POSN_TITLE": "Media Technician", "POSN_CODE": "S61409", - "contractHours": 15, + "contractHours": 5, "startDate": f"2025-04-01", "endDate": "2025-09-01" - }]).on_conflict_replace().execute() + }]).on_conflict_replace().execute() FormHistory.insert([{ - "formHistoryID": 6, - "formID_id": "6", + "formHistoryID": 13, + "formID_id": "13", "historyType_id": "Labor Status Form", "createdBy_id": 1, "createdDate": f"2025-04-14", "status_id": "Approved" - }]).on_conflict_replace().execute() + }]).on_conflict_replace().execute() LaborStatusForm.insert([{ - "laborStatusFormID": 7, + "laborStatusFormID": 14, "termCode_id": f"202500", "studentName": "Elaheh Jamali", "studentSupervisee_id": "B00730361", "supervisor_id": "B12361006", - "department_id": 1, - "jobType": "Primary", + "department_id": 2, + "jobType": "Secondary", "WLS": 1, "POSN_TITLE": "Media Technician", "POSN_CODE": "S61409", - "contractHours": 3, + "contractHours": 5, "startDate": f"2025-04-01", "endDate": "2025-09-01" - }]).on_conflict_replace().execute() + }]).on_conflict_replace().execute() FormHistory.insert([{ - "formHistoryID": 7, - "formID_id": "7", + "formHistoryID": 14, + "formID_id": "14", "historyType_id": "Labor Status Form", "createdBy_id": 1, "createdDate": f"2025-04-14", "status_id": "Approved" - }]).on_conflict_replace().execute() - - - -# labor department + }]).on_conflict_replace().execute() LaborStatusForm.insert([{ - "laborStatusFormID": 4, + "laborStatusFormID": 15, "termCode_id": f"202500", "studentName": "Elaheh Jamali", "studentSupervisee_id": "B00730361", "supervisor_id": "B12361006", - "department_id": 5, - "jobType": "Secondary", + "department_id": 2, + "jobType": "Primary", "WLS": 1, "POSN_TITLE": "Media Technician", "POSN_CODE": "S61409", "contractHours": 5, "startDate": f"2025-04-01", "endDate": "2025-09-01" - }]).on_conflict_replace().execute() + }]).on_conflict_replace().execute() FormHistory.insert([{ - "formHistoryID": 4, - "formID_id": "4", + "formHistoryID": 15, + "formID_id": "15", "historyType_id": "Labor Status Form", "createdBy_id": 1, "createdDate": f"2025-04-14", "status_id": "Approved" - }]).on_conflict_replace().execute() + }]).on_conflict_replace().execute() LaborStatusForm.insert([{ - "laborStatusFormID": 5, + + "laborStatusFormID": 77, "termCode_id": f"202500", - "studentName": "Elaheh Jamali", - "studentSupervisee_id": "B00730361", + "studentName": "Genji Overwatch", + "studentSupervisee_id": "B12345756", "supervisor_id": "B12361006", - "department_id": 5, - "jobType": "Secondary", + "department_id": 1, + "jobType": "Primary", "WLS": 1, - "POSN_TITLE": "Media Technician", - "POSN_CODE": "S61409", - "contractHours": 5, + "POSN_TITLE": "overwtahc guy", + "POSN_CODE": "S61410", + "contractHours": 15, "startDate": f"2025-04-01", "endDate": "2025-09-01" - }]).on_conflict_replace().execute() + + }]).on_conflict_replace().execute() FormHistory.insert([{ - "formHistoryID": 5, - "formID_id": "5", + "formHistoryID": 77, + "formID_id": "77", "historyType_id": "Labor Status Form", "createdBy_id": 1, "createdDate": f"2025-04-14", "status_id": "Approved" - }]).on_conflict_replace().execute() - -# Biology Department + }]).on_conflict_replace().execute() LaborStatusForm.insert([{ - "laborStatusFormID": 8, + + "laborStatusFormID": 60, "termCode_id": f"202500", - "studentName": "Elaheh Jamali", - "studentSupervisee_id": "B00730361", + "studentName": "Mister Marlowe", + "studentSupervisee_id": "B12345759", "supervisor_id": "B12361006", - "department_id": 4, + "department_id": 1, "jobType": "Primary", "WLS": 1, - "POSN_TITLE": "Media Technician", - "POSN_CODE": "S61409", - "contractHours": 5, + "POSN_TITLE": "Break Worker", + "POSN_CODE": "S61412", + "contractHours": 400, "startDate": f"2025-04-01", "endDate": "2025-09-01" - }]).on_conflict_replace().execute() + + }]).on_conflict_replace().execute() FormHistory.insert([{ - "formHistoryID": 8, - "formID_id": "8", + "formHistoryID": 60, + "formID_id": "60", "historyType_id": "Labor Status Form", "createdBy_id": 1, "createdDate": f"2025-04-14", "status_id": "Approved" - }]).on_conflict_replace().execute() + }]).on_conflict_replace().execute() LaborStatusForm.insert([{ - "laborStatusFormID": 9, - "termCode_id": f"202500", - "studentName": "Elaheh Jamali", - "studentSupervisee_id": "B00730361", + + "laborStatusFormID": 61, + "termCode_id": f"202501", + "studentName": "Mister Thanksgiving", + "studentSupervisee_id": "B11231123", "supervisor_id": "B12361006", - "department_id": 4, - "jobType": "Secondary", + "department_id": 1, + "jobType": "Primary", "WLS": 1, - "POSN_TITLE": "Media Technician", - "POSN_CODE": "S61409", - "contractHours": 5, - "startDate": f"2025-04-01", - "endDate": "2025-09-01" - }]).on_conflict_replace().execute() + "POSN_TITLE": "Thanksgiving Worker", + "POSN_CODE": "S61412", + "contractHours": 50, + "startDate": f"2025-11-23", + "endDate": "2025-12-01" + + }]).on_conflict_replace().execute() FormHistory.insert([{ - "formHistoryID": 9, - "formID_id": "9", + "formHistoryID": 61, + "formID_id": "61", "historyType_id": "Labor Status Form", "createdBy_id": 1, - "createdDate": f"2025-04-14", + "createdDate": f"2025-11-01", "status_id": "Approved" }]).on_conflict_replace().execute() -# Mathematics Department LaborStatusForm.insert([{ - "laborStatusFormID": 10, - "termCode_id": f"202500", - "studentName": "Elaheh Jamali", - "studentSupervisee_id": "B00730361", + "laborStatusFormID": 62, + "termCode_id": "202611", + "studentName": "Alex Carter", + "studentSupervisee_id": "B12345762", "supervisor_id": "B12361006", - "department_id": 3, + "department_id": 1, "jobType": "Primary", "WLS": 1, - "POSN_TITLE": "Media Technician", - "POSN_CODE": "S61409", - "contractHours": 5, - "startDate": f"2025-04-01", - "endDate": "2025-09-01" - }]).on_conflict_replace().execute() + "POSN_TITLE": "Office Assistant", + "POSN_CODE": "S61413", + "weeklyHours": 10, + "startDate": "2026-08-15", + "endDate": "2026-12-15" + }]).on_conflict_replace().execute() FormHistory.insert([{ - "formHistoryID": 10, - "formID_id": "10", + "formHistoryID": 62, + "formID_id": "62", "historyType_id": "Labor Status Form", "createdBy_id": 1, - "createdDate": f"2025-04-14", + "createdDate": "2026-08-01", "status_id": "Approved" - }]).on_conflict_replace().execute() + }]).on_conflict_replace().execute() + LaborStatusForm.insert([{ - "laborStatusFormID": 11, - "termCode_id": f"202500", - "studentName": "Elaheh Jamali", - "studentSupervisee_id": "B00730361", + "laborStatusFormID": 63, + "termCode_id": "202611", + "studentName": "Morgan Hayes", + "studentSupervisee_id": "B12345763", "supervisor_id": "B12361006", - "department_id": 3, - "jobType": "Secondary", + "department_id": 1, + "jobType": "Primary", "WLS": 1, - "POSN_TITLE": "Media Technician", - "POSN_CODE": "S61409", - "contractHours": 5, - "startDate": f"2025-04-01", - "endDate": "2025-09-01" - }]).on_conflict_replace().execute() + "POSN_TITLE": "Computer Lab Assistant", + "POSN_CODE": "S61414", + "weeklyHours": 15, + "startDate": "2026-08-15", + "endDate": "2026-12-15" + }]).on_conflict_replace().execute() FormHistory.insert([{ - "formHistoryID": 11, - "formID_id": "11", + "formHistoryID": 63, + "formID_id": "63", "historyType_id": "Labor Status Form", "createdBy_id": 1, - "createdDate": f"2025-04-14", + "createdDate": "2026-08-01", "status_id": "Approved" }]).on_conflict_replace().execute() -#Technology and Applied Design Department LaborStatusForm.insert([{ - "laborStatusFormID": 12, - "termCode_id": f"202500", - "studentName": "Elaheh Jamali", - "studentSupervisee_id": "B00730361", + "laborStatusFormID": 64, + "termCode_id": "202611", + "studentName": "Jordan Brooks", + "studentSupervisee_id": "B12345764", "supervisor_id": "B12361006", - "department_id": 2, + "department_id": 1, + "jobType": "Primary", + "WLS": 1, + "POSN_TITLE": "Help Desk Assistant", + "POSN_CODE": "S61415", + "weeklyHours": 20, + "startDate": "2026-08-15", + "endDate": "2026-12-15" + }]).on_conflict_replace().execute() + +FormHistory.insert([{ + "formHistoryID": 64, + "formID_id": "64", + "historyType_id": "Labor Status Form", + "createdBy_id": 1, + "createdDate": "2026-08-01", + "status_id": "Approved" + }]).on_conflict_replace().execute() + + +LaborStatusForm.insert([{ + "laborStatusFormID": 65, + "termCode_id": "202611", + "studentName": "Taylor Morgan", + "studentSupervisee_id": "B12345765", + "supervisor_id": "B12361006", + "department_id": 1, "jobType": "Secondary", + "WLS": 0, + "POSN_TITLE": "Reception Assistant", + "POSN_CODE": "S61416", + "weeklyHours": 5, + "startDate": "2026-08-15", + "endDate": "2026-12-15" + }]).on_conflict_replace().execute() + +FormHistory.insert([{ + "formHistoryID": 65, + "formID_id": "65", + "historyType_id": "Labor Status Form", + "createdBy_id": 1, + "createdDate": "2026-08-01", + "status_id": "Approved" + }]).on_conflict_replace().execute() + + +LaborStatusForm.insert([{ + "laborStatusFormID": 66, + "termCode_id": "202611", + "studentName": "Casey Turner", + "studentSupervisee_id": "B12345766", + "supervisor_id": "B12361006", + "department_id": 1, + "jobType": "Secondary", + "WLS": 0, + "POSN_TITLE": "Library Assistant", + "POSN_CODE": "S61417", + "weeklyHours": 10, + "startDate": "2026-08-15", + "endDate": "2026-12-15" + }]).on_conflict_replace().execute() + +FormHistory.insert([{ + "formHistoryID": 66, + "formID_id": "66", + "historyType_id": "Labor Status Form", + "createdBy_id": 1, + "createdDate": "2026-08-01", + "status_id": "Approved" + }]).on_conflict_replace().execute() + + +LaborStatusForm.insert([{ + "laborStatusFormID": 72, + "termCode_id": "202612", + "studentName": "Alex Carter", + "studentSupervisee_id": "B12345762", + "supervisor_id": "B12361006", + "department_id": 1, + "jobType": "Primary", "WLS": 1, - "POSN_TITLE": "Media Technician", - "POSN_CODE": "S61409", - "contractHours": 5, - "startDate": f"2025-04-01", - "endDate": "2025-09-01" - }]).on_conflict_replace().execute() + "POSN_TITLE": "Office Assistant", + "POSN_CODE": "S61413", + "weeklyHours": 10, + "startDate": "2027-01-15", + "endDate": "2027-05-15" + }]).on_conflict_replace().execute() FormHistory.insert([{ - "formHistoryID": 12, - "formID_id": "12", + "formHistoryID": 72, + "formID_id": "72", "historyType_id": "Labor Status Form", "createdBy_id": 1, - "createdDate": f"2025-04-14", + "createdDate": "2027-01-05", "status_id": "Approved" - }]).on_conflict_replace().execute() + }]).on_conflict_replace().execute() + LaborStatusForm.insert([{ - "laborStatusFormID": 13, - "termCode_id": f"202500", - "studentName": "Elaheh Jamali", - "studentSupervisee_id": "B00730361", + "laborStatusFormID": 73, + "termCode_id": "202612", + "studentName": "Morgan Hayes", + "studentSupervisee_id": "B12345763", "supervisor_id": "B12361006", - "department_id": 2, + "department_id": 1, "jobType": "Primary", "WLS": 1, - "POSN_TITLE": "Media Technician", - "POSN_CODE": "S61409", - "contractHours": 5, - "startDate": f"2025-04-01", - "endDate": "2025-09-01" - }]).on_conflict_replace().execute() + "POSN_TITLE": "Computer Lab Assistant", + "POSN_CODE": "S61414", + "weeklyHours": 15, + "startDate": "2027-01-15", + "endDate": "2027-05-15" + }]).on_conflict_replace().execute() FormHistory.insert([{ - "formHistoryID": 13, - "formID_id": "13", + "formHistoryID": 73, + "formID_id": "73", "historyType_id": "Labor Status Form", "createdBy_id": 1, - "createdDate": f"2025-04-14", + "createdDate": "2027-01-05", "status_id": "Approved" }]).on_conflict_replace().execute() + LaborStatusForm.insert([{ - "laborStatusFormID": 14, - "termCode_id": f"202500", - "studentName": "Elaheh Jamali", - "studentSupervisee_id": "B00730361", + "laborStatusFormID": 74, + "termCode_id": "202612", + "studentName": "Taylor Morgan", + "studentSupervisee_id": "B12345765", "supervisor_id": "B12361006", - "department_id": 2, + "department_id": 1, "jobType": "Secondary", + "WLS": 0, + "POSN_TITLE": "Reception Assistant", + "POSN_CODE": "S61416", + "weeklyHours": 5, + "startDate": "2027-01-15", + "endDate": "2027-05-15" + }]).on_conflict_replace().execute() + +FormHistory.insert([{ + "formHistoryID": 74, + "formID_id": "74", + "historyType_id": "Labor Status Form", + "createdBy_id": 1, + "createdDate": "2027-01-05", + "status_id": "Approved" + }]).on_conflict_replace().execute() + + +# Student had a Fall-only position and receives a new Spring assignment. + +LaborStatusForm.insert([{ + "laborStatusFormID": 75, + "termCode_id": "202612", + "studentName": "Jordan Brooks", + "studentSupervisee_id": "B12345764", + "supervisor_id": "B12361006", + "department_id": 1, + "jobType": "Primary", "WLS": 1, - "POSN_TITLE": "Media Technician", - "POSN_CODE": "S61409", - "contractHours": 5, - "startDate": f"2025-04-01", - "endDate": "2025-09-01" - }]).on_conflict_replace().execute() + "POSN_TITLE": "Technology Assistant", + "POSN_CODE": "S61423", + "weeklyHours": 12, + "startDate": "2027-01-15", + "endDate": "2027-05-15" + }]).on_conflict_replace().execute() FormHistory.insert([{ - "formHistoryID": 14, - "formID_id": "14", + "formHistoryID": 75, + "formID_id": "75", "historyType_id": "Labor Status Form", "createdBy_id": 1, - "createdDate": f"2025-04-14", + "createdDate": "2027-01-05", "status_id": "Approved" - }]).on_conflict_replace().execute() + }]).on_conflict_replace().execute() + LaborStatusForm.insert([{ - "laborStatusFormID": 15, - "termCode_id": f"202500", - "studentName": "Elaheh Jamali", - "studentSupervisee_id": "B00730361", + "laborStatusFormID": 76, + "termCode_id": "202600", + "studentName": "Jordan Brooks", + "studentSupervisee_id": "B12345764", "supervisor_id": "B12361006", - "department_id": 2, + "department_id": 1, + "jobType": "Secondary", + "WLS": 1, + "POSN_TITLE": "Technology Assistant", + "POSN_CODE": "S61423", + "weeklyHours": 10, + "startDate": "2027-01-15", + "endDate": "2027-05-15" + }]).on_conflict_replace().execute() + +FormHistory.insert([{ + "formHistoryID": 76, + "formID_id": "76", + "historyType_id": "Labor Status Form", + "createdBy_id": 1, + "createdDate": "2027-01-05", + "status_id": "Approved" + }]).on_conflict_replace().execute() + + +# Break Positions + +LaborStatusForm.insert([{ + "laborStatusFormID": 67, + "termCode_id": "202601", + "studentName": "Jamie Foster", + "studentSupervisee_id": "B12345767", + "supervisor_id": "B12361006", + "department_id": 1, "jobType": "Primary", "WLS": 1, - "POSN_TITLE": "Media Technician", - "POSN_CODE": "S61409", - "contractHours": 5, - "startDate": f"2025-04-01", - "endDate": "2025-09-01" - }]).on_conflict_replace().execute() + "POSN_TITLE": "Thanksgiving Worker", + "POSN_CODE": "S61418", + "contractHours": 40, + "startDate": "2026-11-22", + "endDate": "2026-11-29" + }]).on_conflict_replace().execute() + +LaborStatusForm.insert([{ + "laborStatusFormID": 68, + "termCode_id": "202602", + "studentName": "Riley Cooper", + "studentSupervisee_id": "B12345768", + "supervisor_id": "B12361006", + "department_id": 1, + "jobType": "Primary", + "WLS": 1, + "POSN_TITLE": "Christmas Worker", + "POSN_CODE": "S61419", + "contractHours": 120, + "startDate": "2026-12-20", + "endDate": "2027-01-03" + }]).on_conflict_replace().execute() + +LaborStatusForm.insert([{ + "laborStatusFormID": 69, + "termCode_id": "202603", + "studentName": "Drew Bennett", + "studentSupervisee_id": "B12345769", + "supervisor_id": "B12361006", + "department_id": 1, + "jobType": "Primary", + "WLS": 1, + "POSN_TITLE": "Spring Break Worker", + "POSN_CODE": "S61420", + "contractHours": 80, + "startDate": "2027-03-07", + "endDate": "2027-03-14" + }]).on_conflict_replace().execute() + +LaborStatusForm.insert([{ + "laborStatusFormID": 70, + "termCode_id": "202604", + "studentName": "Logan Price", + "studentSupervisee_id": "B12345770", + "supervisor_id": "B12361006", + "department_id": 1, + "jobType": "Primary", + "WLS": 1, + "POSN_TITLE": "Fall Break Worker", + "POSN_CODE": "S61421", + "contractHours": 24, + "startDate": "2026-10-11", + "endDate": "2026-10-18" + }]).on_conflict_replace().execute() + +LaborStatusForm.insert([{ + "laborStatusFormID": 71, + "termCode_id": "202613", + "studentName": "Avery Sullivan", + "studentSupervisee_id": "B12345771", + "supervisor_id": "B12361006", + "department_id": 1, + "jobType": "Primary", + "WLS": 1, + "POSN_TITLE": "Summer Worker", + "POSN_CODE": "S61422", + "contractHours": 320, + "startDate": "2027-05-15", + "endDate": "2027-08-01" + }]).on_conflict_replace().execute() + FormHistory.insert([{ - "formHistoryID": 15, - "formID_id": "15", + "formHistoryID": 67, + "formID_id": "67", "historyType_id": "Labor Status Form", "createdBy_id": 1, - "createdDate": f"2025-04-14", + "createdDate": "2026-11-01", + "status_id": "Approved" + }]).on_conflict_replace().execute() + +FormHistory.insert([{ + "formHistoryID": 68, + "formID_id": "68", + "historyType_id": "Labor Status Form", + "createdBy_id": 1, + "createdDate": "2026-12-01", + "status_id": "Approved" + }]).on_conflict_replace().execute() + +FormHistory.insert([{ + "formHistoryID": 69, + "formID_id": "69", + "historyType_id": "Labor Status Form", + "createdBy_id": 1, + "createdDate": "2027-02-20", + "status_id": "Approved" + }]).on_conflict_replace().execute() + +FormHistory.insert([{ + "formHistoryID": 70, + "formID_id": "70", + "historyType_id": "Labor Status Form", + "createdBy_id": 1, + "createdDate": "2026-10-01", + "status_id": "Approved" + }]).on_conflict_replace().execute() + +FormHistory.insert([{ + "formHistoryID": 71, + "formID_id": "71", + "historyType_id": "Labor Status Form", + "createdBy_id": 1, + "createdDate": "2027-04-15", "status_id": "Approved" }]).on_conflict_replace().execute() @@ -1835,6 +1662,8 @@ ############################ # Allocation Dummy Data: ########################### + +# Active Allocations for 2025 allocations = [ { "termCode": f"202600", @@ -1971,23 +1800,22 @@ "breakHours": 900, }, { - "termCode": f"202600", + "termCode": 202600, "department": 1, "isFinal": True, "approvedOn": None, "approvedBy": None, - "justification": "Maintaining current staffing levels while allowing for moderate growth in student employment opportunities.", - "primary_10": 6, - "primary_12": 5, - "primary_15": 4, - "primary_20": 2, - "secondary_5": 6, + "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": 600, }, ] -print("hehe") Allocation.insert_many(allocations).on_conflict_replace().execute() print(" * allocation added") @@ -2003,8 +1831,8 @@ "positionCode": "S61407", "status": "Active", "wls": 1, - "revisionDate": f"2026-07-01", - "revisedBy": "Mario Nakazawa", + "revisionDate": f"2025-07-01", + "description": "", "department": 1 }, { @@ -2015,7 +1843,7 @@ "wls": 2, "revisionDate": f"2025-09-01", "revisionDate": f"2026-09-01", - "revisedBy": "Deanna Wilborne", + "description": "", "department": 1 }, { @@ -2023,8 +1851,8 @@ "positionCode": "S61409", "status": "Active", "wls": 3, - "revisionDate": f"2026-07-01", - "revisedBy": "Jasmine Jones", + "revisionDate": f"2025-07-01", + "description": "", "department": 1 }, { @@ -2035,6 +1863,8 @@ "revisionDate" : f"2026-01-01", "revisedBy": "Scott Heggen", "department": 1 + "description": "", + "department" : 1 }, { "positionTitle": "Teaching Associate", @@ -2042,7 +1872,7 @@ "status": "Inactive", "wls":2, "revisionDate" : f"2026-01-01", - "revisedBy": "Brian Ramsay", + "description": "", "department" : 3 }, { @@ -2051,7 +1881,7 @@ "status": "Active", "wls":2, "revisionDate" : f"2026-03-29", - "revisedBy": "Jan Pearce", + "description": "", "department" : 3 }, { @@ -2060,7 +1890,7 @@ "status": "Active", "wls":3, "revisionDate" : f"2026-01-23", - "revisedBy": "Scott Heggen", + "description": "", "department" : 1 }, { @@ -2069,7 +1899,7 @@ "status": "Active", "wls":4, "revisionDate" : f"2026-01-31", - "revisedBy": "Jasmine Jones", + "description": "", "department" : 1 }, { @@ -2078,7 +1908,7 @@ "status": "Active", "wls":5, "revisionDate" : f"2026-04-01", - "revisedBy": "Deanna Wilborne", + "description": "", "department" : 1 }, { @@ -2087,7 +1917,7 @@ "status": "Active", "wls":6, "revisionDate" : f"2026-05-03", - "revisedBy": "Jan Pearce", + "description": "", "department" : 1 }, { @@ -2096,7 +1926,7 @@ "status": "Active", "wls":1, "revisionDate" : f"2026-05-03", - "revisedBy": "Jan Pearce", + "description": "", "department" : 1 }, { @@ -2105,7 +1935,7 @@ "status": "Active", "wls":6, "revisionDate" : f"2026-05-03", - "revisedBy": "Brian Ramsay", + "description": "", "department" : 1 } diff --git a/database/migrate_db.sh b/database/migrate_db.sh index e2ba150e..dea226d8 100755 --- a/database/migrate_db.sh +++ b/database/migrate_db.sh @@ -32,7 +32,6 @@ pem add app.models.studentLaborEvaluation.StudentLaborEvaluation pem add app.models.formSearchResult.FormSearchResult pem add app.models.positionHistory.PositionHistory pem add app.models.allocation.Allocation -pem add app.models.positionDescriptionSection.PositionDescriptionSection pem watch pem migrate diff --git a/tests/code/test_allocationManager.py b/tests/code/test_allocationManger.py similarity index 52% rename from tests/code/test_allocationManager.py rename to tests/code/test_allocationManger.py index 7b4fe6e7..ea7da678 100644 --- a/tests/code/test_allocationManager.py +++ b/tests/code/test_allocationManger.py @@ -48,15 +48,6 @@ def testTerm(): #destroy term.delete_instance() -@pytest.fixture -def testBreakTerm(): - #create - term = Term.create(termCode = 200601) - yield term - - #destroy - term.delete_instance() - @pytest.fixture def testAllocation(testDepartment,testTerm): #create @@ -137,8 +128,8 @@ def testLaborStatusForm(testStudent,testSupervisor,testDepartment,testTerm): POSN_CODE = "S61412", contractHours = 500, weeklyHours = 15, - startDate = "2006-08-01", - endDate = "2007-5-01", + startDate = "2025-04-01", + endDate = "2025-09-01", supervisorNotes = None, laborDepartmentNotes = None, studentConfirmation = True, @@ -151,50 +142,6 @@ def testLaborStatusForm(testStudent,testSupervisor,testDepartment,testTerm): #destroy laborStatusForm.delete_instance() -@pytest.fixture -def testBreakLaborStatusForm(testStudent,testSupervisor,testDepartment,testBreakTerm): - breakLaborStatusForm = LaborStatusForm.create( - studentName = "John Doe", - laborStatusFormID = 9898, - termCode = testBreakTerm.termCode, - studentSupervisee = testStudent.ID, - supervisor_id = testSupervisor.ID, - department = testDepartment.departmentID, - jobType = "Secondary", - WLS = 1, - POSN_TITLE = "Vacation Worker", - POSN_CODE = "S61412", - contractHours = 168, - weeklyHours = None, - startDate = "2006-04-01", - endDate = "2006-09-01", - supervisorNotes = None, - laborDepartmentNotes = None, - studentConfirmation = True, - confirmationToken = None, - studentExpirationDate = True, - studentResponseDate = True, - ) - - breakFormHistory = FormHistory.create( - formHistoryID = 9898, - formID_id = "9898", - historyType_id = "Labor Status Form", - releaseForm_id = None, - adjustedForm_id = None, - overloadForm_id = None, - createdBy_id = 1, - createdDate = "2006-02-01", - reviewedDate = "2006-03-01", - reviewedBy_id = 1, - status_id = "Approved", - rejectReason = None - ) - - yield breakLaborStatusForm, breakFormHistory - #destroy - breakLaborStatusForm.delete_instance() - @pytest.fixture def testFormHistory(testLaborStatusForm,testUser): formHistory = FormHistory.create( @@ -257,91 +204,4 @@ def test_getContractedAllocations(testLaborStatusForm, testTerm, testDepartment, assert contractedAllocation['used_secondaries'] == 0 assert contractedAllocation['used_total'] == 1 - assert contractedAllocation['break_hours'] == 500 - -@pytest.mark.integration -def test_getContractedAllocations_withoutAnAllocationRow(testLaborStatusForm, testTerm, testDepartment, testFormHistory): - ''' - getContractedAllocations must not require an Allocation row to exist for - the department/term (e.g. before one has been created or finalized) - - it should still report the LaborStatusForm-derived counts. - ''' - contractedAllocation = getContractedAllocations(testTerm.termCode, testDepartment.departmentID) - assert contractedAllocation['used_15'] == 1 - assert contractedAllocation['break_hours'] == 500 - -@pytest.mark.integration -def test_getContractedAllocations_sumsBreakHoursAcrossAcademicYearCode(testDepartment, testStudent, testSupervisor, testUser): - ''' - A department can have approved break-term contracts under both a specific - term and that year's academic-year "00" bucket term - break_hours should - sum both, not silently keep only whichever one the query happens to see - first. - ''' - specificTerm = Term.create(termCode=200610) - academicYearTerm = Term.create(termCode=200600) # matches testTerm's code - - specificTermForm = LaborStatusForm.create( - laborStatusFormID=9001, termCode=specificTerm, studentSupervisee=testStudent, - supervisor_id=testSupervisor.ID, department=testDepartment, jobType="Primary", WLS=1, - POSN_TITLE="Specific Term Break", POSN_CODE="S9001", contractHours=100, weeklyHours=None, - ) - FormHistory.create( - formHistoryID=9001, formID=specificTermForm, historyType="Labor Status Form", - createdBy=testUser.userID, createdDate="2025-03-02", status="Approved", - ) - - academicYearForm = LaborStatusForm.create( - laborStatusFormID=9002, termCode=academicYearTerm, studentSupervisee=testStudent, - supervisor_id=testSupervisor.ID, department=testDepartment, jobType="Primary", WLS=1, - POSN_TITLE="Academic Year Break", POSN_CODE="S9002", contractHours=250, weeklyHours=None, - ) - FormHistory.create( - formHistoryID=9002, formID=academicYearForm, historyType="Labor Status Form", - createdBy=testUser.userID, createdDate="2025-03-02", status="Approved", - ) - - try: - contractedAllocation = getContractedAllocations(specificTerm.termCode, testDepartment.departmentID) - assert contractedAllocation['break_hours'] == 350 # 100 + 250, both terms summed - finally: - specificTermForm.delete_instance() - academicYearForm.delete_instance() - specificTerm.delete_instance() - academicYearTerm.delete_instance() -def test_getBreakContracts(testBreakLaborStatusForm, testBreakTerm, testDepartment,testTerm): - - # Test that the formHistory object exists - breakContractHours = getBreakContracts(testBreakTerm, testDepartment) - assert breakContractHours == 168 - - # Test it with a higher amount of hours - testBreakLaborStatusForm[0].contractHours = 800 - testBreakLaborStatusForm[0].save() - - breakContractHours = getBreakContracts(testBreakTerm, testDepartment) - assert breakContractHours == 800 - - # Test that it works even if weeklyHours and contractHours are set - testBreakLaborStatusForm[0].weeklyHours = 9999 - testBreakLaborStatusForm[0].save() - - breakContractHours = getBreakContracts(testBreakTerm, testDepartment) - assert breakContractHours == 800 - - # Test that if the form is denied to not show up. - testBreakLaborStatusForm[1].status = "denied by student" - testBreakLaborStatusForm[1].save() - - breakContractHours = getBreakContracts(testBreakTerm, testDepartment) - assert breakContractHours == 0 - - # Test if the term changes to a non-break term - testBreakLaborStatusForm[0].termCode = testTerm - testBreakLaborStatusForm[0].save() - testBreakLaborStatusForm[1].status = "Approved" - testBreakLaborStatusForm[1].save() - - breakContractHours = getBreakContracts(testBreakTerm, testDepartment) - assert breakContractHours == 0 - + assert contractedAllocation['break_hours'] == 500 \ No newline at end of file diff --git a/tests/code/test_download.py b/tests/code/test_download.py deleted file mode 100644 index 66c53b0c..00000000 --- a/tests/code/test_download.py +++ /dev/null @@ -1,151 +0,0 @@ -import io - -import pytest - -from app.logic.download import makePositionDescriptionPDF, removeHTML -from app.models import mainDB -from app.models.department import Department -from app.models.positionDescriptionSection import PositionDescriptionSection -from app.models.positionHistory import PositionHistory - - -@pytest.mark.integration -def test_makePositionDescriptionPDF(): - """ - Tests both HTML stripping and PDF generation using the makePositionDescriptionPDF() function. - """ - with mainDB.atomic() as transaction: - headingResult = removeHTML( - "

Learning Opportunities

" - ) - - # Confirm that the heading text remains. - assert "Learning Opportunities" in headingResult - - # Confirm that the HTML tags were removed. - assert "

" not in headingResult - assert "

" not in headingResult - - sectionResult = removeHTML( - """ -

A. Equipment Management

-

Maintains laboratory equipment & supplies.

- -

B. Experiment Support

-

Supports experiments and records results.

- """ - ) - - # Normalize whitespace so the test does not depend on the exact number of newlines produced by removeHTML(). - normalizedSectionResult = " ".join(sectionResult.split()) - - # Confirm that all readable content remains after stripping HTML. - assert "A. Equipment Management" in normalizedSectionResult - assert "Maintains laboratory equipment & supplies." in normalizedSectionResult - assert "B. Experiment Support" in normalizedSectionResult - assert "Supports experiments and records results." in normalizedSectionResult - - # Confirm that HTML tags and encoded entities were removed. - assert "

" not in normalizedSectionResult - assert "

" not in normalizedSectionResult - assert "

" not in normalizedSectionResult - assert "

" not in normalizedSectionResult - assert "&" not in normalizedSectionResult - - # Create the department shared by both test positions. - department = Department.create( - departmentID=200, - DEPT_NAME="Physics", - ACCOUNT="6742", - ORG="2116", - departmentCompliance=True, - isActive=True, - ) - - # Create a position with HTML-formatted description sections. - positionWithSections = PositionHistory.create( - positionTitle="Lab Technician", - positionCode="S34516", - department=department, - status="Active", - wls=3, - revisionDate="2023-01-01", - revisedBy="Jane Doe", - ) - - # Create a position without description sections to test for "No description available." output. - positionWithoutSections = PositionHistory.create( - positionTitle="Research Assistant", - positionCode="S34517", - department=department, - status="Active", - wls=2, - revisionDate="2023-01-02", - revisedBy="Sarah Smith", - ) - - # Insert this section first even though its order is 2. Tests section-ordering logic used by getPositionDescriptionSections(). - PositionDescriptionSection.create( - position=positionWithSections, - sectionTitle="

Responsibilities

", - sectionContent=""" -

A. Equipment Management

-

Maintains laboratory equipment & supplies.

- -

B. Experiment Support

-

Supports experiments and records results.

- """, - order=2, - ) - - # Insert the order-1 section second. - PositionDescriptionSection.create( - position=positionWithSections, - sectionTitle="

Position Summary

", - sectionContent=""" -

Provides support for laboratory research.

-

Works with faculty and student researchers.

- """, - order=1, - ) - - pdfBufferWithSections = makePositionDescriptionPDF( - department, - positionWithSections, - ) - - # Confirm that the function returns an in-memory byte buffer. - assert isinstance(pdfBufferWithSections, io.BytesIO) - - pdfBytesWithSections = pdfBufferWithSections.getvalue() - - # Confirm that the generated PDF is not empty. - assert len(pdfBytesWithSections) > 0 - - # Confirm that the output begins with the standard PDF header. - assert pdfBytesWithSections.startswith(b"%PDF-") - - # Confirm that the output ends with the standard PDF marker. - assert pdfBytesWithSections.rstrip().endswith(b"%%EOF") - - pdfBufferWithoutSections = makePositionDescriptionPDF( - department, - positionWithoutSections, - ) - - # Confirm that the fallback branch also returns a BytesIO object. - assert isinstance(pdfBufferWithoutSections, io.BytesIO) - - pdfBytesWithoutSections = pdfBufferWithoutSections.getvalue() - - # Confirm that the fallback PDF is not empty. - assert len(pdfBytesWithoutSections) > 0 - - # Confirm that the fallback output is also a valid PDF. - assert pdfBytesWithoutSections.startswith(b"%PDF-") - assert pdfBytesWithoutSections.rstrip().endswith(b"%%EOF") - - # Confirm that the two positions did not produce identical PDFs. - assert pdfBytesWithSections != pdfBytesWithoutSections - - transaction.rollback() \ No newline at end of file diff --git a/tests/code/test_getPositions.py b/tests/code/test_getPositions.py index 4e4ee5e9..a59a4374 100644 --- a/tests/code/test_getPositions.py +++ b/tests/code/test_getPositions.py @@ -10,8 +10,8 @@ def test_getActivePositions(): Test to check if the getActivePositions function in getPositions.py correctly retrieves active positions for a single department. """ with mainDB.atomic() as transaction: - dept1 = Department.create(departmentID=102, DEPT_NAME="Computer Science", ACCOUNT="6740", ORG="2114", departmentCompliance=True, isActive=True) - dept2 = Department.create(departmentID=103, DEPT_NAME="Mathematics", ACCOUNT="6741", ORG="2115", departmentCompliance=True, isActive=True) + dept1 = Department.create(departmentID=100, DEPT_NAME="Computer Science", ACCOUNT="6740", ORG="2114", departmentCompliance=True, isActive=True) + dept2 = Department.create(departmentID=101, DEPT_NAME="Mathematics", ACCOUNT="6741", ORG="2115", departmentCompliance=True, isActive=True) position1 = PositionHistory.create(positionTitle="Teaching Assistant", positionCode="S34512", @@ -80,62 +80,7 @@ def test_getActivePositions(): assert len(posURL3) == 0 transaction.rollback() - -@pytest.mark.integration -def test_getPosition(): - """ - Test to check if the getPosition function in getPositions.py correctly retrieves a single position for a given department, position code, and optional revision date. - """ - with mainDB.atomic() as transaction: - dept = Department.create(departmentID=200, DEPT_NAME="Physics", ACCOUNT="6742", ORG="2116", departmentCompliance=True, isActive=True) - - position1 = PositionHistory.create(positionTitle="Lab Technician", - positionCode="S34516", - department=dept, - status="Inactive", - wls=3, - revisionDate="2024-01-01", - description="") - - position2 = PositionHistory.create(positionTitle="Lab Technician", - positionCode="S34516", - department=dept, - status="Requested", - wls=3, - revisionDate="2025-01-01", - description="") - - position3 = PositionHistory.create(positionTitle="Lab Technician", - positionCode="S34516", - department=dept, - status="Active", - wls=3, - revisionDate="2023-01-01", - description="") - - # Test retrieving the most recent revision - should return regardless of status - retrieved_position = getPosition(dept, "S34516") - assert retrieved_position.revisionDate.isoformat() == "2025-01-01" - - # Test retrieving a specific revision - should return regardless of status - retrieved_position_specific = getPosition(dept, "S34516", "2023-01-01") - assert retrieved_position_specific.revisionDate.isoformat() == "2023-01-01" - assert retrieved_position_specific.status == "Active" - - retrieved_position = getPosition(dept, "S34516", "2024-01-01") - assert retrieved_position.revisionDate.isoformat() == "2024-01-01" - assert retrieved_position.status == "Inactive" - - retrieved_position_specific = getPosition(dept, "S34516", "2025-01-01") - assert retrieved_position_specific.revisionDate.isoformat() == "2025-01-01" - assert retrieved_position_specific.status == "Requested" - - # Test retrieving a non-existent revision date - retrieved_position_non_existent = getPosition(dept, "S34516", "2099-01-01") - assert retrieved_position_non_existent is None - - transaction.rollback() - + @pytest.mark.integration def test_getPositions(): with mainDB.atomic() as transaction: @@ -147,28 +92,32 @@ def test_getPositions(): department=dept1, status="Active", wls=4, - revisionDate="2023-01-01") - + revisionDate="2023-01-01", + description="") + position2 = PositionHistory.create(positionTitle="Research Assistant", positionCode="S34513", department=dept1, status="Inactive", wls=3, - revisionDate="2023-01-01",) + revisionDate="2023-01-01", + description="") position3 = PositionHistory.create(positionTitle="Lab Assistant", positionCode="S34514", department=dept1, status="Active", wls=2, - revisionDate="2026-01-01") + revisionDate="2026-01-01", + description="") position4 = PositionHistory.create(positionTitle="Intern", positionCode="S34515", department=dept1, status="Active", wls=1, - revisionDate="2023-01-01") + revisionDate="2023-01-01", + description="") test1 = list(getPositions(dept1)) test2 = list(getPositions(dept2)) @@ -200,4 +149,4 @@ def test_getPositions(): # Check that no positions are returned when department is None assert len(test3) == 0 - transaction.rollback() \ No newline at end of file + transaction.rollback() diff --git a/tests/code/test_getTerms.py b/tests/code/test_getTerms.py deleted file mode 100644 index eaca2be6..00000000 --- a/tests/code/test_getTerms.py +++ /dev/null @@ -1,56 +0,0 @@ -import pytest -from app import app - -from app.models.term import Term -from app.logic.getTerms import getTerms -from datetime import datetime, date - -@pytest.fixture -def test_terms(): - # Make terms and get a set year, its far enough back that the test won't break other data. - - currentYear = 2000 - AcademicYear = f"{currentYear}-{currentYear + 1}" - print(currentYear) - - test_currentAY = Term.create( - termCode = int(f"{currentYear}00"), - termName = f"AY {currentYear}-{currentYear + 1}", - termStart = f"{currentYear}-08-01", - termEnd = f"{currentYear + 1}-05-01", - termState = 1, - primaryCutOff = f"{currentYear + 1}-09-01", - adjustmentCutOff = f"2002-10-01" - ) - test_fallTerm = Term.create( - termCode = int(f"{currentYear}11"), - termName = f"Fall {currentYear}", - termStart = f"{currentYear}-08-01", - termEnd = f"{currentYear}-12-12", - termState = 1, - primaryCutOff = f"{currentYear}-09-01", - adjustmentCutOff = f"{currentYear}-10-01" - ) - test_springTerm = Term.create( - termCode = int(f"{currentYear}12"), - termName = f"Spring {currentYear + 1}", - termStart = f"{currentYear + 1}-01-01", - termEnd = f"{currentYear + 1}-05-01", - termState = 1, - primaryCutOff = f"{currentYear + 1}-02-01", - adjustmentCutOff = f"{currentYear + 1}-3-01" - ) - yield test_currentAY, test_fallTerm, test_springTerm, AcademicYear - - #destroy all created data - test_currentAY.delete_instance() - test_fallTerm.delete_instance() - test_springTerm.delete_instance() - -@pytest.mark.integration -def test_getCurrentTerms(test_terms): - currentAY, fallTerm, springTerm = getTerms(test_terms[3]) # Get terms for the year that is selected. - - assert currentAY == test_terms[0] - assert fallTerm == test_terms[1] - assert springTerm == test_terms[2] \ No newline at end of file diff --git a/tests/code/test_tracy.py b/tests/code/test_tracy.py index f09eb5ae..730547dd 100644 --- a/tests/code/test_tracy.py +++ b/tests/code/test_tracy.py @@ -18,10 +18,8 @@ def test_init(self, tracy): def test_getStudents(self, tracy): with app.app_context(): students = tracy.getStudents() - for s in students: - assert ['Antonia','Barbara','Elaheh','Guillermo','Jeremiah','Kat', 'Oluwagbayi', 'Test', 'Tyler'] == [s.FIRST_NAME for s in students] - assert ['777','118','718','300','420','420', '883', '700', '420'] == [s.STU_CPO for s in students] - + assert ['Elaheh','Guillermo','Jeremiah','Kat', 'Oluwagbayi', 'Test', 'Tyler'] == [s.FIRST_NAME for s in students] + assert ['718','300','420','420', '883', '700', '420'] == [s.STU_CPO for s in students] @pytest.mark.integration def test_getStudentFromBNumber(self, tracy):