From 2106977935bf99e52d3ed82891e0d7e2d07ed395 Mon Sep 17 00:00:00 2001 From: JervalThomas Date: Sat, 23 Sep 2023 19:09:27 -0400 Subject: [PATCH 01/90] testing out commits to Codecrafters --- App/Test.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 App/Test.txt diff --git a/App/Test.txt b/App/Test.txt new file mode 100644 index 000000000..cef0690dc --- /dev/null +++ b/App/Test.txt @@ -0,0 +1 @@ +CodeCrafters From 18e99a69c3307bedce21bcdc19803013ef73e439 Mon Sep 17 00:00:00 2001 From: Jerrelle Johnson Date: Thu, 28 Sep 2023 11:11:18 -0400 Subject: [PATCH 02/90] testing --- App/controllers/program.py | 14 ++++++++++++++ App/models/__init__.py | 3 ++- App/models/program.py | 26 ++++++++++++++++++++++++++ flaskmvc | 1 + 4 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 App/controllers/program.py create mode 100644 App/models/program.py create mode 160000 flaskmvc diff --git a/App/controllers/program.py b/App/controllers/program.py new file mode 100644 index 000000000..fa9844ac7 --- /dev/null +++ b/App/controllers/program.py @@ -0,0 +1,14 @@ +from App.models import Program + +def create_program_from_file(file_path): + try: + program = Program(file_path) + return program + except FileNotFoundError: + print("File not found.") + except Exception as e: + print(f"An error occurred: {e}") + +def printProgramInfo(program): + program.get_json() + diff --git a/App/models/__init__.py b/App/models/__init__.py index 82da278c5..345ddb5eb 100644 --- a/App/models/__init__.py +++ b/App/models/__init__.py @@ -1 +1,2 @@ -from .user import * \ No newline at end of file +from .user import * +from .program import * \ No newline at end of file diff --git a/App/models/program.py b/App/models/program.py new file mode 100644 index 000000000..edbb5a104 --- /dev/null +++ b/App/models/program.py @@ -0,0 +1,26 @@ +class Program: + id = 1 + + def __init__(self, file_path): + + try: + with open(file_path, 'r') as file: + lines = file.readlines() + self.name = lines[0].strip() # First line is the program name + self.course_codes = [code.strip() for code in lines[1:]] # Subsequent lines are course codes + self.id = Program.latest_programmeID # Assign the latest ID + Program.id += 1 # Increment the latest ID for the next instance + + except FileNotFoundError: + print("File not found.") + + except Exception as e: + print(f"An error occurred: {e}") + + def get_json(self): + return{ + 'Program ID:': self.id, + 'Program Name: ': self.name, + 'Program Courses: ': self.course_codes + } + \ No newline at end of file diff --git a/flaskmvc b/flaskmvc new file mode 160000 index 000000000..210697793 --- /dev/null +++ b/flaskmvc @@ -0,0 +1 @@ +Subproject commit 2106977935bf99e52d3ed82891e0d7e2d07ed395 From 50303f72a98060117e9bf8913051016ea8f9f248 Mon Sep 17 00:00:00 2001 From: JervalThomas Date: Thu, 28 Sep 2023 12:15:54 -0400 Subject: [PATCH 03/90] Staff and Student Classes --- App/models/user.py | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/App/models/user.py b/App/models/user.py index 40caf3f41..be901a13f 100644 --- a/App/models/user.py +++ b/App/models/user.py @@ -24,4 +24,41 @@ def set_password(self, password): def check_password(self, password): """Check hashed password.""" return check_password_hash(self.password, password) + +class Staff(db.Model): + id = db.Column(db.Integer, primary_key=True) + name = db.Column(db.String(80), nullable=False) + + programmes = db.relationship('Programme', backref='staff') + + def add_programme(self, programme): + self.programmes.append(programme) + + def remove_programme(self, programme): + self.programmes.remove(programme) + + def __repr__(self): + return f'' + + +class Student(db.Model): + id = db.Column(db.Integer, primary_key=True) + name = db.Column(db.String(80), nullable=False) + + programme_id = db.Column(db.Integer, db.ForeignKey('programme.id')) + programme = db.relationship('Programme', backref='students') + + courseplan = db.relationship('CoursePlan', backref='student', uselist=False) + + def enroll_in_programme(self, programme): + self.programme = programme + + def add_course_to_plan(self, course): + self.courseplan.courses.append(course) + + def remove_course_from_plan(self, course): + self.courseplan.courses.remove(course) + + def __repr__(self): + return f'' From 616cfa3ad43e6040e9ced46a5b4654e21aff62fe Mon Sep 17 00:00:00 2001 From: Ashley Jacob Date: Thu, 28 Sep 2023 18:01:30 -0400 Subject: [PATCH 04/90] test commit --- App/models/test.txt | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 App/models/test.txt diff --git a/App/models/test.txt b/App/models/test.txt new file mode 100644 index 000000000..e69de29bb From 32a60e4d2c06974322ce323d1a9c81ec4f4c4186 Mon Sep 17 00:00:00 2001 From: JervalThomas Date: Thu, 28 Sep 2023 18:35:26 -0400 Subject: [PATCH 05/90] Staff and Student Classes redone --- App/models/user.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/App/models/user.py b/App/models/user.py index be901a13f..36e766a3a 100644 --- a/App/models/user.py +++ b/App/models/user.py @@ -34,7 +34,7 @@ class Staff(db.Model): def add_programme(self, programme): self.programmes.append(programme) - def remove_programme(self, programme): + def remove_programme(self, programme): self.programmes.remove(programme) def __repr__(self): From 49ecbf26123705de72a5d847a9f1b959a6dde6b4 Mon Sep 17 00:00:00 2001 From: Jerrelle Johnson Date: Thu, 28 Sep 2023 23:17:57 -0400 Subject: [PATCH 06/90] Program 90% completed --- .DS_Store | Bin 0 -> 6148 bytes App/.DS_Store | Bin 0 -> 6148 bytes App/controllers/__init__.py | 3 ++- App/controllers/program.py | 30 +++++++++++++++++++--- App/models/__init__.py | 3 ++- App/models/courses.py | 25 +++++++++++++++++++ App/models/program.py | 24 ++++++++++++------ flaskmvc | 1 - wsgi.py | 48 ++++++++++++++++++++++++++++++++++-- 9 files changed, 117 insertions(+), 17 deletions(-) create mode 100644 .DS_Store create mode 100644 App/.DS_Store create mode 100644 App/models/courses.py delete mode 160000 flaskmvc diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..831f80d09c91bce7bf03fb2ad9f0dbcacf0a7dc8 GIT binary patch literal 6148 zcmeHK%}T>S5Z-O8O({YS3Oz1(E!b8qh?f}a3mDOZN=-=7V9bUlHHT8jSzpK}@p+ut z-GIfMMeGdhe)GGV{UH0p7~}3D95QAz#w=)v9F-bDcWtO)k`XzMk)=T_1F$}V)WrTe z;I}u~8B19j6yLu;j))F%l&+jx&HhXtt%xgRC7xhjal8Km6ZL`f(MS1yt;Q?;HBSRJb~wR_9u=y=!{qw#pv7t52;pf8RN z$E#Jx+S@-ky_`PBFNu89baG%@$&SGa-a#>|dG+Q=ER#p@RM}M)Au&J<5Cg=(W;0;U z1*^N+G|=ja0b-zr0o)%1G(^W>sZnhm(BbtN<1IuK(D5ySC=5CVON|f#;kp!1mvZyO z;JO_A!sIyyOO3jmaWylHV`i=%FI>$IexcGCcQjH@3=jkB3^cWASVH2?qr literal 0 HcmV?d00001 diff --git a/App/.DS_Store b/App/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..c3acb3d9f91fad9d06af3ee57dd8ff1c3827570a GIT binary patch literal 6148 zcmeHK%}T>S5T5OiO({YT3Oz1(E!b8qh?h|73mDOZN^MNgV9b^zZ4RZ7v%Zi|;`2DO zyH#uLRixbsv)}IQOu~G->}CLf^~PQspbh{QDq*3D%`Zapq)SrJmJ%Y9?}$M_h>s8P zlD9GZM+Ru^YH*M17D0-u_O*VAni7VHS5-S6q%C_ z({a)p#@95u5F&Kv{h@mq_}QSob1I^A7({+70|L)Smz%2~@7tfMBZs#P7- z8`Ej$sNLk9ZgcY4 zis%77D7p+22yowKur7Ij%jie0b9M|G1`Gq6%YZ&Lt=i^NU@|uh7zS1_K<5KTCA2l> z3gyv(jVu8W={Hge_NkVj7_QOQm@C8?6sAHERVdRX22AQ6)Il5~( t>K!Tx`Q-{fL$D*SV)Uh}xPdAK?VLJ@w#Hl`T2Rc7fTY1RhJin2-~;8yi|+sc literal 0 HcmV?d00001 diff --git a/App/controllers/__init__.py b/App/controllers/__init__.py index 8b0409577..a65d3c384 100644 --- a/App/controllers/__init__.py +++ b/App/controllers/__init__.py @@ -1,2 +1,3 @@ from .user import * -from .auth import * \ No newline at end of file +from .auth import * +from .program import * \ No newline at end of file diff --git a/App/controllers/program.py b/App/controllers/program.py index fa9844ac7..465a2fb3b 100644 --- a/App/controllers/program.py +++ b/App/controllers/program.py @@ -1,14 +1,36 @@ from App.models import Program +from App.database import db -def create_program_from_file(file_path): +def create_program(file_path): try: - program = Program(file_path) - return program + newProgram = Program(file_path) + db.session.add(newProgram) + db.session.commit() + return newProgram + except FileNotFoundError: print("File not found.") except Exception as e: print(f"An error occurred: {e}") -def printProgramInfo(program): +def get_program_by_name(programName): + return Program.query.filter_by(name=programName).first() + +def get_program(id): + return Program.query.get(id) + +def get_all_programs(): + return Program.query.all() + +# def get_all_users_json(): +# program = Program.query.all() +# if not program: +# return [] + +# users = [user.get_json() for user in users] +# return users + +def print_program_info(id): + program = get_program(id) program.get_json() diff --git a/App/models/__init__.py b/App/models/__init__.py index 345ddb5eb..730d98ef0 100644 --- a/App/models/__init__.py +++ b/App/models/__init__.py @@ -1,2 +1,3 @@ from .user import * -from .program import * \ No newline at end of file +from .program import * +from .courses import * \ No newline at end of file diff --git a/App/models/courses.py b/App/models/courses.py new file mode 100644 index 000000000..398b9a826 --- /dev/null +++ b/App/models/courses.py @@ -0,0 +1,25 @@ +from App.database import db + +class Course(db.Model): + courseCode = db.Column(db.String(8), primary_key=True) + courseName = db.Column(db.String(25)) + credits = db.Column(db.Integer) + rating = db.Column(db.Integer) + prerequisites = db.Column(db.String(24)) + + def __init__(self, course_code, course_name, ratings=None, credits=None, prerequisites=None): + self.courseCode = course_code + self.course_name = course_name + self.rating = ratings + self.credits = credits + self.prerequisites = prerequisites + + def get_json(self): + return{ + 'Course Code:': self.courseCode, + 'Course Name: ': self.course_name, + 'Course Rating: ': self.rating, + 'No. of Credits: ': self.credits, + 'Prerequistes: ': self.prerequisites + } + diff --git a/App/models/program.py b/App/models/program.py index edbb5a104..87d173da6 100644 --- a/App/models/program.py +++ b/App/models/program.py @@ -1,26 +1,34 @@ -class Program: - id = 1 +from App.database import db +from App.models import courses +import json +class Program(db.Model): + id = db.Column(db.Integer, primary_key=True) + name = db.Column(db.String(50)) + coursesCodes = db.Column(db.String(150)) def __init__(self, file_path): try: with open(file_path, 'r') as file: lines = file.readlines() - self.name = lines[0].strip() # First line is the program name - self.course_codes = [code.strip() for code in lines[1:]] # Subsequent lines are course codes - self.id = Program.latest_programmeID # Assign the latest ID - Program.id += 1 # Increment the latest ID for the next instance - + self.name = lines[0].strip() + self.courseCodes = [code.strip() for code in lines[1:]] + #self.courseCodes = json.dumps([code.strip() for code in lines[1:]]) + except FileNotFoundError: print("File not found.") except Exception as e: print(f"An error occurred: {e}") + + # def get_course_codes(self): + # return json.loads(self.coursesCodes) if self.coursesCodes else [] + def get_json(self): return{ 'Program ID:': self.id, 'Program Name: ': self.name, - 'Program Courses: ': self.course_codes + 'Program Courses: ': self.coursesCodes } \ No newline at end of file diff --git a/flaskmvc b/flaskmvc deleted file mode 160000 index 210697793..000000000 --- a/flaskmvc +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 2106977935bf99e52d3ed82891e0d7e2d07ed395 diff --git a/wsgi.py b/wsgi.py index 87b4a3bab..40df0eae8 100644 --- a/wsgi.py +++ b/wsgi.py @@ -4,7 +4,16 @@ from App.database import db, get_migrate from App.main import create_app -from App.controllers import ( create_user, get_all_users_json, get_all_users ) +from App.controllers import ( + create_user, + get_all_users_json, + get_all_users, + create_program, + get_program, + get_program_by_name, + print_program_info + ) + # This commands file allow you to create convenient CLI commands for testing controllers @@ -66,4 +75,39 @@ def user_tests_command(type): sys.exit(pytest.main(["-k", "App"])) -app.cli.add_command(test) \ No newline at end of file +app.cli.add_command(test) + + +''' +Program Commands +''' + +program = AppGroup('program', help = 'Program object commands') + +@program.command('create', help='Create a new program') +@click.argument('file_path') +def create_program_command(file_path): + with open(file_path, 'r') as file: + course_codes = [code.strip() for code in file.readlines()[1:]] + print('Course codes:', course_codes) # Print the course codes + newprogram = create_program(file_path) + print(f'Program created with ID {newprogram.id} and name "{newprogram.name}" and courses of this program are {newprogram.get_course_codes()}') + +# @program.command('display', help='Display program information') +# @click.argument('program_id', type=int) +# def display_program_command(program_id): +# print_program_info(program_id) + + +@program.command('getProgram', help='Get program by name') +@click.argument('id', type=int) +def get_Program_command(id): + program = get_program(id) + if program: + r = program.get_json() + print(r) + else: + print(f'Program with ID "{id}" not found.') + +app.cli.add_command(program) + From d62bcfbf130f8b8de895131ac5fd209b3c92bd5c Mon Sep 17 00:00:00 2001 From: Ashley Jacob Date: Fri, 29 Sep 2023 07:51:29 -0400 Subject: [PATCH 07/90] Created Admin & Course Plan models --- App/controllers/admin.py | 35 +++++++++++++++++++ .../test.txt => controllers/coursePlan.py} | 0 App/models/admin.py | 21 +++++++++++ App/models/coursePlan.py | 24 +++++++++++++ 4 files changed, 80 insertions(+) create mode 100644 App/controllers/admin.py rename App/{models/test.txt => controllers/coursePlan.py} (100%) create mode 100644 App/models/admin.py create mode 100644 App/models/coursePlan.py diff --git a/App/controllers/admin.py b/App/controllers/admin.py new file mode 100644 index 000000000..2d6831d90 --- /dev/null +++ b/App/controllers/admin.py @@ -0,0 +1,35 @@ +from App.models import User +from App.models import Student +from App.models import Staff +from App.models import db + +def addStudent(id,username,password): #creates new student + newstudent=Student(id=id,username=username,password=password) + try: + db.session.add(newstudent) + db.session.commit() + except Exception as e: #student already exists + db.session.rollback() + print(f'Username or ID already taken') + print(f'Student created.') + return newstudent + +def addStaff(id,username,password): #creates new staff member + newstaff=Staff(id=id,username=username,password=password) + try: + db.session.add(newstaff) + db.session.commit() + except Exception as e: #staff already exists + db.session.rollback() + print(f'Username or ID already taken') + print(f'Staff created.') + return newstaff + +def removeAccount(id): #removes account by id + acc=User.query.filter_by(id=id).first() + if not acc: + print(f'Account with ID {id} not found.') + return + db.session.delete(acc) + db.session.commit() + print(f'Account deleted.') diff --git a/App/models/test.txt b/App/controllers/coursePlan.py similarity index 100% rename from App/models/test.txt rename to App/controllers/coursePlan.py diff --git a/App/models/admin.py b/App/models/admin.py new file mode 100644 index 000000000..ac857a337 --- /dev/null +++ b/App/models/admin.py @@ -0,0 +1,21 @@ +from App.database import db +from App.models import User + +class Admin(User): + id=db.Column(db.foreignkey('user.id'), nullable=False) + name=db.Column(db.String(120), nullable=False) + user=db.relationship('User',backref=db.backref('Admin')) + + def __init__(self, username, password, name): + super.__init__(username=username,password=password) + self.name=name + + def get_json(self): + return{ + 'id': self.id, + 'name': self.name + } + + def __repr__(self): + return f'' + diff --git a/App/models/coursePlan.py b/App/models/coursePlan.py new file mode 100644 index 000000000..f0631ec7a --- /dev/null +++ b/App/models/coursePlan.py @@ -0,0 +1,24 @@ +from flask_login import UserMixin +from App.database import db + +class CoursePlan(db.Model,UserMixin): + planId=db.Column(db.Integer, primary_key=True) + studentId=db.Column(db.Integer, db.foreignkey('student.id'), nullable=False) + courses=db.Column(db.ARRAY(db.String), nullable=True) + student=db.relationship('Student', db.backref('CoursePlan')) + + def __init__(self, studentId, courses=None): + self.studentId = studentId + self.courses=courses + + def get_json(self): + return{ + 'planId': self.planId, + 'studentId': self.studentId, + 'courses': self.courses + } + + def __repr__(self): + return f'' + + From c3570d11c40eafe79d3ad45687e0b787bf2c7f97 Mon Sep 17 00:00:00 2001 From: Ashley Jacob Date: Fri, 29 Sep 2023 10:57:04 -0400 Subject: [PATCH 08/90] Created Admin & Course Plan Controllers --- App/controllers/admin.py | 2 +- App/controllers/coursePlan.py | 119 ++++++++++++++++++++++++++++++++++ 2 files changed, 120 insertions(+), 1 deletion(-) diff --git a/App/controllers/admin.py b/App/controllers/admin.py index 2d6831d90..bc78840c7 100644 --- a/App/controllers/admin.py +++ b/App/controllers/admin.py @@ -1,7 +1,7 @@ from App.models import User from App.models import Student from App.models import Staff -from App.models import db +from App.database import db def addStudent(id,username,password): #creates new student newstudent=Student(id=id,username=username,password=password) diff --git a/App/controllers/coursePlan.py b/App/controllers/coursePlan.py index e69de29bb..3534e7512 100644 --- a/App/controllers/coursePlan.py +++ b/App/controllers/coursePlan.py @@ -0,0 +1,119 @@ +from App.database import db +from App.models import Student +from App.models import CoursePlan +from App.models import Programme +from App.models import Course + +def addCourse(Student, courseCode): + plan=CoursePlan.query.filter_by(studentId=Student.id).first() + plan.courses.append(courseCode) + print(f'Course added') + +def removeCourse(Student, courseCode): + plan=CoursePlan.query.filter_by(studentId=Student.id).first() + if courseCode in plan.courses: + plan.courses.remove(courseCode) + print(f'Course removed') + return + print(f'Course not found') + +def getProgramme(Student): + return Programme.query.filter_by(programmeId=Student.programme_id).first() + +def getRemainingCourses(completed, required): + remaining=required.copy() + for course in required: + if course in completed: + remaining.remove(course) + return remaining + +def getRemainingCore(Student): + programme=getProgramme(Student) + reqCore=programme.cores + remaining=getRemainingCourses(Student.courseHistory,reqCore) + return remaining + +def getRemainingFoun(Student): + programme=getProgramme(Student) + reqFoun=programme.foun + remaining=getRemainingCourses(Student.courseHistory,reqFoun) + return remaining + +def getRemainingElec(Student): + programme=getProgramme(Student) + reqElec=programme.electives + remaining=getRemainingCourses(Student.courseHistory,reqElec) + return remaining + +def remElecCredits(Student): + programme=getProgramme(Student) + requiredCreds=programme.elecCredits + for course in programme.electives: + if course in Student.courseHistory: + c=Course.query.filter_by(courseCode=course).first() #get course + requiredCreds=requiredCreds-c.credits #subtract credits + return requiredCreds + +def findAvailable(courseList): + listing=1 #FIX - courses offered (posted by staff) + available=[] + for course in courseList: + if course in listing: + c=Course.query.filter_by(courseCode=course).first() #get course + if c: + available.append(c) + return available #returns an array of course objects + + +def prioritizeElectives(Student): + #get available electives + electives=findAvailable(getRemainingElec(Student)) + credits=remElecCredits(Student) + courses=[] + + #select courses to satisfy the programme's credit requiremen + for c in electives: + if credits>0: + courses.append(c) + credits=credits-c.credits + + #merge available, required core and foundation courses + courses=courses + findAvailable(getRemainingCore(Student)) + findAvailable(getRemainingFoun(Student)) + return courses + + +def easyCourses(Student): + #get electives, order by difficulty + electives=findAvailable(getRemainingElec(Student)) + electives.sort(key=lambda x:getattr(x, "rating", 0)) + + #select courses to satisfy the programme's credit requirement + credits=remElecCredits(Student) + courses=[] + for c in electives: + if credits>0: + courses.append(c) + credits=credits-c.credits + + #merge available core and foundation courses and sort by difficulty + courses= courses + findAvailable(getRemainingCore(Student)) + findAvailable(getRemainingFoun(Student)) + courses.sort(key=lambda x:getattr(x, "rating", 0)) + return courses + + +def fastestGraduation(Student): + #get electives, order by credits (descending order) + electives=findAvailable(getRemainingElec(Student)) + electives.sort(key=lambda x:getattr(x, "credits", 0), reverse=True) + + #select courses to satisfy the programme's credit requirement + credits=remElecCredits(Student) + courses=[] + for c in electives: + if credits>0: + courses.append(c) + credits=credits-c.credits + + #get available, required core and foundation courses + courses= courses + findAvailable(getRemainingCore(Student)) + findAvailable(getRemainingFoun(Student)) + return courses \ No newline at end of file From 7e180d45808c4f903fd617999d8bcedad34d5337 Mon Sep 17 00:00:00 2001 From: Jerrelle Johnson Date: Fri, 29 Sep 2023 11:40:25 -0400 Subject: [PATCH 09/90] added course with some features not all --- App/controllers/__init__.py | 3 ++- App/controllers/courses.py | 38 +++++++++++++++++++++++++++++++++++++ App/models/courses.py | 27 +++++++++++++++++++------- App/models/program.py | 9 ++++----- wsgi.py | 18 +++++++++++++++++- 5 files changed, 81 insertions(+), 14 deletions(-) create mode 100644 App/controllers/courses.py diff --git a/App/controllers/__init__.py b/App/controllers/__init__.py index a65d3c384..4ebd92c38 100644 --- a/App/controllers/__init__.py +++ b/App/controllers/__init__.py @@ -1,3 +1,4 @@ from .user import * from .auth import * -from .program import * \ No newline at end of file +from .program import * +from .courses import * \ No newline at end of file diff --git a/App/controllers/courses.py b/App/controllers/courses.py new file mode 100644 index 000000000..726450f20 --- /dev/null +++ b/App/controllers/courses.py @@ -0,0 +1,38 @@ +from App.models import Course +from App.database import db + +def create_course(file_path): + try: + newCourse = Course(file_path) + db.session.add(newCourse) + db.session.commit() + return newCourse + + except FileNotFoundError: + print("File not found.") + except Exception as e: + print(f"An error occurred: {e}") + +def get_course_by_name(name): + return Course.query.filter_by(courseName=name).first() + +def get_course_by_courseCode(code): + return Course.query.get(courseCode=code).first() + +def get_prerequisites(code): + course = get_course_by_courseCode(code) + if course: + return course.prerequisites + else: + return None + +def get_credits(code): + course = get_course_by_courseCode(code) + if course: + return course.credits + else: + return None + + +def get_all_courses(): + return Course.query.all() \ No newline at end of file diff --git a/App/models/courses.py b/App/models/courses.py index 398b9a826..747fabe92 100644 --- a/App/models/courses.py +++ b/App/models/courses.py @@ -1,4 +1,5 @@ from App.database import db +import json class Course(db.Model): courseCode = db.Column(db.String(8), primary_key=True) @@ -7,17 +8,29 @@ class Course(db.Model): rating = db.Column(db.Integer) prerequisites = db.Column(db.String(24)) - def __init__(self, course_code, course_name, ratings=None, credits=None, prerequisites=None): - self.courseCode = course_code - self.course_name = course_name - self.rating = ratings - self.credits = credits - self.prerequisites = prerequisites + def __init__(self, file_path): + try: + with open(file_path, 'r') as file: + lines = file.readlines() + self.courseCode = lines[0].strip() + self.courseName = lines[1].strip() + self.credits = lines[2].strip() + self.rating = lines[3].strip() + self.prerequisites = json.dumps([code.strip() for code in lines[4:]]) + + except FileNotFoundError: + print("File not found.") + + except Exception as e: + print(f"An error occurred: {e}") + + def get_prerequisites(self): + return json.loads(self.prerequisites) if self.prerequisites else [] def get_json(self): return{ 'Course Code:': self.courseCode, - 'Course Name: ': self.course_name, + 'Course Name: ': self.courseName, 'Course Rating: ': self.rating, 'No. of Credits: ': self.credits, 'Prerequistes: ': self.prerequisites diff --git a/App/models/program.py b/App/models/program.py index 87d173da6..f3a38b674 100644 --- a/App/models/program.py +++ b/App/models/program.py @@ -7,13 +7,11 @@ class Program(db.Model): coursesCodes = db.Column(db.String(150)) def __init__(self, file_path): - try: with open(file_path, 'r') as file: lines = file.readlines() self.name = lines[0].strip() - self.courseCodes = [code.strip() for code in lines[1:]] - #self.courseCodes = json.dumps([code.strip() for code in lines[1:]]) + self.coursesCodes = json.dumps([code.strip() for code in lines[1:]]) except FileNotFoundError: print("File not found.") @@ -21,8 +19,9 @@ def __init__(self, file_path): except Exception as e: print(f"An error occurred: {e}") - # def get_course_codes(self): - # return json.loads(self.coursesCodes) if self.coursesCodes else [] + def get_course_codes(self): + return json.loads(self.coursesCodes) if self.coursesCodes else [] + def get_json(self): diff --git a/wsgi.py b/wsgi.py index 40df0eae8..6602bc72c 100644 --- a/wsgi.py +++ b/wsgi.py @@ -10,7 +10,7 @@ get_all_users, create_program, get_program, - get_program_by_name, + create_course, print_program_info ) @@ -111,3 +111,19 @@ def get_Program_command(id): app.cli.add_command(program) + +''' +Course Commands +''' + +course = AppGroup('course', help = 'Program object commands') + +@course.command('create', help='Create a new course') +@click.argument('file_path') +def create_course_command(file_path): + with open(file_path, 'r') as file: + newcourse = create_course(file_path) + print(f'Course created with course code "{newcourse.courseCode}", name "{newcourse.courseName}", credits "{newcourse.credits}", ratings "{newcourse.rating}" and prerequites "{newcourse.prerequisites}"') + + +app.cli.add_command(course) \ No newline at end of file From bc01e4a0d8175d4ca9aac6a68d365c04eb3b1ab3 Mon Sep 17 00:00:00 2001 From: Jerrelle Johnson Date: Fri, 29 Sep 2023 23:58:13 -0400 Subject: [PATCH 10/90] updated the program code --- App/.DS_Store | Bin 6148 -> 6148 bytes App/controllers/courses.py | 9 +++---- App/controllers/program.py | 48 ++++++++++++++++++++++++---------- App/models/courses.py | 2 +- App/models/program.py | 40 +++++++++++++++++++++++----- wsgi.py | 52 ++++++++++++++----------------------- 6 files changed, 92 insertions(+), 59 deletions(-) diff --git a/App/.DS_Store b/App/.DS_Store index c3acb3d9f91fad9d06af3ee57dd8ff1c3827570a..611dedb96f2fe70210cea19e5d791c1acacb5791 100644 GIT binary patch delta 46 zcmZoMXffEJ$;`NYvKDh8mw0uxrIC(;p|SDgbxhKXos&;7$uo9se#ETGvYCzJA3p#^ CDGn0= delta 21 dcmZoMXffEJ$voMRY0u^-%t|bq**X650{~Ld2UP$7 diff --git a/App/controllers/courses.py b/App/controllers/courses.py index 726450f20..66126cf9c 100644 --- a/App/controllers/courses.py +++ b/App/controllers/courses.py @@ -13,9 +13,6 @@ def create_course(file_path): except Exception as e: print(f"An error occurred: {e}") -def get_course_by_name(name): - return Course.query.filter_by(courseName=name).first() - def get_course_by_courseCode(code): return Course.query.get(courseCode=code).first() @@ -33,6 +30,6 @@ def get_credits(code): else: return None - -def get_all_courses(): - return Course.query.all() \ No newline at end of file +def get_ratings(code): + course = get_course_by_courseCode(code) + return course.rating if course else 0 diff --git a/App/controllers/program.py b/App/controllers/program.py index 465a2fb3b..0d890f333 100644 --- a/App/controllers/program.py +++ b/App/controllers/program.py @@ -16,21 +16,41 @@ def create_program(file_path): def get_program_by_name(programName): return Program.query.filter_by(name=programName).first() -def get_program(id): - return Program.query.get(id) +def get_level1_credits(programName): + program = get_program_by_name(programName) + return program.level1_credits if program else 0 -def get_all_programs(): - return Program.query.all() +def get_level1_courses(programName): + program = get_program_by_name(programName) + courses = program.str_level1_courses + return courses if program else [] + +def get_core_credits(programName): + program = get_program_by_name(programName) + return program.core_credits if program else 0 + +def get_core_courses(programName): + program = get_program_by_name(programName) + courses = program.str_core_courses() + return courses if program else [] + +def get_elective_credits(programName): + program = get_program_by_name(programName) + return program.elective_credits if program else 0 + +def get_elective_courses(programName): + program = get_program_by_name(programName) + courses = program.str_elective_courses + return courses if program else [] + +def get_foun_credits(programName): + program = get_program_by_name(programName) + return program.foun_credits if program else 0 + +def get_foun_courses(programName): + program = get_program_by_name(programName) + courses = program.str_foun_courses + return courses if program else [] -# def get_all_users_json(): -# program = Program.query.all() -# if not program: -# return [] - -# users = [user.get_json() for user in users] -# return users -def print_program_info(id): - program = get_program(id) - program.get_json() diff --git a/App/models/courses.py b/App/models/courses.py index 747fabe92..1856e20d5 100644 --- a/App/models/courses.py +++ b/App/models/courses.py @@ -16,7 +16,7 @@ def __init__(self, file_path): self.courseName = lines[1].strip() self.credits = lines[2].strip() self.rating = lines[3].strip() - self.prerequisites = json.dumps([code.strip() for code in lines[4:]]) + self.prerequisites = json.dumps(lines[4].strip().split(',')) except FileNotFoundError: print("File not found.") diff --git a/App/models/program.py b/App/models/program.py index f3a38b674..9f20adcaa 100644 --- a/App/models/program.py +++ b/App/models/program.py @@ -1,17 +1,30 @@ from App.database import db -from App.models import courses import json class Program(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(50)) - coursesCodes = db.Column(db.String(150)) + level1_credits = db.Column(db.Integer) + level1_courses = db.Column(db.String(200)) + core_credits = db.Column(db.Integer) + core_courses = db.Column(db.String(200)) + elective_credits = db.Column(db.Integer) + elective_courses = db.Column(db.String(200)) + foun_credits = db.Column(db.Integer) + foun_courses = db.Column(db.String(30)) def __init__(self, file_path): try: with open(file_path, 'r') as file: lines = file.readlines() self.name = lines[0].strip() - self.coursesCodes = json.dumps([code.strip() for code in lines[1:]]) + self.level1_credits = lines[1].strip() + self.level1_courses = json.dumps(lines[2].strip().split(',')) + self.core_credits = lines[3].strip() + self.core_courses = json.dumps(lines[4].strip().split(',')) + self.elective_credits = lines[5].strip() + self.elective_courses = json.dumps(lines[6].strip().split(',')) + self.foun_credits = lines[7].strip() + self.foun_courses = json.dumps(lines[8].strip().split(',')) except FileNotFoundError: print("File not found.") @@ -19,15 +32,30 @@ def __init__(self, file_path): except Exception as e: print(f"An error occurred: {e}") - def get_course_codes(self): - return json.loads(self.coursesCodes) if self.coursesCodes else [] + def str_level1_courses(self): + return json.loads(self.level1_courses) if self.level1_courses else [] + def str_core_courses(self): + return json.loads(self.core_courses) if self.core_courses else [] + + def str_elective_courses(self): + return json.loads(self.elective_courses) if self.elective_courses else [] + + def str_foun_courses(self): + return json.loads(self.foun_courses) if self.foun_courses else [] def get_json(self): return{ 'Program ID:': self.id, 'Program Name: ': self.name, - 'Program Courses: ': self.coursesCodes + 'Level I Credits: ': self.level1_credits, + 'Level I Courses: ': self.level1_courses, + 'Core Credits: ': self.core_credits, + 'Core Courses: ': self.core_courses, + 'Elective Credits ': self.elective_credits, + 'Elective Courses: ': self.elective_courses, + 'Foundation Credits: ': self.foun_credits, + 'Foundation Courses: ': self.foun_courses } \ No newline at end of file diff --git a/wsgi.py b/wsgi.py index 6602bc72c..ce5714521 100644 --- a/wsgi.py +++ b/wsgi.py @@ -9,9 +9,8 @@ get_all_users_json, get_all_users, create_program, - get_program, + get_core_courses, create_course, - print_program_info ) @@ -76,7 +75,7 @@ def user_tests_command(type): app.cli.add_command(test) - +################################################################# ''' Program Commands @@ -88,42 +87,31 @@ def user_tests_command(type): @click.argument('file_path') def create_program_command(file_path): with open(file_path, 'r') as file: - course_codes = [code.strip() for code in file.readlines()[1:]] - print('Course codes:', course_codes) # Print the course codes newprogram = create_program(file_path) - print(f'Program created with ID {newprogram.id} and name "{newprogram.name}" and courses of this program are {newprogram.get_course_codes()}') - -# @program.command('display', help='Display program information') -# @click.argument('program_id', type=int) -# def display_program_command(program_id): -# print_program_info(program_id) + print(f'Program created with ID {newprogram.id} and name "{newprogram.name}"') +@program.command('core', help='Get program core courses') +@click.argument('programName', type=str) +def get_CoreCourses(name): + courses = get_core_courses(name) + print(f'{courses}') if courses else print(f'error') -@program.command('getProgram', help='Get program by name') -@click.argument('id', type=int) -def get_Program_command(id): - program = get_program(id) - if program: - r = program.get_json() - print(r) - else: - print(f'Program with ID "{id}" not found.') app.cli.add_command(program) +################################################################# +# ''' +# Course Commands +# ''' -''' -Course Commands -''' - -course = AppGroup('course', help = 'Program object commands') +# course = AppGroup('course', help = 'Program object commands') -@course.command('create', help='Create a new course') -@click.argument('file_path') -def create_course_command(file_path): - with open(file_path, 'r') as file: - newcourse = create_course(file_path) - print(f'Course created with course code "{newcourse.courseCode}", name "{newcourse.courseName}", credits "{newcourse.credits}", ratings "{newcourse.rating}" and prerequites "{newcourse.prerequisites}"') +# @course.command('create', help='Create a new course') +# @click.argument('file_path') +# def create_course_command(file_path): +# with open(file_path, 'r') as file: +# newcourse = create_course(file_path) +# print(f'Course created with course code "{newcourse.courseCode}", name "{newcourse.courseName}", credits "{newcourse.credits}", ratings "{newcourse.rating}" and prerequites "{newcourse.prerequisites}"') -app.cli.add_command(course) \ No newline at end of file +# app.cli.add_command(course) \ No newline at end of file From 175b169c3ef03c713ab4b92d9092fbc8e2d716f1 Mon Sep 17 00:00:00 2001 From: Jerrelle Johnson Date: Sat, 30 Sep 2023 10:34:20 -0400 Subject: [PATCH 11/90] Did some more updates --- .DS_Store | Bin 6148 -> 6148 bytes App/controllers/courses.py | 13 +++------- testData/courseTest.txt | 5 ++++ testData/test.txt | 9 +++++++ testData/test2.txt | 4 +++ wsgi.py | 49 ++++++++++++++++++++++++++----------- 6 files changed, 57 insertions(+), 23 deletions(-) create mode 100644 testData/courseTest.txt create mode 100644 testData/test.txt create mode 100644 testData/test2.txt diff --git a/.DS_Store b/.DS_Store index 831f80d09c91bce7bf03fb2ad9f0dbcacf0a7dc8..d33561525b977ecafb01ff6cf6587d40bd8c155c 100644 GIT binary patch delta 403 zcmZoMXfc=|#>B!ku~2NHo}wrR0|Nsi1A_oVaY0f}eiD$kJ*i;xN5S{|P9R)*U>IhVfMO_LW ybyf)X7Gw~%6xq+f5bR{!%+A5j0Ssy&=R5Ocei2InU`PWIm|z0YnB`mu~2NHo}wrd0|Nsi1A_oVaY0f}eiD$kBdK6w;qu7_A}qqp42}#1 z3 Date: Sun, 1 Oct 2023 14:53:57 -0400 Subject: [PATCH 12/90] Staff and Student Classes redone --- App/controllers/admin.py | 35 +++++++++++++++++++++++++++++++++++ App/controllers/staff.py | 0 App/controllers/student.py | 0 App/models/admin.py | 21 +++++++++++++++++++++ App/models/staff.py | 21 +++++++++++++++++++++ App/models/student.py | 21 +++++++++++++++++++++ 6 files changed, 98 insertions(+) create mode 100644 App/controllers/admin.py create mode 100644 App/controllers/staff.py create mode 100644 App/controllers/student.py create mode 100644 App/models/admin.py create mode 100644 App/models/staff.py create mode 100644 App/models/student.py diff --git a/App/controllers/admin.py b/App/controllers/admin.py new file mode 100644 index 000000000..8c6381fae --- /dev/null +++ b/App/controllers/admin.py @@ -0,0 +1,35 @@ +from flask import request, jsonify +from App import app, db +from App.models.admin import Admin +from App.models.programme import Program + +# Controller for adding a program for the admin. +@app.route('/admin/program', methods=['POST']) +def add_program(): + if not request.is_json: + return jsonify({"message": "Request is not in JSON format"}), 400 + + name = request.json.get('name') + + if not name: + return jsonify({"message": "Program name is required"}), 400 + + new_program = Program(name) + + db.session.add(new_program) + db.session.commit() + + return jsonify({"message": "Program added successfully"}) + +# Controller for removing a program for the admin. +@app.route('/admin/program/', methods=['DELETE']) +def remove_program(id): + program = Program.query.get(id) + + if not program: + return jsonify({"message": "Program not found"}), 404 + + db.session.delete(program) + db.session.commit() + + return jsonify({"message": "Program deleted successfully"}) diff --git a/App/controllers/staff.py b/App/controllers/staff.py new file mode 100644 index 000000000..e69de29bb diff --git a/App/controllers/student.py b/App/controllers/student.py new file mode 100644 index 000000000..e69de29bb diff --git a/App/models/admin.py b/App/models/admin.py new file mode 100644 index 000000000..2492e9e56 --- /dev/null +++ b/App/models/admin.py @@ -0,0 +1,21 @@ +# admin.py + +from user import User # Import the User class from user.py +from App.database import db + +class Admin(User): + id = db.Column(db.String(10), foreign_key=True, unique=True) + name = db.Column(db.String(50)) + + def __init__(self, username, password, admin_id, name): + super().__init__(username, password) + self.id = admin_id + self.name = name + + def get_json(self): + user_json = super().get_json() + user_json['admin_id'] = self.id + user_json['name'] = self.name + return user_json + + # You can add more methods specific to the Admin class here diff --git a/App/models/staff.py b/App/models/staff.py new file mode 100644 index 000000000..831fe507b --- /dev/null +++ b/App/models/staff.py @@ -0,0 +1,21 @@ +# staff.py + +from user import User # Import the User class from user.py +from App.database import db + +class Staff(User): + id = db.Column(db.String(10), foreign_key=True, unique=True) #foreign key + name = db.Column(db.String(50)) + + def __init__(self, username, password, staff_id, name): + super().__init__(username, password) + self.id = staff_id + self.name = name + + def get_json(self): + user_json = super().get_json() + user_json['staff_id'] = self.id + user_json['name'] = self.name + return user_json + + # You can add more methods specific to the Staff class here diff --git a/App/models/student.py b/App/models/student.py new file mode 100644 index 000000000..66262d5b0 --- /dev/null +++ b/App/models/student.py @@ -0,0 +1,21 @@ +# student.py + +from user import User # Import the User class from user.py +from App.database import db + +class Student(User): + id = db.Column(db.String(10), foreign_key=True, unique=True) #foreign key + name = db.Column(db.String(50)) + + def __init__(self, username, password, student_id, name): + super().__init__(username, password) + self.id = student_id + self.name = name + + def get_json(self): + user_json = super().get_json() + user_json['student_id'] = self.id + user_json['name'] = self.name + return user_json + + # You can add more methods specific to the Student class here From dcff40302f3f53ed3bccb33a47b639544b3b0615 Mon Sep 17 00:00:00 2001 From: JervalThomas Date: Sun, 1 Oct 2023 17:29:05 -0400 Subject: [PATCH 13/90] Staff and Student Classes redone --- App/controllers/admin.py | 35 ----------------------------------- App/models/admin.py | 21 --------------------- App/models/user.py | 38 -------------------------------------- 3 files changed, 94 deletions(-) delete mode 100644 App/controllers/admin.py delete mode 100644 App/models/admin.py diff --git a/App/controllers/admin.py b/App/controllers/admin.py deleted file mode 100644 index 8c6381fae..000000000 --- a/App/controllers/admin.py +++ /dev/null @@ -1,35 +0,0 @@ -from flask import request, jsonify -from App import app, db -from App.models.admin import Admin -from App.models.programme import Program - -# Controller for adding a program for the admin. -@app.route('/admin/program', methods=['POST']) -def add_program(): - if not request.is_json: - return jsonify({"message": "Request is not in JSON format"}), 400 - - name = request.json.get('name') - - if not name: - return jsonify({"message": "Program name is required"}), 400 - - new_program = Program(name) - - db.session.add(new_program) - db.session.commit() - - return jsonify({"message": "Program added successfully"}) - -# Controller for removing a program for the admin. -@app.route('/admin/program/', methods=['DELETE']) -def remove_program(id): - program = Program.query.get(id) - - if not program: - return jsonify({"message": "Program not found"}), 404 - - db.session.delete(program) - db.session.commit() - - return jsonify({"message": "Program deleted successfully"}) diff --git a/App/models/admin.py b/App/models/admin.py deleted file mode 100644 index 2492e9e56..000000000 --- a/App/models/admin.py +++ /dev/null @@ -1,21 +0,0 @@ -# admin.py - -from user import User # Import the User class from user.py -from App.database import db - -class Admin(User): - id = db.Column(db.String(10), foreign_key=True, unique=True) - name = db.Column(db.String(50)) - - def __init__(self, username, password, admin_id, name): - super().__init__(username, password) - self.id = admin_id - self.name = name - - def get_json(self): - user_json = super().get_json() - user_json['admin_id'] = self.id - user_json['name'] = self.name - return user_json - - # You can add more methods specific to the Admin class here diff --git a/App/models/user.py b/App/models/user.py index 36e766a3a..22314f63d 100644 --- a/App/models/user.py +++ b/App/models/user.py @@ -24,41 +24,3 @@ def set_password(self, password): def check_password(self, password): """Check hashed password.""" return check_password_hash(self.password, password) - -class Staff(db.Model): - id = db.Column(db.Integer, primary_key=True) - name = db.Column(db.String(80), nullable=False) - - programmes = db.relationship('Programme', backref='staff') - - def add_programme(self, programme): - self.programmes.append(programme) - - def remove_programme(self, programme): - self.programmes.remove(programme) - - def __repr__(self): - return f'' - - -class Student(db.Model): - id = db.Column(db.Integer, primary_key=True) - name = db.Column(db.String(80), nullable=False) - - programme_id = db.Column(db.Integer, db.ForeignKey('programme.id')) - programme = db.relationship('Programme', backref='students') - - courseplan = db.relationship('CoursePlan', backref='student', uselist=False) - - def enroll_in_programme(self, programme): - self.programme = programme - - def add_course_to_plan(self, course): - self.courseplan.courses.append(course) - - def remove_course_from_plan(self, course): - self.courseplan.courses.remove(course) - - def __repr__(self): - return f'' - From 4bbeb2b506cf88cc3244b59ed1e693ef44f07f94 Mon Sep 17 00:00:00 2001 From: JervalThomas Date: Sun, 1 Oct 2023 17:51:02 -0400 Subject: [PATCH 14/90] Staff and Student Controllers --- App/controllers/staff.py | 38 ++++++++++++++++++++++++++++++++++++++ App/controllers/student.py | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+) diff --git a/App/controllers/staff.py b/App/controllers/staff.py index e69de29bb..01120cafb 100644 --- a/App/controllers/staff.py +++ b/App/controllers/staff.py @@ -0,0 +1,38 @@ +from program import Program +from course import Course +from App.models import Staff + +class StaffController: + def __init__(self): + self.programmes = [] # Store programme instances here + self.courses = [] # Store course instances here + + def add_programme(self, programme_name, description): + programme = Programme(programme_name, description) + self.programmes.append(programme) + + def remove_programme(self, programme_name): + programme = self.get_programme_by_name(programme_name) + if programme: + self.programmes.remove(programme) + + def add_course(self, course_code, course_name, credits): + course = Course(course_code, course_name, credits) + self.courses.append(course) + + def remove_course(self, course_code): + course = self.get_course_by_code(course_code) + if course: + self.courses.remove(course) + + def get_programme_by_name(self, programme_name): + for programme in self.programmes: + if programme.name == programme_name: + return programme + return None + + def get_course_by_code(self, course_code): + for course in self.courses: + if course.code == course_code: + return course + return None diff --git a/App/controllers/student.py b/App/controllers/student.py index e69de29bb..43d1ce294 100644 --- a/App/controllers/student.py +++ b/App/controllers/student.py @@ -0,0 +1,33 @@ +from App.models import Student +from App.database import db + +def enroll_in_programme(self, username, password, student_id, name, programme): + student = Student(username, password, student_id, name) + programme.add_student(student) + self.students.append(student) + +def add_course_to_plan(self, student_id, course): + student = self.get_student_by_id(student_id) + if student: + student.add_course_to_plan(course) + +def remove_course_from_plan(self, student_id, course): + student = self.get_student_by_id(student_id) + if student: + student.remove_course_from_plan(course) + +def view_course_plan(self, student_id): + student = self.get_student_by_id(student_id) + if student: + return student.view_course_plan() + +def add_course(self, student_id, courses, file): + student = self.get_student_by_id(student_id) + if student: + student.add_course(courses, file) + +def get_student_by_id(self, student_id): + for student in self.students: + if student.id == student_id: + return student + return None \ No newline at end of file From 7da7270fbdecdc5e3ac1a0a8aa98906576815ece Mon Sep 17 00:00:00 2001 From: JervalThomas Date: Sun, 1 Oct 2023 17:59:11 -0400 Subject: [PATCH 15/90] Staff and Student Controllers --- App/controllers/staff.py | 86 +++++++++++++++++++++++----------------- 1 file changed, 49 insertions(+), 37 deletions(-) diff --git a/App/controllers/staff.py b/App/controllers/staff.py index 01120cafb..973a74b55 100644 --- a/App/controllers/staff.py +++ b/App/controllers/staff.py @@ -1,38 +1,50 @@ -from program import Program -from course import Course -from App.models import Staff - -class StaffController: - def __init__(self): - self.programmes = [] # Store programme instances here - self.courses = [] # Store course instances here - - def add_programme(self, programme_name, description): - programme = Programme(programme_name, description) - self.programmes.append(programme) - - def remove_programme(self, programme_name): - programme = self.get_programme_by_name(programme_name) - if programme: - self.programmes.remove(programme) - - def add_course(self, course_code, course_name, credits): - course = Course(course_code, course_name, credits) - self.courses.append(course) - - def remove_course(self, course_code): - course = self.get_course_by_code(course_code) +from App.models import Program, Course +from App.database import db + + +def add_programme(self, program_name, description): + try: + new_program = Program(name=program_name, description=description) + db.session.add(new_program) + db.session.commit() + return new_program + except Exception as e: + db.session.rollback() + print(f"An error occurred while adding the program: {e}") + + +def remove_programme(self, program_name): + try: + program = Program.query.filter_by(name=program_name).first() + if program: + db.session.delete(program) + db.session.commit() + else: + print(f"Program '{program_name}' not found.") + except Exception as e: + db.session.rollback() + print(f"An error occurred while removing the program: {e}") + + +def add_course(self, course_code, course_name, credits): + try: + new_course = Course(code=course_code, name=course_name, credits=credits) + db.session.add(new_course) + db.session.commit() + return new_course + except Exception as e: + db.session.rollback() + print(f"An error occurred while adding the course: {e}") + + +def remove_course(self, course_code): + try: + course = Course.query.filter_by(code=course_code).first() if course: - self.courses.remove(course) - - def get_programme_by_name(self, programme_name): - for programme in self.programmes: - if programme.name == programme_name: - return programme - return None - - def get_course_by_code(self, course_code): - for course in self.courses: - if course.code == course_code: - return course - return None + db.session.delete(course) + db.session.commit() + else: + print(f"Course '{course_code}' not found.") + except Exception as e: + db.session.rollback() + print(f"An error occurred while removing the course: {e}") From e502c7b862531cceb41c6d3276b958d488ce8fb8 Mon Sep 17 00:00:00 2001 From: JervalThomas Date: Sun, 1 Oct 2023 18:49:51 -0400 Subject: [PATCH 16/90] Staff and Student Controllers --- App/controllers/__init__.py | 4 ++- App/controllers/student.py | 54 +++++++++++++++++++------------------ App/models/__init__.py | 4 ++- App/models/student.py | 25 ++++++++++++++--- wsgi.py | 46 +++++++++++++++++++++++++++++++ 5 files changed, 102 insertions(+), 31 deletions(-) diff --git a/App/controllers/__init__.py b/App/controllers/__init__.py index 8b0409577..66f8ced06 100644 --- a/App/controllers/__init__.py +++ b/App/controllers/__init__.py @@ -1,2 +1,4 @@ from .user import * -from .auth import * \ No newline at end of file +from .auth import * +from .student import * +from .staff import * \ No newline at end of file diff --git a/App/controllers/student.py b/App/controllers/student.py index 43d1ce294..b5bf7eb2e 100644 --- a/App/controllers/student.py +++ b/App/controllers/student.py @@ -1,33 +1,35 @@ -from App.models import Student +from App.models import Student, CoursePlan, Program, PassCourses from App.database import db -def enroll_in_programme(self, username, password, student_id, name, programme): - student = Student(username, password, student_id, name) - programme.add_student(student) - self.students.append(student) -def add_course_to_plan(self, student_id, course): - student = self.get_student_by_id(student_id) - if student: - student.add_course_to_plan(course) +def enroll_in_programme(self, programme_id): + programme = Program.query.get(programme_id) + if programme: + self.student.programmes.append(programme) + db.session.commit() -def remove_course_from_plan(self, student_id, course): - student = self.get_student_by_id(student_id) - if student: - student.remove_course_from_plan(course) +def add_course_to_plan(self, course_id): + course = CoursePlan.query.get(course_id) + if course: + self.student.courses.append(course) + db.session.commit() -def view_course_plan(self, student_id): - student = self.get_student_by_id(student_id) - if student: - return student.view_course_plan() +def remove_course_from_plan(self, course_id): + course = CoursePlan.query.get(course_id) + if course: + self.student.courses.remove(course) + db.session.commit() -def add_course(self, student_id, courses, file): - student = self.get_student_by_id(student_id) - if student: - student.add_course(courses, file) +def view_course_plan(self): + return [course.get_json() for course in self.student.courses] -def get_student_by_id(self, student_id): - for student in self.students: - if student.id == student_id: - return student - return None \ No newline at end of file +def add_courses_from_file(self, file_path): + try: + with open(file_path, 'r') as file: + course_ids = [line.strip() for line in file.readlines()] + for course_id in course_ids: + self.add_course_to_plan(course_id) + except FileNotFoundError: + return "File not found." + except Exception as e: + return str(e) \ No newline at end of file diff --git a/App/models/__init__.py b/App/models/__init__.py index 82da278c5..f75aea424 100644 --- a/App/models/__init__.py +++ b/App/models/__init__.py @@ -1 +1,3 @@ -from .user import * \ No newline at end of file +from .user import * +from .staff import * +from .student import * \ No newline at end of file diff --git a/App/models/student.py b/App/models/student.py index 66262d5b0..59b8c9b97 100644 --- a/App/models/student.py +++ b/App/models/student.py @@ -1,12 +1,19 @@ -# student.py - from user import User # Import the User class from user.py from App.database import db class Student(User): - id = db.Column(db.String(10), foreign_key=True, unique=True) #foreign key + id = db.Column(db.String(10), foreign_key=True, unique=True) name = db.Column(db.String(50)) + # Define a one-to-many relationship with PassCourses + course_history = db.relationship('PassCourses', backref='student', lazy=True) + + # Define a many-to-many relationship with CoursePlan + courses = db.relationship('CoursePlan', secondary='student_course', back_populates='students') + + # Define a many-to-many relationship with Programme + programmes = db.relationship('Programme', secondary='student_programme', back_populates='students') + def __init__(self, username, password, student_id, name): super().__init__(username, password) self.id = student_id @@ -19,3 +26,15 @@ def get_json(self): return user_json # You can add more methods specific to the Student class here + +# Define the many-to-many association table for courses +student_course_association = db.Table('student_course', + db.Column('student_id', db.String(10), db.ForeignKey('student.id')), + db.Column('course_id', db.Integer, db.ForeignKey('course_plan.id')) +) + +# Define the many-to-many association table for programmes +student_programme_association = db.Table('student_programme', + db.Column('student_id', db.String(10), db.ForeignKey('student.id')), + db.Column('programme_id', db.Integer, db.ForeignKey('programme.id')) +) diff --git a/wsgi.py b/wsgi.py index 87b4a3bab..b916b89df 100644 --- a/wsgi.py +++ b/wsgi.py @@ -49,6 +49,52 @@ def list_user_command(format): app.cli.add_command(user_cli) # add the group to the cli + +# ... (previous code remains the same) + +''' +Staff Commands +''' + +staff_cli = AppGroup('staff', help='Staff object commands') + +@staff_cli.command("add_programme", help="Add a program") +@click.argument("program_name") +@click.argument("description") +def add_programme_command(program_name, description): + from App.controllers.staff import StaffController # Import the StaffController + staff_controller = StaffController() # Initialize the StaffController + staff_controller.add_programme(program_name, description) # Call the add_programme method + print(f"Program '{program_name}' added!") + +@staff_cli.command("remove_programme", help="Remove a program") +@click.argument("program_name") +def remove_programme_command(program_name): + from App.controllers.staff import StaffController # Import the StaffController + staff_controller = StaffController() # Initialize the StaffController + staff_controller.remove_programme(program_name) # Call the remove_programme method + print(f"Program '{program_name}' removed!") + +@staff_cli.command("add_course", help="Add a course") +@click.argument("course_code") +@click.argument("course_name") +@click.argument("credits", type=int) +def add_course_command(course_code, course_name, credits): + from App.controllers.staff import StaffController # Import the StaffController + staff_controller = StaffController() # Initialize the StaffController + staff_controller.add_course(course_code, course_name, credits) # Call the add_course method + print(f"Course '{course_code}' added!") + +@staff_cli.command("remove_course", help="Remove a course") +@click.argument("course_code") +def remove_course_command(course_code): + from App.controllers.staff import StaffController # Import the StaffController + staff_controller = StaffController() # Initialize the StaffController + staff_controller.remove_course(course_code) # Call the remove_course method + print(f"Course '{course_code}' removed!") + +app.cli.add_command(staff_cli) + ''' Test Commands ''' From e08a8e2583f0231e7957cddc4cbc67099cf10c8c Mon Sep 17 00:00:00 2001 From: JervalThomas Date: Sun, 1 Oct 2023 18:57:48 -0400 Subject: [PATCH 17/90] Staff and Student Controllers --- App/controllers/student.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/App/controllers/student.py b/App/controllers/student.py index b5bf7eb2e..2d6c850c7 100644 --- a/App/controllers/student.py +++ b/App/controllers/student.py @@ -1,4 +1,4 @@ -from App.models import Student, CoursePlan, Program, PassCourses +from App.models import CoursePlan, Program, PassCourses from App.database import db From bc8391325d44b4271473470a063211888f2037d5 Mon Sep 17 00:00:00 2001 From: Ashley Jacob Date: Sun, 1 Oct 2023 19:40:31 -0400 Subject: [PATCH 18/90] Updates Course Plan controllers --- App/controllers/coursePlan.py | 39 ++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/App/controllers/coursePlan.py b/App/controllers/coursePlan.py index 3534e7512..cfd7b150c 100644 --- a/App/controllers/coursePlan.py +++ b/App/controllers/coursePlan.py @@ -1,11 +1,12 @@ from App.database import db from App.models import Student from App.models import CoursePlan -from App.models import Programme +from App.models import Program from App.models import Course def addCourse(Student, courseCode): plan=CoursePlan.query.filter_by(studentId=Student.id).first() + #verify prereqs plan.courses.append(courseCode) print(f'Course added') @@ -18,7 +19,7 @@ def removeCourse(Student, courseCode): print(f'Course not found') def getProgramme(Student): - return Programme.query.filter_by(programmeId=Student.programme_id).first() + return Program.query.filter_by(programmeId=Student.programme_id).first() def getRemainingCourses(completed, required): remaining=required.copy() @@ -29,33 +30,33 @@ def getRemainingCourses(completed, required): def getRemainingCore(Student): programme=getProgramme(Student) - reqCore=programme.cores + reqCore=programme.get_core_courses(programme.name) remaining=getRemainingCourses(Student.courseHistory,reqCore) return remaining def getRemainingFoun(Student): programme=getProgramme(Student) - reqFoun=programme.foun + reqFoun=programme.get_foun_courses(programme.name) remaining=getRemainingCourses(Student.courseHistory,reqFoun) return remaining def getRemainingElec(Student): programme=getProgramme(Student) - reqElec=programme.electives + reqElec=programme.get_elective_courses(programme.name) remaining=getRemainingCourses(Student.courseHistory,reqElec) return remaining def remElecCredits(Student): programme=getProgramme(Student) - requiredCreds=programme.elecCredits - for course in programme.electives: + requiredCreds=programme.get_elective_credits(programme.name) + for course in programme.get_elective_courses(programme.name): if course in Student.courseHistory: c=Course.query.filter_by(courseCode=course).first() #get course - requiredCreds=requiredCreds-c.credits #subtract credits + requiredCreds=requiredCreds-c.get_credits(course) #subtract credits return requiredCreds def findAvailable(courseList): - listing=1 #FIX - courses offered (posted by staff) + listing=[] #FIX - courses offered (posted by staff) available=[] for course in courseList: if course in listing: @@ -64,6 +65,21 @@ def findAvailable(courseList): available.append(c) return available #returns an array of course objects +def checkPrereq(Student, listing): + completed=Student.courseHistory + validCourses=[] + + for course in listing: + satisfied=True + prereq=course.get_prerequisites(course.courseCode) + #check if the student did all the prereq courses + for c in prereq: + if c not in completed: #if at least one was not done, the student can't take the course + satisfied=False + if satisfied: + validCourses.append(c) + + return validCourses def prioritizeElectives(Student): #get available electives @@ -71,7 +87,7 @@ def prioritizeElectives(Student): credits=remElecCredits(Student) courses=[] - #select courses to satisfy the programme's credit requiremen + #select courses to satisfy the programme's credit requirements for c in electives: if credits>0: courses.append(c) @@ -79,6 +95,7 @@ def prioritizeElectives(Student): #merge available, required core and foundation courses courses=courses + findAvailable(getRemainingCore(Student)) + findAvailable(getRemainingFoun(Student)) + courses=checkPrereq(Student,courses) return courses @@ -98,6 +115,7 @@ def easyCourses(Student): #merge available core and foundation courses and sort by difficulty courses= courses + findAvailable(getRemainingCore(Student)) + findAvailable(getRemainingFoun(Student)) courses.sort(key=lambda x:getattr(x, "rating", 0)) + courses=checkPrereq(Student,courses) return courses @@ -116,4 +134,5 @@ def fastestGraduation(Student): #get available, required core and foundation courses courses= courses + findAvailable(getRemainingCore(Student)) + findAvailable(getRemainingFoun(Student)) + courses=checkPrereq(Student,courses) return courses \ No newline at end of file From 3c654feb2cd2c63d52fc6673ce71cda495d06c39 Mon Sep 17 00:00:00 2001 From: JervalThomas Date: Sun, 1 Oct 2023 20:19:10 -0400 Subject: [PATCH 19/90] Staff and Student Controllers --- App/controllers/staff.py | 4 +- App/controllers/student.py | 97 ++++++++++++------- wsgi.py | 186 +++++++++++++++++++++++++++++-------- 3 files changed, 214 insertions(+), 73 deletions(-) diff --git a/App/controllers/staff.py b/App/controllers/staff.py index 973a74b55..79b8d4788 100644 --- a/App/controllers/staff.py +++ b/App/controllers/staff.py @@ -2,7 +2,7 @@ from App.database import db -def add_programme(self, program_name, description): +def add_program(self, program_name, description): try: new_program = Program(name=program_name, description=description) db.session.add(new_program) @@ -13,7 +13,7 @@ def add_programme(self, program_name, description): print(f"An error occurred while adding the program: {e}") -def remove_programme(self, program_name): +def remove_program(self, program_name): try: program = Program.query.filter_by(name=program_name).first() if program: diff --git a/App/controllers/student.py b/App/controllers/student.py index 2d6c850c7..1235fd89a 100644 --- a/App/controllers/student.py +++ b/App/controllers/student.py @@ -1,35 +1,68 @@ -from App.models import CoursePlan, Program, PassCourses +from App.models import Student, CoursePlan, Program from App.database import db +def create_student(username, password, student_id, name): + new_student = Student(username=username, password=password, id=student_id, name=name) + db.session.add(new_student) + db.session.commit() + return new_student -def enroll_in_programme(self, programme_id): - programme = Program.query.get(programme_id) - if programme: - self.student.programmes.append(programme) - db.session.commit() - -def add_course_to_plan(self, course_id): - course = CoursePlan.query.get(course_id) - if course: - self.student.courses.append(course) - db.session.commit() - -def remove_course_from_plan(self, course_id): - course = CoursePlan.query.get(course_id) - if course: - self.student.courses.remove(course) - db.session.commit() - -def view_course_plan(self): - return [course.get_json() for course in self.student.courses] - -def add_courses_from_file(self, file_path): - try: - with open(file_path, 'r') as file: - course_ids = [line.strip() for line in file.readlines()] - for course_id in course_ids: - self.add_course_to_plan(course_id) - except FileNotFoundError: - return "File not found." - except Exception as e: - return str(e) \ No newline at end of file +def get_student_by_username(username): + return Student.query.filter_by(username=username).first() + +def get_student(id): + return Student.query.get(id) + +def get_all_students(): + return Student.query.all() + +def get_all_students_json(): + students = Student.query.all() + if not students: + return [] + students_json = [student.get_json() for student in students] + return students_json + +def update_student(id, username): + student = get_student(id) + if student: + student.username = username + db.session.add(student) + db.session.commit() + return student + +def enroll_in_programme(student, programme_id): + programme = Program.query.get(programme_id) + if programme: + student.programmes.append(programme) + db.session.add(student) # Add the student object to the session + db.session.commit() + +def add_course_to_plan(student, course_id): + course = CoursePlan.query.get(course_id) + if course: + student.courses.append(course) + db.session.add(student) # Add the student object to the session + db.session.commit() + +def remove_course_from_plan(student, course_id): + course = CoursePlan.query.get(course_id) + if course: + student.courses.remove(course) + db.session.add(student) # Add the student object to the session + db.session.commit() + +def view_course_plan(student): + return [course.get_json() for course in student.courses] + +def add_courses_from_file(student, file_path): + try: + with open(file_path, 'r') as file: + course_ids = [line.strip() for line in file.readlines()] + for course_id in course_ids: + add_course_to_plan(student, course_id) + db.session.commit() # Commit the changes after adding courses + except FileNotFoundError: + return "File not found." + except Exception as e: + return str(e) diff --git a/wsgi.py b/wsgi.py index b916b89df..6f0c871a4 100644 --- a/wsgi.py +++ b/wsgi.py @@ -5,18 +5,32 @@ from App.database import db, get_migrate from App.main import create_app from App.controllers import ( create_user, get_all_users_json, get_all_users ) +from App.controllers import ( + create_student, + get_all_students_json, + get_all_students, + get_student_by_username, + get_student, + update_student, + enroll_in_programme, + add_course_to_plan, + remove_course_from_plan, + view_course_plan, + add_courses_from_file, ) # This commands file allow you to create convenient CLI commands for testing controllers app = create_app() migrate = get_migrate(app) + # This command creates and initializes the database @app.cli.command("init", help="Creates and initializes the database") def initialize(): db.drop_all() db.create_all() create_user('bob', 'bobpass') + print('database intialized') ''' @@ -53,47 +67,141 @@ def list_user_command(format): # ... (previous code remains the same) ''' -Staff Commands +Student ''' +student_cli = AppGroup("student", help="Student object commands") + +# Define the student create command +@student_cli.command("create", help="Creates a student") +@click.argument("username") +@click.argument("password") +@click.argument("student_id") +@click.argument("name") +def create_student_command(username, password, student_id, name): + create_student(username, password, student_id, name) + print(f"Student {username} created.") + + +# Define the student list command +@student_cli.command("list", help="Lists students in the database") +@click.argument("format", default="string") +def list_students_command(format): + if format == "string": + students = get_all_students() + for student in students: + print(student.get_json()) + else: + students_json = get_all_students_json() + print(students_json) + + +# Define the student get-by-username command +@student_cli.command("get-by-username", help="Get a student by username") +@click.argument("username") +def get_student_by_username_command(username): + student = get_student_by_username(username) + if student: + print(student.get_json()) + else: + print(f"Student with username {username} not found.") + + +# Define the student get command +@student_cli.command("get", help="Get a student by ID") +@click.argument("student_id", type=int) +def get_student_command(student_id): + student = get_student(student_id) + if student: + print(student.get_json()) + else: + print(f"Student with ID {student_id} not found.") + + +# Define the student update command +@student_cli.command("update", help="Update a student's username by ID") +@click.argument("student_id", type=int) +@click.argument("username") +def update_student_command(student_id, username): + updated_student = update_student(student_id, username) + if updated_student: + print(f"Student updated: {updated_student.get_json()}") + else: + print(f"Student with ID {student_id} not found.") + + +# Define the student enroll command +@student_cli.command("enroll", help="Enroll a student in a program by ID") +@click.argument("student_id", type=int) +@click.argument("programme_id") +def enroll_in_programme_command(student_id, programme_id): + student = get_student(student_id) + if student: + enroll_in_programme(student, programme_id) + print(f"Student enrolled in program with ID {programme_id}.") + else: + print(f"Student with ID {student_id} not found.") + + +# Define the student add-course command +@student_cli.command("add-course", help="Add a course to a student's plan by ID") +@click.argument("student_id", type=int) +@click.argument("course_id") +def add_course_to_plan_command(student_id, course_id): + student = get_student(student_id) + if student: + add_course_to_plan(student, course_id) + print(f"Course with ID {course_id} added to the student's plan.") + else: + print(f"Student with ID {student_id} not found.") + + +# Define the student remove-course command +@student_cli.command("remove-course", help="Remove a course from a student's plan by ID") +@click.argument("student_id", type=int) +@click.argument("course_id") +def remove_course_from_plan_command(student_id, course_id): + student = get_student(student_id) + if student: + remove_course_from_plan(student, course_id) + print(f"Course with ID {course_id} removed from the student's plan.") + else: + print(f"Student with ID {student_id} not found.") + + +# Define the student view-courses command +@student_cli.command("view-courses", help="View a student's course plan by ID") +@click.argument("student_id", type=int) +def view_course_plan_command(student_id): + student = get_student(student_id) + if student: + courses = view_course_plan(student) + if courses: + for course in courses: + print(course) + else: + print("No courses found in the plan.") + else: + print(f"Student with ID {student_id} not found.") + + +# Define the student add-courses-from-file command +@student_cli.command("add-courses-from-file", help="Add courses to a student's plan from a file") +@click.argument("student_id", type=int) +@click.argument("file_path") +def add_courses_from_file_command(student_id, file_path): + student = get_student(student_id) + if student: + result = add_courses_from_file(student, file_path) + if result: + print(result) + else: + print(f"Courses added from the file: {file_path}") + else: + print(f"Student with ID {student_id} not found.") + -staff_cli = AppGroup('staff', help='Staff object commands') - -@staff_cli.command("add_programme", help="Add a program") -@click.argument("program_name") -@click.argument("description") -def add_programme_command(program_name, description): - from App.controllers.staff import StaffController # Import the StaffController - staff_controller = StaffController() # Initialize the StaffController - staff_controller.add_programme(program_name, description) # Call the add_programme method - print(f"Program '{program_name}' added!") - -@staff_cli.command("remove_programme", help="Remove a program") -@click.argument("program_name") -def remove_programme_command(program_name): - from App.controllers.staff import StaffController # Import the StaffController - staff_controller = StaffController() # Initialize the StaffController - staff_controller.remove_programme(program_name) # Call the remove_programme method - print(f"Program '{program_name}' removed!") - -@staff_cli.command("add_course", help="Add a course") -@click.argument("course_code") -@click.argument("course_name") -@click.argument("credits", type=int) -def add_course_command(course_code, course_name, credits): - from App.controllers.staff import StaffController # Import the StaffController - staff_controller = StaffController() # Initialize the StaffController - staff_controller.add_course(course_code, course_name, credits) # Call the add_course method - print(f"Course '{course_code}' added!") - -@staff_cli.command("remove_course", help="Remove a course") -@click.argument("course_code") -def remove_course_command(course_code): - from App.controllers.staff import StaffController # Import the StaffController - staff_controller = StaffController() # Initialize the StaffController - staff_controller.remove_course(course_code) # Call the remove_course method - print(f"Course '{course_code}' removed!") - -app.cli.add_command(staff_cli) +# Add the student command group to the app's CLI +app.cli.add_command(student_cli) ''' Test Commands From 0a8224b0bf779d2a2f21727b2a0e7d451797645c Mon Sep 17 00:00:00 2001 From: JervalThomas Date: Sun, 1 Oct 2023 21:07:10 -0400 Subject: [PATCH 20/90] Staff and Student Controllers --- App/models/staff.py | 7 ++- App/models/student.py | 4 +- wsgi.py | 134 +----------------------------------------- 3 files changed, 7 insertions(+), 138 deletions(-) diff --git a/App/models/staff.py b/App/models/staff.py index 831fe507b..88bfb8335 100644 --- a/App/models/staff.py +++ b/App/models/staff.py @@ -1,10 +1,12 @@ # staff.py -from user import User # Import the User class from user.py +from .user import User # Import the User class from user.py from App.database import db class Staff(User): - id = db.Column(db.String(10), foreign_key=True, unique=True) #foreign key + + + id = db.Column(db.String(10), db.ForeignKey('user.id'), primary_key=True) #foreign key name = db.Column(db.String(50)) def __init__(self, username, password, staff_id, name): @@ -18,4 +20,3 @@ def get_json(self): user_json['name'] = self.name return user_json - # You can add more methods specific to the Staff class here diff --git a/App/models/student.py b/App/models/student.py index 59b8c9b97..6507a0816 100644 --- a/App/models/student.py +++ b/App/models/student.py @@ -1,8 +1,8 @@ -from user import User # Import the User class from user.py +from .user import User # Import the User class from user.py from App.database import db class Student(User): - id = db.Column(db.String(10), foreign_key=True, unique=True) + id = db.Column(db.String(10), db.ForeignKey('user.id'), primary_key=True) name = db.Column(db.String(50)) # Define a one-to-many relationship with PassCourses diff --git a/wsgi.py b/wsgi.py index 6f0c871a4..38dca2087 100644 --- a/wsgi.py +++ b/wsgi.py @@ -4,19 +4,7 @@ from App.database import db, get_migrate from App.main import create_app -from App.controllers import ( create_user, get_all_users_json, get_all_users ) -from App.controllers import ( - create_student, - get_all_students_json, - get_all_students, - get_student_by_username, - get_student, - update_student, - enroll_in_programme, - add_course_to_plan, - remove_course_from_plan, - view_course_plan, - add_courses_from_file, ) +from App.controllers import ( create_user, get_all_users_json, get_all_users, create_student,) # This commands file allow you to create convenient CLI commands for testing controllers @@ -81,126 +69,6 @@ def create_student_command(username, password, student_id, name): create_student(username, password, student_id, name) print(f"Student {username} created.") - -# Define the student list command -@student_cli.command("list", help="Lists students in the database") -@click.argument("format", default="string") -def list_students_command(format): - if format == "string": - students = get_all_students() - for student in students: - print(student.get_json()) - else: - students_json = get_all_students_json() - print(students_json) - - -# Define the student get-by-username command -@student_cli.command("get-by-username", help="Get a student by username") -@click.argument("username") -def get_student_by_username_command(username): - student = get_student_by_username(username) - if student: - print(student.get_json()) - else: - print(f"Student with username {username} not found.") - - -# Define the student get command -@student_cli.command("get", help="Get a student by ID") -@click.argument("student_id", type=int) -def get_student_command(student_id): - student = get_student(student_id) - if student: - print(student.get_json()) - else: - print(f"Student with ID {student_id} not found.") - - -# Define the student update command -@student_cli.command("update", help="Update a student's username by ID") -@click.argument("student_id", type=int) -@click.argument("username") -def update_student_command(student_id, username): - updated_student = update_student(student_id, username) - if updated_student: - print(f"Student updated: {updated_student.get_json()}") - else: - print(f"Student with ID {student_id} not found.") - - -# Define the student enroll command -@student_cli.command("enroll", help="Enroll a student in a program by ID") -@click.argument("student_id", type=int) -@click.argument("programme_id") -def enroll_in_programme_command(student_id, programme_id): - student = get_student(student_id) - if student: - enroll_in_programme(student, programme_id) - print(f"Student enrolled in program with ID {programme_id}.") - else: - print(f"Student with ID {student_id} not found.") - - -# Define the student add-course command -@student_cli.command("add-course", help="Add a course to a student's plan by ID") -@click.argument("student_id", type=int) -@click.argument("course_id") -def add_course_to_plan_command(student_id, course_id): - student = get_student(student_id) - if student: - add_course_to_plan(student, course_id) - print(f"Course with ID {course_id} added to the student's plan.") - else: - print(f"Student with ID {student_id} not found.") - - -# Define the student remove-course command -@student_cli.command("remove-course", help="Remove a course from a student's plan by ID") -@click.argument("student_id", type=int) -@click.argument("course_id") -def remove_course_from_plan_command(student_id, course_id): - student = get_student(student_id) - if student: - remove_course_from_plan(student, course_id) - print(f"Course with ID {course_id} removed from the student's plan.") - else: - print(f"Student with ID {student_id} not found.") - - -# Define the student view-courses command -@student_cli.command("view-courses", help="View a student's course plan by ID") -@click.argument("student_id", type=int) -def view_course_plan_command(student_id): - student = get_student(student_id) - if student: - courses = view_course_plan(student) - if courses: - for course in courses: - print(course) - else: - print("No courses found in the plan.") - else: - print(f"Student with ID {student_id} not found.") - - -# Define the student add-courses-from-file command -@student_cli.command("add-courses-from-file", help="Add courses to a student's plan from a file") -@click.argument("student_id", type=int) -@click.argument("file_path") -def add_courses_from_file_command(student_id, file_path): - student = get_student(student_id) - if student: - result = add_courses_from_file(student, file_path) - if result: - print(result) - else: - print(f"Courses added from the file: {file_path}") - else: - print(f"Student with ID {student_id} not found.") - - -# Add the student command group to the app's CLI app.cli.add_command(student_cli) ''' From 87c2928a32bafd5a2ab81dd1d76aee64d28f079a Mon Sep 17 00:00:00 2001 From: Ashley Jacob Date: Sun, 1 Oct 2023 21:30:09 -0400 Subject: [PATCH 21/90] Updates to course plan --- App/controllers/coursePlan.py | 6 +++--- App/models/coursePlan.py | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/App/controllers/coursePlan.py b/App/controllers/coursePlan.py index cfd7b150c..a85c98aee 100644 --- a/App/controllers/coursePlan.py +++ b/App/controllers/coursePlan.py @@ -91,7 +91,7 @@ def prioritizeElectives(Student): for c in electives: if credits>0: courses.append(c) - credits=credits-c.credits + credits=credits-c.get_credits(c.courseCode) #merge available, required core and foundation courses courses=courses + findAvailable(getRemainingCore(Student)) + findAvailable(getRemainingFoun(Student)) @@ -110,7 +110,7 @@ def easyCourses(Student): for c in electives: if credits>0: courses.append(c) - credits=credits-c.credits + credits=credits-c.get_credits(c.courseCode) #merge available core and foundation courses and sort by difficulty courses= courses + findAvailable(getRemainingCore(Student)) + findAvailable(getRemainingFoun(Student)) @@ -130,7 +130,7 @@ def fastestGraduation(Student): for c in electives: if credits>0: courses.append(c) - credits=credits-c.credits + credits=credits-c.get_credits(c.courseCode) #get available, required core and foundation courses courses= courses + findAvailable(getRemainingCore(Student)) + findAvailable(getRemainingFoun(Student)) diff --git a/App/models/coursePlan.py b/App/models/coursePlan.py index f0631ec7a..d288a1e8d 100644 --- a/App/models/coursePlan.py +++ b/App/models/coursePlan.py @@ -3,9 +3,9 @@ class CoursePlan(db.Model,UserMixin): planId=db.Column(db.Integer, primary_key=True) - studentId=db.Column(db.Integer, db.foreignkey('student.id'), nullable=False) - courses=db.Column(db.ARRAY(db.String), nullable=True) - student=db.relationship('Student', db.backref('CoursePlan')) + #studentId=db.Column(db.Integer, db.foreignkey('student.id'), nullable=False) + courses=db.Column(db.String(255), nullable=True) + #student=db.relationship('Student', db.backref('CoursePlan')) def __init__(self, studentId, courses=None): self.studentId = studentId From 111820f7d3849141dd07c2bb08b17668baf38d2a Mon Sep 17 00:00:00 2001 From: Ashley Jacob Date: Sun, 1 Oct 2023 22:03:55 -0400 Subject: [PATCH 22/90] Updated controllers --- .DS_Store | Bin 0 -> 6148 bytes App/.DS_Store | Bin 0 -> 6148 bytes App/controllers/__init__.py | 6 +- App/controllers/coursePlan.py | 38 ++++++++++-- App/controllers/courses.py | 25 ++++++++ App/controllers/offeredCourses.py | 16 +++++ App/controllers/program.py | 65 +++++++++++++++++++ App/models/__init__.py | 6 +- App/models/courses.py | 38 ++++++++++++ App/models/offeredCourses.py | 20 ++++++ App/models/program.py | 61 ++++++++++++++++++ testData/courseTest.txt | 5 ++ testData/test.txt | 9 +++ testData/test2.txt | 4 ++ wsgi.py | 100 +++++++++++++++++++++++++++++- 15 files changed, 384 insertions(+), 9 deletions(-) create mode 100644 .DS_Store create mode 100644 App/.DS_Store create mode 100644 App/controllers/courses.py create mode 100644 App/controllers/offeredCourses.py create mode 100644 App/controllers/program.py create mode 100644 App/models/courses.py create mode 100644 App/models/offeredCourses.py create mode 100644 App/models/program.py create mode 100644 testData/courseTest.txt create mode 100644 testData/test.txt create mode 100644 testData/test2.txt diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..d33561525b977ecafb01ff6cf6587d40bd8c155c GIT binary patch literal 6148 zcmeHK!A{#i5S=9{Y(PjkfanRW)N7Ig?SQC`b-0mp!2;H@!0-);l;A%{Gg-T!{mq$s=HKVqTL{IIwrm*k548Jz1` zP=@8S7=)8!8Xak!Mt6P~eM?5OVSDXBXJwdVqlqa<;t{6&_?~33o(=Rgiwjd5*a_K^ ztzmoP@^W{pqk8@Ryraa_MphZ`;2Is?%tbKC zQk|V)gt8@+FoFWD4!5PQEi!$&Rt>353 literal 0 HcmV?d00001 diff --git a/App/.DS_Store b/App/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..611dedb96f2fe70210cea19e5d791c1acacb5791 GIT binary patch literal 6148 zcmeHK%}T>S5T0$TrWBzEMUM+!3-(6~;w40V0V8@)sf{Tbj9E!ia|nf8)d$ii@p+ut z-D+#CM-kl#v)^WSCgJ-w>}CLfIYYk%PzL}Dov>8J<_n{F@);}XkqRP{&xk=lh}Qt( znP@Zc8x^3ntHC9%TLdYt+Q<4OUY6W>q3|%`#k&iGByBcdS*cuESX{D}teSQ1UW?34 z`{^)o`td2<9SIS7<9^>e4hC7TzOpBxv>!x+SSAGi07K4Bg2)${BZiTm$Xr)VSXHaq ztFPyId%M-(?QVC};Q3Cw+2C89?r2oCRyQ_x4|_M^Z6qF*qzu14Y0DbN@PwT??C#w- z3Pp5<5tO|E_YmNBo53XS=O5?2mLt~&Z*@A~(0)+-=F%ovCJ23^s*+7>6fg?>YX$VK zY1RI<3WmH9Q^{FjN%G~? Date: Mon, 2 Oct 2023 14:02:27 -0400 Subject: [PATCH 23/90] Staff and Student Controllers --- wsgi.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/wsgi.py b/wsgi.py index 0806762e1..29388cdfb 100644 --- a/wsgi.py +++ b/wsgi.py @@ -4,9 +4,6 @@ from App.database import db, get_migrate from App.main import create_app -<<<<<<< HEAD -from App.controllers import ( create_user, get_all_users_json, get_all_users, create_student,) -======= from App.controllers import ( create_user, get_all_users_json, @@ -19,7 +16,6 @@ get_prerequisites, ) ->>>>>>> jerrellebranch # This commands file allow you to create convenient CLI commands for testing controllers From bb63319b690221739a511c4c872b0b6dd95cc1d4 Mon Sep 17 00:00:00 2001 From: JervalThomas Date: Mon, 2 Oct 2023 14:45:50 -0400 Subject: [PATCH 24/90] Staff and Student Controllers --- App/models/student.py | 73 ++++++++++++++++++++++++++----------------- 1 file changed, 44 insertions(+), 29 deletions(-) diff --git a/App/models/student.py b/App/models/student.py index 6507a0816..ecac1bbe6 100644 --- a/App/models/student.py +++ b/App/models/student.py @@ -1,40 +1,55 @@ from .user import User # Import the User class from user.py from App.database import db +import json class Student(User): id = db.Column(db.String(10), db.ForeignKey('user.id'), primary_key=True) name = db.Column(db.String(50)) + course_history = db.Column(db.String(500)) + nextSemCourses = db.Column(db.String(50)) + program = db.Column(db.String(50)) + +# def __init__(self, file_path): +# try: +# with open(file_path, 'r') as file: +# lines = file.readlines() +# self.name = lines[0].strip() +# self.level1_credits = lines[1].strip() +# self.level1_courses = json.dumps(lines[2].strip().split(',')) +# self.core_credits = lines[3].strip() +# self.core_courses = json.dumps(lines[4].strip().split(',')) +# self.elective_credits = lines[5].strip() +# self.elective_courses = json.dumps(lines[6].strip().split(',')) +# self.foun_credits = lines[7].strip() +# self.foun_courses = json.dumps(lines[8].strip().split(',')) + +# except FileNotFoundError: +# print("File not found.") + +# except Exception as e: +# print(f"An error occurred: {e}") + +def __init__(self, username, password, student_id, name, file_path): + super().__init__(username, password) + self.id = student_id + self.name = name + + with open(file_path, 'r') as file: + lines = file.readlines() - # Define a one-to-many relationship with PassCourses - course_history = db.relationship('PassCourses', backref='student', lazy=True) - # Define a many-to-many relationship with CoursePlan - courses = db.relationship('CoursePlan', secondary='student_course', back_populates='students') + # course History, courses, programmes using a file, - # Define a many-to-many relationship with Programme - programmes = db.relationship('Programme', secondary='student_programme', back_populates='students') +# needed for nextSemCourses and Course history +# def get_prerequisites(self): +# return json.loads(self.prerequisites) if self.prerequisites else [] - def __init__(self, username, password, student_id, name): - super().__init__(username, password) - self.id = student_id - self.name = name +def get_json(self): + return{ + 'student_id': self.id, + 'name': self.name, + 'course history': self.course_history, + 'next semester courses': self.nextSemCourses, + 'program' : self.program + } - def get_json(self): - user_json = super().get_json() - user_json['student_id'] = self.id - user_json['name'] = self.name - return user_json - - # You can add more methods specific to the Student class here - -# Define the many-to-many association table for courses -student_course_association = db.Table('student_course', - db.Column('student_id', db.String(10), db.ForeignKey('student.id')), - db.Column('course_id', db.Integer, db.ForeignKey('course_plan.id')) -) - -# Define the many-to-many association table for programmes -student_programme_association = db.Table('student_programme', - db.Column('student_id', db.String(10), db.ForeignKey('student.id')), - db.Column('programme_id', db.Integer, db.ForeignKey('programme.id')) -) From 39bffcec398701ab33bdfd9bd84e3f195b7d2415 Mon Sep 17 00:00:00 2001 From: JervalThomas Date: Mon, 2 Oct 2023 21:20:41 -0400 Subject: [PATCH 25/90] changing controllers methods for stuuden to suit app concept --- App/controllers/staff.py | 100 ++++++++++++++++++++----------------- App/controllers/student.py | 90 +++++++++++++++++---------------- App/models/staff.py | 20 +++----- App/models/student.py | 51 ++++++------------- 4 files changed, 124 insertions(+), 137 deletions(-) diff --git a/App/controllers/staff.py b/App/controllers/staff.py index 79b8d4788..22d4506b9 100644 --- a/App/controllers/staff.py +++ b/App/controllers/staff.py @@ -1,50 +1,56 @@ -from App.models import Program, Course +from App.models import Program, Course, Staff from App.database import db -def add_program(self, program_name, description): - try: - new_program = Program(name=program_name, description=description) - db.session.add(new_program) - db.session.commit() - return new_program - except Exception as e: - db.session.rollback() - print(f"An error occurred while adding the program: {e}") - - -def remove_program(self, program_name): - try: - program = Program.query.filter_by(name=program_name).first() - if program: - db.session.delete(program) - db.session.commit() - else: - print(f"Program '{program_name}' not found.") - except Exception as e: - db.session.rollback() - print(f"An error occurred while removing the program: {e}") - - -def add_course(self, course_code, course_name, credits): - try: - new_course = Course(code=course_code, name=course_name, credits=credits) - db.session.add(new_course) - db.session.commit() - return new_course - except Exception as e: - db.session.rollback() - print(f"An error occurred while adding the course: {e}") - - -def remove_course(self, course_code): - try: - course = Course.query.filter_by(code=course_code).first() - if course: - db.session.delete(course) - db.session.commit() - else: - print(f"Course '{course_code}' not found.") - except Exception as e: - db.session.rollback() - print(f"An error occurred while removing the course: {e}") +def create_staff(password, staff_id, name): + new_staff = Staff(password, staff_id, name) + db.session.add(new_staff) + db.session.commit() + return new_staff + +# def add_program(self, program_name, description): +# try: +# new_program = Program(name=program_name, description=description) +# db.session.add(new_program) +# db.session.commit() +# return new_program +# except Exception as e: +# db.session.rollback() +# print(f"An error occurred while adding the program: {e}") + + +# def remove_program(self, program_name): +# try: +# program = Program.query.filter_by(name=program_name).first() +# if program: +# db.session.delete(program) +# db.session.commit() +# else: +# print(f"Program '{program_name}' not found.") +# except Exception as e: +# db.session.rollback() +# print(f"An error occurred while removing the program: {e}") + + +# def add_course(self, course_code, course_name, credits): +# try: +# new_course = Course(code=course_code, name=course_name, credits=credits) +# db.session.add(new_course) +# db.session.commit() +# return new_course +# except Exception as e: +# db.session.rollback() +# print(f"An error occurred while adding the course: {e}") + + +# def remove_course(self, course_code): +# try: +# course = Course.query.filter_by(code=course_code).first() +# if course: +# db.session.delete(course) +# db.session.commit() +# else: +# print(f"Course '{course_code}' not found.") +# except Exception as e: +# db.session.rollback() +# print(f"An error occurred while removing the course: {e}") diff --git a/App/controllers/student.py b/App/controllers/student.py index 1235fd89a..2d4e9d482 100644 --- a/App/controllers/student.py +++ b/App/controllers/student.py @@ -1,8 +1,8 @@ from App.models import Student, CoursePlan, Program from App.database import db -def create_student(username, password, student_id, name): - new_student = Student(username=username, password=password, id=student_id, name=name) +def create_student(file_path): + new_student = Student(file_path) db.session.add(new_student) db.session.commit() return new_student @@ -10,9 +10,6 @@ def create_student(username, password, student_id, name): def get_student_by_username(username): return Student.query.filter_by(username=username).first() -def get_student(id): - return Student.query.get(id) - def get_all_students(): return Student.query.all() @@ -23,46 +20,53 @@ def get_all_students_json(): students_json = [student.get_json() for student in students] return students_json -def update_student(id, username): - student = get_student(id) - if student: - student.username = username - db.session.add(student) - db.session.commit() - return student +def get_course_history(username): + student = get_student_by_username(username) + return student.course_history if student else [] + +def get_program(username): + student = get_student_by_username(username) + return student.program if student else "" + +def get_nextSemCourses(username): + student = get_student_by_username(username) + return student.nextSemCourses if student else [] -def enroll_in_programme(student, programme_id): - programme = Program.query.get(programme_id) - if programme: - student.programmes.append(programme) - db.session.add(student) # Add the student object to the session - db.session.commit() +# def enroll_in_programme(student, programme_id): +# programme = Program.query.get(programme_id) +# if programme: +# student.programmes.append(programme) +# db.session.add(student) # Add the student object to the session +# db.session.commit() -def add_course_to_plan(student, course_id): - course = CoursePlan.query.get(course_id) - if course: - student.courses.append(course) - db.session.add(student) # Add the student object to the session - db.session.commit() +# def add_course_to_plan(student, course_id): +# #Ashely needed here +# course = CoursePlan.query.get(course_id) +# if course: +# student.courses.append(course) +# db.session.add(student) +# db.session.commit() -def remove_course_from_plan(student, course_id): - course = CoursePlan.query.get(course_id) - if course: - student.courses.remove(course) - db.session.add(student) # Add the student object to the session - db.session.commit() +# def remove_course_from_plan(student, course_id): +# #Ashely needed here +# course = CoursePlan.query.get(course_id) +# if course: +# student.courses.remove(course) +# db.session.add(student) # Add the student object to the session +# db.session.commit() -def view_course_plan(student): - return [course.get_json() for course in student.courses] +# def view_course_plan(student): +# #Ashely needed here +# return [course.get_json() for course in student.courses] -def add_courses_from_file(student, file_path): - try: - with open(file_path, 'r') as file: - course_ids = [line.strip() for line in file.readlines()] - for course_id in course_ids: - add_course_to_plan(student, course_id) - db.session.commit() # Commit the changes after adding courses - except FileNotFoundError: - return "File not found." - except Exception as e: - return str(e) +# def add_courses_from_file(student, file_path): +# try: +# with open(file_path, 'r') as file: +# course_ids = [line.strip() for line in file.readlines()] +# for course_id in course_ids: +# add_course_to_plan(student, course_id) +# db.session.commit() # Commit the changes after adding courses +# except FileNotFoundError: +# return "File not found." +# except Exception as e: +# return str(e) diff --git a/App/models/staff.py b/App/models/staff.py index 88bfb8335..e517ba863 100644 --- a/App/models/staff.py +++ b/App/models/staff.py @@ -1,22 +1,18 @@ -# staff.py - -from .user import User # Import the User class from user.py +from .user import User from App.database import db class Staff(User): - - - id = db.Column(db.String(10), db.ForeignKey('user.id'), primary_key=True) #foreign key + id = db.Column(db.String(10), db.ForeignKey('user.id'), primary_key=True) name = db.Column(db.String(50)) - def __init__(self, username, password, staff_id, name): - super().__init__(username, password) + def __init__(self, password, staff_id, name): + super().__init__(staff_id, password) self.id = staff_id self.name = name def get_json(self): - user_json = super().get_json() - user_json['staff_id'] = self.id - user_json['name'] = self.name - return user_json + return{ + 'staff_id': self.id, + 'name': self.name, + } diff --git a/App/models/student.py b/App/models/student.py index ecac1bbe6..b80cc4881 100644 --- a/App/models/student.py +++ b/App/models/student.py @@ -1,50 +1,31 @@ -from .user import User # Import the User class from user.py +from App.models import User from App.database import db import json class Student(User): - id = db.Column(db.String(10), db.ForeignKey('user.id'), primary_key=True) + id = db.Column( db.ForeignKey('user.id'), primary_key=True) name = db.Column(db.String(50)) course_history = db.Column(db.String(500)) + #CoursePlan -> nextSemCourses nextSemCourses = db.Column(db.String(50)) program = db.Column(db.String(50)) -# def __init__(self, file_path): -# try: -# with open(file_path, 'r') as file: -# lines = file.readlines() -# self.name = lines[0].strip() -# self.level1_credits = lines[1].strip() -# self.level1_courses = json.dumps(lines[2].strip().split(',')) -# self.core_credits = lines[3].strip() -# self.core_courses = json.dumps(lines[4].strip().split(',')) -# self.elective_credits = lines[5].strip() -# self.elective_courses = json.dumps(lines[6].strip().split(',')) -# self.foun_credits = lines[7].strip() -# self.foun_courses = json.dumps(lines[8].strip().split(',')) - -# except FileNotFoundError: -# print("File not found.") -# except Exception as e: -# print(f"An error occurred: {e}") - -def __init__(self, username, password, student_id, name, file_path): - super().__init__(username, password) - self.id = student_id - self.name = name - + def __init__(self, file_path): with open(file_path, 'r') as file: lines = file.readlines() - - - # course History, courses, programmes using a file, - -# needed for nextSemCourses and Course history -# def get_prerequisites(self): -# return json.loads(self.prerequisites) if self.prerequisites else [] - -def get_json(self): + username = lines[0].strip() + password = lines[1].strip() + super.__init__(username, password) + self.id = lines[0].strip() + self.name = lines[2].strip() + self.program = lines[3].strip() + self.course_history = json.dumps(lines[4].strip().split(',')) + + def str_course_history(self): + return json.loads(self.course_history) if self.course_history else [] + + def get_json(self): return{ 'student_id': self.id, 'name': self.name, From 7e90192690427189fb9d9a603a7dfc8e7eb568e8 Mon Sep 17 00:00:00 2001 From: Ashley Jacob Date: Tue, 3 Oct 2023 05:00:45 -0400 Subject: [PATCH 26/90] Updated course plan --- App/controllers/coursePlan.py | 8 ++++---- App/models/coursePlan.py | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/App/controllers/coursePlan.py b/App/controllers/coursePlan.py index 1494d6752..346dc3b1c 100644 --- a/App/controllers/coursePlan.py +++ b/App/controllers/coursePlan.py @@ -1,6 +1,6 @@ from App.database import db -from App.models import Student -from App.models import Staff +#from App.models import Student +#from App.models import Staff from App.models import CoursePlan from App.models import Program from App.models import Course @@ -12,8 +12,8 @@ def getProgramme(Student): def getOfferedCourses(): - staff=Staff.first() - return staff.get_all_courses() + listing=OfferedCourses.first() + return listing.offered def addCourse(Student, courseCode): diff --git a/App/models/coursePlan.py b/App/models/coursePlan.py index a68d53ac4..671f66ae7 100644 --- a/App/models/coursePlan.py +++ b/App/models/coursePlan.py @@ -4,9 +4,9 @@ class CoursePlan(db.Model,UserMixin): planId=db.Column(db.Integer, primary_key=True) - studentId=db.Column(db.Integer, db.foreignkey('student.id'), nullable=False) + #studentId=db.Column(db.Integer, db.foreignkey('student.id'), nullable=False) courses=db.Column(db.ARRAY(db.String), nullable=True) - student=db.relationship('Student', db.backref('CoursePlan')) + #=db.relationship('Student', db.backref('CoursePlan')) def __init__(self, studentId, courses=None): self.studentId = studentId From f508844f1634d3c106bd5ebe35f5c844359c3352 Mon Sep 17 00:00:00 2001 From: Ashley Jacob Date: Tue, 3 Oct 2023 15:24:47 -0400 Subject: [PATCH 27/90] Updated admin and cli commands --- App/controllers/admin.py | 57 ++++++++++++++++++++++++++-------------- App/models/admin.py | 5 ++-- App/models/coursePlan.py | 2 +- wsgi.py | 34 +++++++++++++++++++++++- 4 files changed, 74 insertions(+), 24 deletions(-) diff --git a/App/controllers/admin.py b/App/controllers/admin.py index bc78840c7..cf847fdae 100644 --- a/App/controllers/admin.py +++ b/App/controllers/admin.py @@ -1,35 +1,52 @@ from App.models import User from App.models import Student from App.models import Staff +from App.models import Admin from App.database import db +from App.controllers import create_user +from App.controllers.staff import create_staff -def addStudent(id,username,password): #creates new student - newstudent=Student(id=id,username=username,password=password) - try: - db.session.add(newstudent) - db.session.commit() - except Exception as e: #student already exists - db.session.rollback() - print(f'Username or ID already taken') - print(f'Student created.') - return newstudent - -def addStaff(id,username,password): #creates new staff member - newstaff=Staff(id=id,username=username,password=password) - try: - db.session.add(newstaff) - db.session.commit() - except Exception as e: #staff already exists - db.session.rollback() - print(f'Username or ID already taken') - print(f'Staff created.') + +def createAdmin(id, username, password, name): + newadmin = Admin(id, username, password, name) + try: + db.session.add(newadmin) + db.session.commit() + except Exception as e: #admin already exists + db.session.rollback() + print(f'Username already taken') + print(f'Admin created.') + return newadmin + + +# def addStudent(id,username,password): #creates new student +# newstudent=Student(id=id,username=username,password=password) +# try: +# db.session.add(newstudent) +# db.session.commit() +# except Exception as e: #student already exists +# db.session.rollback() +# print(f'Username or ID already taken') +# print(f'Student created.') +# return newstudent + + +def addStaff(id,username,password,name): #creates new staff member + newstaff = create_staff(password, id, name) return newstaff + def removeAccount(id): #removes account by id acc=User.query.filter_by(id=id).first() if not acc: print(f'Account with ID {id} not found.') return + student=Student.query.filter_by(id=id).first() + staff=Staff.query.filter_by(id=id).first() + if student: + db.session.delete(student) + else: + db.session.delete(staff) db.session.delete(acc) db.session.commit() print(f'Account deleted.') diff --git a/App/models/admin.py b/App/models/admin.py index ac857a337..100a88229 100644 --- a/App/models/admin.py +++ b/App/models/admin.py @@ -2,13 +2,14 @@ from App.models import User class Admin(User): - id=db.Column(db.foreignkey('user.id'), nullable=False) + id=db.Column(db.ForeignKey('user.id'), primary_key=True) name=db.Column(db.String(120), nullable=False) - user=db.relationship('User',backref=db.backref('Admin')) + # user=db.relationship('User',backref=db.backref('Admin')) def __init__(self, username, password, name): super.__init__(username=username,password=password) self.name=name + self.id=id def get_json(self): return{ diff --git a/App/models/coursePlan.py b/App/models/coursePlan.py index 671f66ae7..7d67350b1 100644 --- a/App/models/coursePlan.py +++ b/App/models/coursePlan.py @@ -5,7 +5,7 @@ class CoursePlan(db.Model,UserMixin): planId=db.Column(db.Integer, primary_key=True) #studentId=db.Column(db.Integer, db.foreignkey('student.id'), nullable=False) - courses=db.Column(db.ARRAY(db.String), nullable=True) + courses=db.Column(db.String(200), nullable=True) #=db.relationship('Student', db.backref('CoursePlan')) def __init__(self, studentId, courses=None): diff --git a/wsgi.py b/wsgi.py index 42f0f150c..06f73b645 100644 --- a/wsgi.py +++ b/wsgi.py @@ -1,5 +1,7 @@ import click, pytest, sys from flask import Flask +from App.controllers.admin import addStaff, createAdmin, removeAccount +from App.controllers.student import create_student from flask.cli import with_appcontext, AppGroup from App.database import db, get_migrate @@ -18,7 +20,6 @@ getRemainingCourses, ) - # This commands file allow you to create convenient CLI commands for testing controllers app = create_app() @@ -84,6 +85,37 @@ def create_student_command(username, password, student_id, name): app.cli.add_command(student_cli) +''' +Admin Commands +''' + +admin_cli = AppGroup("admin", help="Admin object commands") + +# Define the admin create command +@admin_cli.command("create_admin", help="Creates an admin") +@click.argument("id") +@click.argument("username") +@click.argument("password") +@click.argument("name") +def create_admin_command(id, username, password, name): + createAdmin(id, username, password, name) + +@admin_cli.command("create_staff", help="Creates a staff member") +@click.argument("id") +@click.argument("username") +@click.argument("password") +@click.argument("name") +def create_staff_command(id, username, password, name): + addStaff(id, username, password, name) + print(f"Staff member {username} created") + +@admin_cli.command("delete", help="Creates a staff member") +@click.argument("id") +def delete_user_command(id): + removeAccount(id) + +app.cli.add_command(admin_cli) + ''' Test Commands ''' From 2c8b02cc3eeb4b75b0fb5960a0e24cbf6d84106f Mon Sep 17 00:00:00 2001 From: Ashley Jacob Date: Tue, 3 Oct 2023 15:31:37 -0400 Subject: [PATCH 28/90] updated init files --- App/controllers/__init__.py | 1 + App/models/__init__.py | 1 + App/models/admin.py | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/App/controllers/__init__.py b/App/controllers/__init__.py index 75b9e83ee..246361243 100644 --- a/App/controllers/__init__.py +++ b/App/controllers/__init__.py @@ -4,6 +4,7 @@ from .program import * from .staff import * from .student import * +from .admin import * from .courses import * from .coursePlan import * from .offeredCourses import * diff --git a/App/models/__init__.py b/App/models/__init__.py index 8104b6ecd..c558e06fb 100644 --- a/App/models/__init__.py +++ b/App/models/__init__.py @@ -3,6 +3,7 @@ from .program import * from .staff import * from .student import * +from .admin import * from .courses import * from .coursePlan import * from .offeredCourses import * diff --git a/App/models/admin.py b/App/models/admin.py index 100a88229..6668c6538 100644 --- a/App/models/admin.py +++ b/App/models/admin.py @@ -7,7 +7,7 @@ class Admin(User): # user=db.relationship('User',backref=db.backref('Admin')) def __init__(self, username, password, name): - super.__init__(username=username,password=password) + super().__init__(username=username,password=password) self.name=name self.id=id From 11bf53297e3f48aaebb0b5d2b3eeeb10512b9dd7 Mon Sep 17 00:00:00 2001 From: Ashley Jacob Date: Tue, 3 Oct 2023 16:26:14 -0400 Subject: [PATCH 29/90] Updated course plan controller-addCourse() --- App/controllers/coursePlan.py | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/App/controllers/coursePlan.py b/App/controllers/coursePlan.py index 346dc3b1c..0ef4e21d2 100644 --- a/App/controllers/coursePlan.py +++ b/App/controllers/coursePlan.py @@ -1,6 +1,6 @@ from App.database import db -#from App.models import Student -#from App.models import Staff +from App.models import Student +from App.models import Staff from App.models import CoursePlan from App.models import Program from App.models import Course @@ -20,15 +20,20 @@ def addCourse(Student, courseCode): plan=CoursePlan.query.filter_by(studentId=Student.id).first() course=checkPrereq(Student,[{courseCode}]) #verify prereqs if course: - validCourse=findAvailable(course)#check availability + availableCourse=findAvailable(course) #check availability + if availableCourse: + requiredCourses=getRemainingCore(Student)+getRemainingElec(Student)+getRemainingFoun(Student) + remainingCourses=getRemainingCourses(Student.courseHistory, requiredCourses) + if courseCode in remainingCourses: #if course is listed as a degree requirement + plan.courses.append(courseCode) + print(f'Course added') + else: #course is not listed as a degree requirement + print(f'Course added. NOTE: This course is not required for your degree.') + else: + print(f'Course not available') else: print(f'Pre-req unsatisfied') - - if validCourse: - plan.courses.append(courseCode) - print(f'Course added') - else: - print(f'Course not available') + return def removeCourse(Student, courseCode): From 06ed45095dca40f954d68bb5466f43f322d755fb Mon Sep 17 00:00:00 2001 From: Jerrelle Johnson Date: Tue, 3 Oct 2023 20:46:49 -0400 Subject: [PATCH 30/90] scaled the course code to read larger files --- App/controllers/courses.py | 27 ++++++++++++++++++++++----- App/models/coursePlan.py | 6 +++--- App/models/courses.py | 16 ++-------------- App/views/course.py | 24 ++++++++++++++++++++++++ testData/courseTest.txt | 8 +++++++- wsgi.py | 4 ++-- 6 files changed, 60 insertions(+), 25 deletions(-) create mode 100644 App/views/course.py diff --git a/App/controllers/courses.py b/App/controllers/courses.py index b8aa32946..9928a7410 100644 --- a/App/controllers/courses.py +++ b/App/controllers/courses.py @@ -1,13 +1,30 @@ from App.models import Course from App.database import db +import json def create_course(file_path): - newCourse = Course(file_path) - db.session.add(newCourse) - db.session.commit() - return newCourse - + try: + with open(file_path, 'r') as file: + lines = file.readlines() + for i in range(0, len(lines), 6): + course = Course() + course.courseCode = lines[i].strip() + course.courseName = lines[i + 1].strip() + course.credits = int(lines[i + 2].strip()) + course.rating = int(lines[i + 3].strip()) + course.prerequisites = json.dumps(lines[i + 4].strip().split(',')) + db.session.add(course) + + db.session.commit() + except FileNotFoundError: + print("File not found.") + return False + + except Exception as e: + print(f"An error occurred: {e}") + return False + def get_course_by_courseCode(code): return Course.query.filter_by(courseCode=code).first() diff --git a/App/models/coursePlan.py b/App/models/coursePlan.py index a68d53ac4..3aa0740be 100644 --- a/App/models/coursePlan.py +++ b/App/models/coursePlan.py @@ -4,9 +4,9 @@ class CoursePlan(db.Model,UserMixin): planId=db.Column(db.Integer, primary_key=True) - studentId=db.Column(db.Integer, db.foreignkey('student.id'), nullable=False) - courses=db.Column(db.ARRAY(db.String), nullable=True) - student=db.relationship('Student', db.backref('CoursePlan')) + studentId=db.Column(db.Integer, db.ForeignKey('student.id'), nullable=False) + #courses=db.Column(db.ARRAY(db.String), nullable=True) + #student=db.relationship('Student', db.backref('CoursePlan')) def __init__(self, studentId, courses=None): self.studentId = studentId diff --git a/App/models/courses.py b/App/models/courses.py index 1856e20d5..b53c0399f 100644 --- a/App/models/courses.py +++ b/App/models/courses.py @@ -8,21 +8,9 @@ class Course(db.Model): rating = db.Column(db.Integer) prerequisites = db.Column(db.String(24)) - def __init__(self, file_path): - try: - with open(file_path, 'r') as file: - lines = file.readlines() - self.courseCode = lines[0].strip() - self.courseName = lines[1].strip() - self.credits = lines[2].strip() - self.rating = lines[3].strip() - self.prerequisites = json.dumps(lines[4].strip().split(',')) + def __init__(self): + pass - except FileNotFoundError: - print("File not found.") - - except Exception as e: - print(f"An error occurred: {e}") def get_prerequisites(self): return json.loads(self.prerequisites) if self.prerequisites else [] diff --git a/App/views/course.py b/App/views/course.py new file mode 100644 index 000000000..1716ecc15 --- /dev/null +++ b/App/views/course.py @@ -0,0 +1,24 @@ +from flask import Blueprint, jsonify, request + +from App.controllers import create_course + +course_views = Blueprint('course_views', __name__, template_folder='../templates') + +@course_views.route('/courses/', methods=['POST']) +def upload_course(): + try: + data = request.get_json() + + if not all(key in data for key in ('file_path',)): + return jsonify({'error': 'Invalid request data'}), 400 + + file_path = data['file_path'] + new_course = create_course(file_path) + + return jsonify({'message': f'Course {new_course.courseCode} created successfully'}), 201 + + except Exception as e: + return jsonify({'error': f'An error occurred: {str(e)}'}), 50 + + + \ No newline at end of file diff --git a/testData/courseTest.txt b/testData/courseTest.txt index c82a53610..0f3115149 100644 --- a/testData/courseTest.txt +++ b/testData/courseTest.txt @@ -2,4 +2,10 @@ COMP3605 Data Analytics 3 3 -COMP2611, MATH2250 \ No newline at end of file +COMP2611, MATH2250 + +COMP3610 +Big Data Analytics +3 +3 +COMP3605 \ No newline at end of file diff --git a/wsgi.py b/wsgi.py index 42f0f150c..703c3088e 100644 --- a/wsgi.py +++ b/wsgi.py @@ -31,7 +31,7 @@ def initialize(): db.drop_all() db.create_all() create_user('bob', 'bobpass') - + create_course('testData/courseTest.txt') print('database intialized') ''' @@ -79,7 +79,7 @@ def list_user_command(format): @click.argument("student_id") @click.argument("name") def create_student_command(username, password, student_id, name): - create_student(username, password, student_id, name) + #create_student(username, password, student_id, name) print(f"Student {username} created.") app.cli.add_command(student_cli) From 0a7c0d4cb4eadd35e719780ba5c592d6b7bdf587 Mon Sep 17 00:00:00 2001 From: Jerrelle Johnson Date: Tue, 3 Oct 2023 21:42:57 -0400 Subject: [PATCH 31/90] changed offeredCourses and added staff view --- App/controllers/offeredCourses.py | 15 ++++++++++----- App/models/offeredCourses.py | 26 ++++++++++---------------- App/views/__init__.py | 4 +++- App/views/auth.py | 3 ++- App/views/staff.py | 26 ++++++++++++++++++++++++++ wsgi.py | 6 ++++++ 6 files changed, 57 insertions(+), 23 deletions(-) create mode 100644 App/views/staff.py diff --git a/App/controllers/offeredCourses.py b/App/controllers/offeredCourses.py index 7d066f1e2..0f6bd0fbc 100644 --- a/App/controllers/offeredCourses.py +++ b/App/controllers/offeredCourses.py @@ -1,12 +1,17 @@ from App.models import OfferedCourses +from App.controllers import get_course_by_courseCode from App.database import db import json -def addSemesterCourses(file_path): - semCourses = OfferedCourses(file_path) - db.sesssion.add(semCourses) - db.session.commit() - return semCourses +def addSemesterCourses(courseCode): + course = get_course_by_courseCode(courseCode) + if course: + semCourses = OfferedCourses(courseCode) + db.session.add(semCourses) + db.session.commit() + return course + else: + print("Course not found") def removeAllCourses(semCourses): semCourses.offered = json.dumps([]) diff --git a/App/models/offeredCourses.py b/App/models/offeredCourses.py index 4261f1fa1..fba028955 100644 --- a/App/models/offeredCourses.py +++ b/App/models/offeredCourses.py @@ -1,20 +1,14 @@ import json from App.database import db -class OfferedCourses: - offered = db.Column(db.String(1000)) +class OfferedCourses(db.Model): + id = db.Column(db.Integer, primary_key=True) + offered = db.Column(db.String(10)) - def __init__(self, file_path): - try: - with open(file_path, 'r') as file: - lines = file.readlines() - self.offered = json.dumps([course_code.strip() for course_code in lines]) - - except FileNotFoundError: - print("File not found.") - - except Exception as e: - print(f"An error occurred: {e}") - - def toString(self): - return json.loads(self.offered) if self.offered else [] + def __init__(self, courseCode): + self.offered = courseCode + + def get_json(self): + return{ + 'Course Code:': self.offered + } diff --git a/App/views/__init__.py b/App/views/__init__.py index 3a4791e19..1658f4ee1 100644 --- a/App/views/__init__.py +++ b/App/views/__init__.py @@ -3,7 +3,9 @@ from .user import user_views from .index import index_views from .auth import auth_views +from .course import course_views +from .staff import staff_views -views = [user_views, index_views, auth_views] +views = [user_views, index_views, auth_views, course_views, staff_views] # blueprints must be added to this list \ No newline at end of file diff --git a/App/views/auth.py b/App/views/auth.py index 291a02bbd..f4c14a162 100644 --- a/App/views/auth.py +++ b/App/views/auth.py @@ -7,7 +7,8 @@ from App.controllers import ( create_user, jwt_authenticate, - login + login, + get_all_users ) auth_views = Blueprint('auth_views', __name__, template_folder='../templates') diff --git a/App/views/staff.py b/App/views/staff.py new file mode 100644 index 000000000..f87a357d8 --- /dev/null +++ b/App/views/staff.py @@ -0,0 +1,26 @@ +from flask import Blueprint, render_template, jsonify, request, send_from_directory, flash, redirect, url_for +from flask_jwt_extended import jwt_required, current_user as jwt_current_user +from flask_login import current_user, login_required + +from.index import index_views + +from App.controllers import ( + create_user, + jwt_authenticate, + get_all_users, + get_all_users_json, + jwt_required, + addSemesterCourses +) + +staff_views = Blueprint('staff_views', __name__, template_folder='../templates') + +@staff_views.route('/staff/addNextSemesterCourse/', methods=['POST']) +def addCourse(courseCode): + course = addSemesterCourses(courseCode) + return jsonify({'message': f"Course {course['courseName']} added"}) if course else 200 + + + + + diff --git a/wsgi.py b/wsgi.py index 703c3088e..1e193b2f1 100644 --- a/wsgi.py +++ b/wsgi.py @@ -16,6 +16,7 @@ get_prerequisites, get_all_courses, getRemainingCourses, + addSemesterCourses ) @@ -164,6 +165,11 @@ def get_course(code): course = get_course_by_courseCode(code) print(f'Course Name: {course.courseName}') if course else print(f'error') +@course.command('nextsem', help='Add a course to offered courses') +@click.argument('code', type=str) +def add_course(code): + course = addSemesterCourses(code) + print(f'Course Name: {course.courseName}') if course else print(f'error') app.cli.add_command(course) From 44124422f0660694965af2308d773e3140471b16 Mon Sep 17 00:00:00 2001 From: Ashley Jacob Date: Wed, 4 Oct 2023 05:27:17 -0400 Subject: [PATCH 32/90] Updated admin - remove all courses --- App/controllers/admin.py | 22 +++++++++------------- App/models/coursePlan.py | 3 +-- App/models/student.py | 2 +- 3 files changed, 11 insertions(+), 16 deletions(-) diff --git a/App/controllers/admin.py b/App/controllers/admin.py index cf847fdae..374022566 100644 --- a/App/controllers/admin.py +++ b/App/controllers/admin.py @@ -3,10 +3,12 @@ from App.models import Staff from App.models import Admin from App.database import db -from App.controllers import create_user +from App.models import OfferedCourses +from App.controllers import create_user, removeAllCourses from App.controllers.staff import create_staff + def createAdmin(id, username, password, name): newadmin = Admin(id, username, password, name) try: @@ -19,23 +21,17 @@ def createAdmin(id, username, password, name): return newadmin -# def addStudent(id,username,password): #creates new student -# newstudent=Student(id=id,username=username,password=password) -# try: -# db.session.add(newstudent) -# db.session.commit() -# except Exception as e: #student already exists -# db.session.rollback() -# print(f'Username or ID already taken') -# print(f'Student created.') -# return newstudent - - def addStaff(id,username,password,name): #creates new staff member newstaff = create_staff(password, id, name) return newstaff +def removeCourseListing(): + semcourses=OfferedCourses.query.first() + removeAllCourses(semcourses) + print(f'Course listing removed') + + def removeAccount(id): #removes account by id acc=User.query.filter_by(id=id).first() if not acc: diff --git a/App/models/coursePlan.py b/App/models/coursePlan.py index 7d67350b1..9df1ca425 100644 --- a/App/models/coursePlan.py +++ b/App/models/coursePlan.py @@ -4,9 +4,8 @@ class CoursePlan(db.Model,UserMixin): planId=db.Column(db.Integer, primary_key=True) - #studentId=db.Column(db.Integer, db.foreignkey('student.id'), nullable=False) + studentId=db.Column(db.Integer, db.ForeignKey('student.id'), nullable=False) courses=db.Column(db.String(200), nullable=True) - #=db.relationship('Student', db.backref('CoursePlan')) def __init__(self, studentId, courses=None): self.studentId = studentId diff --git a/App/models/student.py b/App/models/student.py index b80cc4881..fe2342d3f 100644 --- a/App/models/student.py +++ b/App/models/student.py @@ -6,7 +6,7 @@ class Student(User): id = db.Column( db.ForeignKey('user.id'), primary_key=True) name = db.Column(db.String(50)) course_history = db.Column(db.String(500)) - #CoursePlan -> nextSemCourses + plan_id = db.Column( db.ForeignKey('courseplan.planId')) nextSemCourses = db.Column(db.String(50)) program = db.Column(db.String(50)) From 999e985d5c4120511597990df93fba349ab9d410 Mon Sep 17 00:00:00 2001 From: Ashley Jacob Date: Wed, 4 Oct 2023 06:53:05 -0400 Subject: [PATCH 33/90] adjusted code to be compatable with other classes --- App/controllers/admin.py | 4 ++-- App/controllers/coursePlan.py | 22 ++++++++++++++++++++++ App/controllers/student.py | 1 + App/models/admin.py | 2 +- App/models/coursePlan.py | 10 +++++----- App/models/student.py | 3 +-- 6 files changed, 32 insertions(+), 10 deletions(-) diff --git a/App/controllers/admin.py b/App/controllers/admin.py index 374022566..67309f76d 100644 --- a/App/controllers/admin.py +++ b/App/controllers/admin.py @@ -4,9 +4,9 @@ from App.models import Admin from App.database import db from App.models import OfferedCourses -from App.controllers import create_user, removeAllCourses +# from App.controllers import removeAllCourses from App.controllers.staff import create_staff - +import json def createAdmin(id, username, password, name): diff --git a/App/controllers/coursePlan.py b/App/controllers/coursePlan.py index 0ef4e21d2..513ff3bee 100644 --- a/App/controllers/coursePlan.py +++ b/App/controllers/coursePlan.py @@ -7,6 +7,25 @@ from App.models import OfferedCourses +def createCoursePlan(id): + blankPlan=CoursePlan(id) + db.session.add(blankPlan) + db.session.commit() + return blankPlan + + +def getCoursePlan(id): + plan=CoursePlan.query.filter_by(studentId=id).first() + return plan.courses + + +def updateCoursePlan(studentId, courses): + plan=CoursePlan.query.filter_by(studentId=studentId).first() + for c in courses: + plan.courses.append(c) + db.session.commit() + + def getProgramme(Student): return Program.query.filter_by(programmeId=Student.programme_id).first() @@ -127,6 +146,7 @@ def prioritizeElectives(Student): #merge available, required core and foundation courses courses=courses + findAvailable(getRemainingCore(Student)) + findAvailable(getRemainingFoun(Student)) courses=checkPrereq(Student,courses) + updateCoursePlan(Student.id,courses) return courses @@ -147,6 +167,7 @@ def easyCourses(Student): courses= courses + findAvailable(getRemainingCore(Student)) + findAvailable(getRemainingFoun(Student)) courses.sort(key=lambda x:getattr(x, "rating", 0)) courses=checkPrereq(Student,courses) + updateCoursePlan(Student.id,courses) return courses @@ -166,4 +187,5 @@ def fastestGraduation(Student): #get available, required core and foundation courses courses= courses + findAvailable(getRemainingCore(Student)) + findAvailable(getRemainingFoun(Student)) courses=checkPrereq(Student,courses) + updateCoursePlan(Student.id,courses) return courses \ No newline at end of file diff --git a/App/controllers/student.py b/App/controllers/student.py index 2d4e9d482..641b2c34e 100644 --- a/App/controllers/student.py +++ b/App/controllers/student.py @@ -1,6 +1,7 @@ from App.models import Student, CoursePlan, Program from App.database import db + def create_student(file_path): new_student = Student(file_path) db.session.add(new_student) diff --git a/App/models/admin.py b/App/models/admin.py index 6668c6538..35c0c7d87 100644 --- a/App/models/admin.py +++ b/App/models/admin.py @@ -7,7 +7,7 @@ class Admin(User): # user=db.relationship('User',backref=db.backref('Admin')) def __init__(self, username, password, name): - super().__init__(username=username,password=password) + super().__init__(username,password) self.name=name self.id=id diff --git a/App/models/coursePlan.py b/App/models/coursePlan.py index 3aa0740be..7c7e3fdf2 100644 --- a/App/models/coursePlan.py +++ b/App/models/coursePlan.py @@ -4,13 +4,13 @@ class CoursePlan(db.Model,UserMixin): planId=db.Column(db.Integer, primary_key=True) - studentId=db.Column(db.Integer, db.ForeignKey('student.id'), nullable=False) - #courses=db.Column(db.ARRAY(db.String), nullable=True) - #student=db.relationship('Student', db.backref('CoursePlan')) + studentId=db.Column(db.Integer, db.ForeignKey('student.id'), nullable=False) + courses=db.Column(db.String(200), nullable=True) - def __init__(self, studentId, courses=None): + + def __init__(self, studentId): self.studentId = studentId - self.courses=json.dumps(courses) + self.courses="" def get_json(self): return{ diff --git a/App/models/student.py b/App/models/student.py index fe2342d3f..76d318fa0 100644 --- a/App/models/student.py +++ b/App/models/student.py @@ -6,10 +6,9 @@ class Student(User): id = db.Column( db.ForeignKey('user.id'), primary_key=True) name = db.Column(db.String(50)) course_history = db.Column(db.String(500)) - plan_id = db.Column( db.ForeignKey('courseplan.planId')) nextSemCourses = db.Column(db.String(50)) program = db.Column(db.String(50)) - + plan=db.relationship('CoursePlan',backref='student',lazy=True) def __init__(self, file_path): with open(file_path, 'r') as file: From 004494a6f4b9696eef217aa6faa72857e173aec5 Mon Sep 17 00:00:00 2001 From: Ashley Jacob Date: Wed, 4 Oct 2023 09:05:04 -0400 Subject: [PATCH 34/90] updated relationship between student & course plan --- App/models/student.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/App/models/student.py b/App/models/student.py index 76d318fa0..c08dbda71 100644 --- a/App/models/student.py +++ b/App/models/student.py @@ -1,6 +1,8 @@ from App.models import User from App.database import db import json +from App.models.coursePlan import CoursePlan + class Student(User): id = db.Column( db.ForeignKey('user.id'), primary_key=True) @@ -20,6 +22,7 @@ def __init__(self, file_path): self.name = lines[2].strip() self.program = lines[3].strip() self.course_history = json.dumps(lines[4].strip().split(',')) + self.plan=CoursePlan(id) def str_course_history(self): return json.loads(self.course_history) if self.course_history else [] From a1cbd57cf8b96ff0fd984b6037741605b41e7945 Mon Sep 17 00:00:00 2001 From: Ashley Jacob Date: Wed, 4 Oct 2023 09:15:00 -0400 Subject: [PATCH 35/90] updated student controller to work w/ courseplan --- App/controllers/student.py | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/App/controllers/student.py b/App/controllers/student.py index 641b2c34e..9ee3d542b 100644 --- a/App/controllers/student.py +++ b/App/controllers/student.py @@ -1,4 +1,5 @@ from App.models import Student, CoursePlan, Program +from App.controllers.coursePlan import addCourse, getCoursePlan, removeCourse from App.database import db @@ -40,25 +41,17 @@ def get_nextSemCourses(username): # db.session.add(student) # Add the student object to the session # db.session.commit() -# def add_course_to_plan(student, course_id): -# #Ashely needed here -# course = CoursePlan.query.get(course_id) -# if course: -# student.courses.append(course) -# db.session.add(student) -# db.session.commit() +def add_course_to_plan(student, course_id): + addCourse(student,course_id) + return -# def remove_course_from_plan(student, course_id): -# #Ashely needed here -# course = CoursePlan.query.get(course_id) -# if course: -# student.courses.remove(course) -# db.session.add(student) # Add the student object to the session -# db.session.commit() +def remove_course_from_plan(student, course_id): + removeCourse(student,course_id) + return -# def view_course_plan(student): -# #Ashely needed here -# return [course.get_json() for course in student.courses] +def view_course_plan(student): + plan=getCoursePlan(student.id) + return plan # def add_courses_from_file(student, file_path): # try: From 3c6e8eda5282840c2f2566186b22d5fce31f589d Mon Sep 17 00:00:00 2001 From: Ashley Jacob Date: Wed, 4 Oct 2023 10:31:32 -0400 Subject: [PATCH 36/90] updated course plan - merge lvl 1&2 cores --- App/controllers/coursePlan.py | 2 +- App/controllers/courses.py | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/App/controllers/coursePlan.py b/App/controllers/coursePlan.py index 513ff3bee..e8caa01f8 100644 --- a/App/controllers/coursePlan.py +++ b/App/controllers/coursePlan.py @@ -74,7 +74,7 @@ def getRemainingCourses(completed, required): def getRemainingCore(Student): programme=getProgramme(Student) - reqCore=programme.get_core_courses(programme.name) + reqCore=programme.get_level1_courses(programme.name) + programme.get_core_courses(programme.name) remaining=getRemainingCourses(Student.courseHistory,reqCore) return remaining diff --git a/App/controllers/courses.py b/App/controllers/courses.py index 9928a7410..0779fdccd 100644 --- a/App/controllers/courses.py +++ b/App/controllers/courses.py @@ -19,11 +19,9 @@ def create_course(file_path): except FileNotFoundError: print("File not found.") - return False except Exception as e: print(f"An error occurred: {e}") - return False def get_course_by_courseCode(code): return Course.query.filter_by(courseCode=code).first() From 56a30174d27b74651fc8d2720b6f591f86e8da6d Mon Sep 17 00:00:00 2001 From: Kyle-McIntosh <78955773+Kyle-McIntosh@users.noreply.github.com> Date: Wed, 4 Oct 2023 14:43:56 +0000 Subject: [PATCH 37/90] Updated requirements, wsgi, coursePlan controller and model, student controller and model, and program model --- App/controllers/coursePlan.py | 65 ++++++++++++++++++++++++++--------- App/controllers/student.py | 20 ++++++----- App/models/coursePlan.py | 6 ++-- App/models/program.py | 2 ++ App/models/student.py | 20 ++++++++--- requirements.txt | 3 +- wsgi.py | 28 +++++++++++++-- 7 files changed, 108 insertions(+), 36 deletions(-) diff --git a/App/controllers/coursePlan.py b/App/controllers/coursePlan.py index e950edf99..d59239e2d 100644 --- a/App/controllers/coursePlan.py +++ b/App/controllers/coursePlan.py @@ -1,10 +1,28 @@ from App.database import db -#from App.models import Student +from App.models import Student from App.models import CoursePlan from App.models import Program from App.models import Course from App.models import OfferedCourses + + +def create_easy_plan(studentId): + # Get the student object based on studentId + student = Student.query.get(studentId) + # Generate a list of courses using the easyCourses function + courses = easyCourses(student) + + # Create a new CoursePlan for the student with the generated courses + new_course_plan = CoursePlan(studentId=studentId, courses=courses) + + # Add the new course plan to the database and commit the changes + db.session.add(new_course_plan) + db.session.commit() + + return new_course_plan + + def addCourse(Student, courseCode): plan=CoursePlan.query.filter_by(studentId=Student.id).first() plan.courses.append(courseCode) @@ -19,41 +37,54 @@ def removeCourse(Student, courseCode): print(f'Course not found') def getProgramme(Student): - return Program.query.filter_by(programmeId=Student.programme_id).first() + return Program.query.filter_by(id=Student.program_id).first() def getRemainingCourses(completed, required): - remaining=required.copy() + # Check if either 'completed' or 'required' is None + if completed is None or required is None: + return [] # Return an empty list or handle it in a way that makes sense for your application + + remaining = required.copy() for course in required: if course in completed: remaining.remove(course) return remaining + def getRemainingCore(Student): programme=getProgramme(Student) reqCore=Program.get_core_courses() - remaining=getRemainingCourses(Student.courseHistory,reqCore) + remaining=getRemainingCourses(Student.course_history,reqCore) return remaining def getRemainingFoun(Student): programme=getProgramme(Student) reqFoun=Program.get_foun_courses() - remaining=getRemainingCourses(Student.courseHistory,reqFoun) + remaining=getRemainingCourses(Student.course_history,reqFoun) return remaining - def getRemainingElec(Student): - programme=getProgramme(Student) - reqElec=Program.get_elective_courses() - remaining=getRemainingCourses(Student.courseHistory,reqElec) - return remaining + program = getProgramme(Student) # Get the student's program + if program: + reqElec = program.str_elective_courses() # Use the instance method to get elective courses + if reqElec: + remaining = getRemainingCourses(Student.course_history, reqElec) + return remaining + return [] def remElecCredits(Student): - programme=getProgramme(Student) - requiredCreds=Program.get_elective_credits - for course in programme.elective_courses: - if course in Student.courseHistory: - c=Course.query.filter_by(courseCode=course).first() #get course - requiredCreds=requiredCreds-c.credits #subtract credits - return requiredCreds + program = getProgramme(Student) # Get the student's program + if program: + requiredCreds = program.elective_credits # Access the elective_credits attribute + elective_courses = program.str_elective_courses() # Use the instance method to get elective courses + if elective_courses: + for course in elective_courses: + if course in Student.course_history: + c = Course.query.filter_by(courseCode=course).first() # Get course + if c: + requiredCreds = requiredCreds - c.credits # Subtract credits + return requiredCreds + return 0 + def findAvailable(courseList): listing= get_all_courses() #FIX - courses offered (posted by staff) diff --git a/App/controllers/student.py b/App/controllers/student.py index 1235fd89a..ac0abbde3 100644 --- a/App/controllers/student.py +++ b/App/controllers/student.py @@ -1,8 +1,9 @@ from App.models import Student, CoursePlan, Program from App.database import db -def create_student(username, password, student_id, name): - new_student = Student(username=username, password=password, id=student_id, name=name) +def create_student(username, password, name): + new_student = Student(username=username, password=password) + new_student.name = name db.session.add(new_student) db.session.commit() return new_student @@ -31,12 +32,15 @@ def update_student(id, username): db.session.commit() return student -def enroll_in_programme(student, programme_id): - programme = Program.query.get(programme_id) - if programme: - student.programmes.append(programme) - db.session.add(student) # Add the student object to the session - db.session.commit() +def enroll_in_programme(student_id, programme_id): + student = get_student(student_id) + if student: + programme = Program.query.get(programme_id) + if programme: + student.program_id = programme_id + db.session.add(student) # Add the student object to the session + db.session.commit() + def add_course_to_plan(student, course_id): course = CoursePlan.query.get(course_id) diff --git a/App/models/coursePlan.py b/App/models/coursePlan.py index 4e7ad7dc9..776c2afb1 100644 --- a/App/models/coursePlan.py +++ b/App/models/coursePlan.py @@ -4,9 +4,11 @@ class CoursePlan(db.Model,UserMixin): planId=db.Column(db.Integer, primary_key=True) - #studentId=db.Column(db.Integer, db.foreignkey('student.id'), nullable=False) + studentId=db.Column(db.String(10), db.ForeignKey('student.id'), nullable=False) courses = db.Column((db.String(200)), nullable=True) - #student=db.relationship('Student', db.backref('CoursePlan')) + student = db.relationship('Student', backref=db.backref('course_plans', uselist=True)) + + def __init__(self, studentId, courses=None): self.studentId = studentId diff --git a/App/models/program.py b/App/models/program.py index 9f20adcaa..8c80ec841 100644 --- a/App/models/program.py +++ b/App/models/program.py @@ -11,6 +11,8 @@ class Program(db.Model): elective_courses = db.Column(db.String(200)) foun_credits = db.Column(db.Integer) foun_courses = db.Column(db.String(30)) + students = db.relationship('Student', backref='program', lazy=True) + def __init__(self, file_path): try: diff --git a/App/models/student.py b/App/models/student.py index ecac1bbe6..60344cfe7 100644 --- a/App/models/student.py +++ b/App/models/student.py @@ -7,7 +7,9 @@ class Student(User): name = db.Column(db.String(50)) course_history = db.Column(db.String(500)) nextSemCourses = db.Column(db.String(50)) - program = db.Column(db.String(50)) + program_id = db.Column(db.String(10), db.ForeignKey('program.id')) + associated_program = db.relationship('Program', back_populates='students', overlaps="program") + # def __init__(self, file_path): # try: @@ -29,13 +31,21 @@ class Student(User): # except Exception as e: # print(f"An error occurred: {e}") -def __init__(self, username, password, student_id, name, file_path): +def __init__(self, username, password, name, course_history=None, next_sem_courses=None, program_id=None): + # Call the parent class's __init__ method super().__init__(username, password) - self.id = student_id + + # Initialize the additional fields self.name = name + self.course_history = course_history + self.nextSemCourses = next_sem_courses + self.program_id = program_id + #program_id = db.Column(db.String(10), db.ForeignKey('program.id')) + #program = db.relationship('Program', back_populates='students') + - with open(file_path, 'r') as file: - lines = file.readlines() + #with open(file_path, 'r') as file: + # lines = file.readlines() # course History, courses, programmes using a file, diff --git a/requirements.txt b/requirements.txt index a6ad05eeb..ae8e09c0f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -13,4 +13,5 @@ psycopg2-binary==2.9.3 pytest==7.0.1 python-dotenv==0.21.1 Flask-JWT-Extended==4.4.4 -Flask-Migrate==3.1.0 \ No newline at end of file +Flask-Migrate==3.1.0 +Werkzeug==2.2.2 \ No newline at end of file diff --git a/wsgi.py b/wsgi.py index 42f0f150c..962a806ea 100644 --- a/wsgi.py +++ b/wsgi.py @@ -16,6 +16,10 @@ get_prerequisites, get_all_courses, getRemainingCourses, + create_student, + create_easy_plan, + enroll_in_programme, + get_student, ) @@ -76,12 +80,22 @@ def list_user_command(format): @student_cli.command("create", help="Creates a student") @click.argument("username") @click.argument("password") -@click.argument("student_id") + @click.argument("name") -def create_student_command(username, password, student_id, name): - create_student(username, password, student_id, name) +def create_student_command(username, password, name): + create_student(username, password, name) print(f"Student {username} created.") + +@student_cli.command("enroll", help="Enroll student in programme") +@click.argument("student_id") +@click.argument("programme_id") +def enroll_student(student_id, programme_id): + enroll_in_programme(student_id, programme_id) + print(f"Student, added a programme.") + + + app.cli.add_command(student_cli) ''' @@ -184,4 +198,12 @@ def remaining(programname): print(f'Remaining courses are: {newRemaining}') +# Define the course plan create command +@coursePlan.command("create_easy", help="Creates a course plan") +@click.argument("student_id") + +def create_plan(student_id): + create_easy_plan(student_id) + print(f"Course plan created for {student_id}.") + app.cli.add_command(coursePlan) \ No newline at end of file From 3730291204a28f064a7c97fcf5ae052469df4afe Mon Sep 17 00:00:00 2001 From: Jerrelle Johnson Date: Wed, 4 Oct 2023 13:17:40 -0400 Subject: [PATCH 38/90] added kyle's changes to code --- App/controllers/coursePlan.py | 58 ++++++++++++++++++++++++++--------- App/controllers/student.py | 18 ++++++----- App/models/coursePlan.py | 3 +- App/models/program.py | 1 + App/models/student.py | 41 ++++++------------------- 5 files changed, 65 insertions(+), 56 deletions(-) diff --git a/App/controllers/coursePlan.py b/App/controllers/coursePlan.py index 1494d6752..bb1658574 100644 --- a/App/controllers/coursePlan.py +++ b/App/controllers/coursePlan.py @@ -8,7 +8,7 @@ def getProgramme(Student): - return Program.query.filter_by(programmeId=Student.programme_id).first() + return Program.query.filter_by(id=Student.program_id).first() def getOfferedCourses(): @@ -42,6 +42,11 @@ def removeCourse(Student, courseCode): def getRemainingCourses(completed, required): remaining=required.copy() + + # Check if either 'completed' or 'required' is None + if completed is None or required is None: + return [] # Return an empty list or handle it in a way that makes sense for your application + for course in required: if course in completed: remaining.remove(course) @@ -51,32 +56,40 @@ def getRemainingCourses(completed, required): def getRemainingCore(Student): programme=getProgramme(Student) reqCore=programme.get_core_courses(programme.name) - remaining=getRemainingCourses(Student.courseHistory,reqCore) + remaining=getRemainingCourses(Student.course_history,reqCore) return remaining def getRemainingFoun(Student): programme=getProgramme(Student) reqFoun=programme.get_foun_courses(programme.name) - remaining=getRemainingCourses(Student.courseHistory,reqFoun) + remaining=getRemainingCourses(Student.course_history,reqFoun) return remaining def getRemainingElec(Student): - programme=getProgramme(Student) - reqElec=programme.get_elective_courses(programme.name) - remaining=getRemainingCourses(Student.courseHistory,reqElec) - return remaining + program = getProgramme(Student) # Get the student's program + if program: + reqElec = program.str_elective_courses() # Use the instance method to get elective courses + if reqElec: + remaining = getRemainingCourses(Student.course_history, reqElec) + return remaining + return [] def remElecCredits(Student): - programme=getProgramme(Student) - requiredCreds=programme.get_elective_credits(programme.name) - for course in programme.get_elective_courses(programme.name): - if course in Student.courseHistory: - c=Course.query.filter_by(courseCode=course).first() #get course - requiredCreds=requiredCreds-c.get_credits(course) #subtract credits - return requiredCreds + program = getProgramme(Student) # Get the student's program + if program: + requiredCreds = program.elective_credits # Access the elective_credits attribute + elective_courses = program.str_elective_courses() # Use the instance method to get elective courses + if elective_courses: + for course in elective_courses: + if course in Student.course_history: + c = Course.query.filter_by(courseCode=course).first() # Get course + if c: + requiredCreds = requiredCreds - c.credits # Subtract credits + return requiredCreds + return 0 def findAvailable(courseList): @@ -161,4 +174,19 @@ def fastestGraduation(Student): #get available, required core and foundation courses courses= courses + findAvailable(getRemainingCore(Student)) + findAvailable(getRemainingFoun(Student)) courses=checkPrereq(Student,courses) - return courses \ No newline at end of file + return courses + +def create_easy_plan(studentId): + # Get the student object based on studentId + student = Student.query.get(studentId) + # Generate a list of courses using the easyCourses function + courses = easyCourses(student) + + # Create a new CoursePlan for the student with the generated courses + new_course_plan = CoursePlan(studentId=studentId, courses=courses) + + # Add the new course plan to the database and commit the changes + db.session.add(new_course_plan) + db.session.commit() + + return new_course_plan \ No newline at end of file diff --git a/App/controllers/student.py b/App/controllers/student.py index 1235fd89a..45935db7d 100644 --- a/App/controllers/student.py +++ b/App/controllers/student.py @@ -1,8 +1,8 @@ from App.models import Student, CoursePlan, Program from App.database import db -def create_student(username, password, student_id, name): - new_student = Student(username=username, password=password, id=student_id, name=name) +def create_student(student_id, password, name): + new_student = Student(username=student_id, password=password, name=name) db.session.add(new_student) db.session.commit() return new_student @@ -31,12 +31,14 @@ def update_student(id, username): db.session.commit() return student -def enroll_in_programme(student, programme_id): - programme = Program.query.get(programme_id) - if programme: - student.programmes.append(programme) - db.session.add(student) # Add the student object to the session - db.session.commit() +def enroll_in_programme(student_id, programme_id): + student = get_student(student_id) + if student: + programme = Program.query.get(programme_id) + if programme: + student.program_id = programme_id + db.session.add(student) + db.session.commit() def add_course_to_plan(student, course_id): course = CoursePlan.query.get(course_id) diff --git a/App/models/coursePlan.py b/App/models/coursePlan.py index 3aa0740be..5dc149d0c 100644 --- a/App/models/coursePlan.py +++ b/App/models/coursePlan.py @@ -5,8 +5,9 @@ class CoursePlan(db.Model,UserMixin): planId=db.Column(db.Integer, primary_key=True) studentId=db.Column(db.Integer, db.ForeignKey('student.id'), nullable=False) - #courses=db.Column(db.ARRAY(db.String), nullable=True) + courses=db.Column(db.String(100), nullable=True) #student=db.relationship('Student', db.backref('CoursePlan')) + student = db.relationship('Student', backref=db.backref('course_plans', uselist=True)) def __init__(self, studentId, courses=None): self.studentId = studentId diff --git a/App/models/program.py b/App/models/program.py index 9f20adcaa..ff8e536ff 100644 --- a/App/models/program.py +++ b/App/models/program.py @@ -11,6 +11,7 @@ class Program(db.Model): elective_courses = db.Column(db.String(200)) foun_credits = db.Column(db.Integer) foun_courses = db.Column(db.String(30)) + students = db.relationship('Student', backref='program', lazy=True) def __init__(self, file_path): try: diff --git a/App/models/student.py b/App/models/student.py index ecac1bbe6..90edaac25 100644 --- a/App/models/student.py +++ b/App/models/student.py @@ -1,4 +1,4 @@ -from .user import User # Import the User class from user.py +from App.models import User from App.database import db import json @@ -7,42 +7,19 @@ class Student(User): name = db.Column(db.String(50)) course_history = db.Column(db.String(500)) nextSemCourses = db.Column(db.String(50)) - program = db.Column(db.String(50)) + program_id = db.Column(db.String(10), db.ForeignKey('program.id')) + associated_program = db.relationship('Program', back_populates='students', overlaps="program") -# def __init__(self, file_path): -# try: -# with open(file_path, 'r') as file: -# lines = file.readlines() -# self.name = lines[0].strip() -# self.level1_credits = lines[1].strip() -# self.level1_courses = json.dumps(lines[2].strip().split(',')) -# self.core_credits = lines[3].strip() -# self.core_courses = json.dumps(lines[4].strip().split(',')) -# self.elective_credits = lines[5].strip() -# self.elective_courses = json.dumps(lines[6].strip().split(',')) -# self.foun_credits = lines[7].strip() -# self.foun_courses = json.dumps(lines[8].strip().split(',')) - -# except FileNotFoundError: -# print("File not found.") - -# except Exception as e: -# print(f"An error occurred: {e}") - -def __init__(self, username, password, student_id, name, file_path): + def __init__(self, username, password, name, course_history=None, next_sem_courses=None, program_id=None): super().__init__(username, password) - self.id = student_id self.name = name - - with open(file_path, 'r') as file: - lines = file.readlines() - + self.course_history = course_history + self.nextSemCourses = next_sem_courses + self.program_id = program_id - # course History, courses, programmes using a file, -# needed for nextSemCourses and Course history -# def get_prerequisites(self): -# return json.loads(self.prerequisites) if self.prerequisites else [] + def str_courseHistory(self): + return json.loads(self.course_history) if self.course_history else [] def get_json(self): return{ From a3a8fb55197de67d00795511f5716bc2d7b2ed6a Mon Sep 17 00:00:00 2001 From: JervalThomas Date: Wed, 4 Oct 2023 13:48:40 -0400 Subject: [PATCH 39/90] merge conflicts --- App/controllers/student.py | 88 +++++++++++++++----------------------- 1 file changed, 35 insertions(+), 53 deletions(-) diff --git a/App/controllers/student.py b/App/controllers/student.py index 853065b0b..45935db7d 100644 --- a/App/controllers/student.py +++ b/App/controllers/student.py @@ -1,13 +1,8 @@ from App.models import Student, CoursePlan, Program from App.database import db -<<<<<<< HEAD -def create_student(file_path): - new_student = Student(file_path) -======= def create_student(student_id, password, name): new_student = Student(username=student_id, password=password, name=name) ->>>>>>> development db.session.add(new_student) db.session.commit() return new_student @@ -15,6 +10,9 @@ def create_student(student_id, password, name): def get_student_by_username(username): return Student.query.filter_by(username=username).first() +def get_student(id): + return Student.query.get(id) + def get_all_students(): return Student.query.all() @@ -25,15 +23,14 @@ def get_all_students_json(): students_json = [student.get_json() for student in students] return students_json -def get_course_history(username): - student = get_student_by_username(username) - return student.course_history if student else [] +def update_student(id, username): + student = get_student(id) + if student: + student.username = username + db.session.add(student) + db.session.commit() + return student -<<<<<<< HEAD -def get_program(username): - student = get_student_by_username(username) - return student.program if student else "" -======= def enroll_in_programme(student_id, programme_id): student = get_student(student_id) if student: @@ -42,47 +39,32 @@ def enroll_in_programme(student_id, programme_id): student.program_id = programme_id db.session.add(student) db.session.commit() ->>>>>>> development - -def get_nextSemCourses(username): - student = get_student_by_username(username) - return student.nextSemCourses if student else [] - -# def enroll_in_programme(student, programme_id): -# programme = Program.query.get(programme_id) -# if programme: -# student.programmes.append(programme) -# db.session.add(student) # Add the student object to the session -# db.session.commit() -# def add_course_to_plan(student, course_id): -# #Ashely needed here -# course = CoursePlan.query.get(course_id) -# if course: -# student.courses.append(course) -# db.session.add(student) -# db.session.commit() +def add_course_to_plan(student, course_id): + course = CoursePlan.query.get(course_id) + if course: + student.courses.append(course) + db.session.add(student) # Add the student object to the session + db.session.commit() -# def remove_course_from_plan(student, course_id): -# #Ashely needed here -# course = CoursePlan.query.get(course_id) -# if course: -# student.courses.remove(course) -# db.session.add(student) # Add the student object to the session -# db.session.commit() +def remove_course_from_plan(student, course_id): + course = CoursePlan.query.get(course_id) + if course: + student.courses.remove(course) + db.session.add(student) # Add the student object to the session + db.session.commit() -# def view_course_plan(student): -# #Ashely needed here -# return [course.get_json() for course in student.courses] +def view_course_plan(student): + return [course.get_json() for course in student.courses] -# def add_courses_from_file(student, file_path): -# try: -# with open(file_path, 'r') as file: -# course_ids = [line.strip() for line in file.readlines()] -# for course_id in course_ids: -# add_course_to_plan(student, course_id) -# db.session.commit() # Commit the changes after adding courses -# except FileNotFoundError: -# return "File not found." -# except Exception as e: -# return str(e) +def add_courses_from_file(student, file_path): + try: + with open(file_path, 'r') as file: + course_ids = [line.strip() for line in file.readlines()] + for course_id in course_ids: + add_course_to_plan(student, course_id) + db.session.commit() # Commit the changes after adding courses + except FileNotFoundError: + return "File not found." + except Exception as e: + return str(e) From 11ab32c350ce687ca46f7f4606bd5f4f3ac193a3 Mon Sep 17 00:00:00 2001 From: JervalThomas Date: Wed, 4 Oct 2023 13:49:10 -0400 Subject: [PATCH 40/90] merge conflicts --- App/controllers/staff.py | 100 ++++++++++++++++++--------------------- 1 file changed, 47 insertions(+), 53 deletions(-) diff --git a/App/controllers/staff.py b/App/controllers/staff.py index 22d4506b9..79b8d4788 100644 --- a/App/controllers/staff.py +++ b/App/controllers/staff.py @@ -1,56 +1,50 @@ -from App.models import Program, Course, Staff +from App.models import Program, Course from App.database import db -def create_staff(password, staff_id, name): - new_staff = Staff(password, staff_id, name) - db.session.add(new_staff) - db.session.commit() - return new_staff - -# def add_program(self, program_name, description): -# try: -# new_program = Program(name=program_name, description=description) -# db.session.add(new_program) -# db.session.commit() -# return new_program -# except Exception as e: -# db.session.rollback() -# print(f"An error occurred while adding the program: {e}") - - -# def remove_program(self, program_name): -# try: -# program = Program.query.filter_by(name=program_name).first() -# if program: -# db.session.delete(program) -# db.session.commit() -# else: -# print(f"Program '{program_name}' not found.") -# except Exception as e: -# db.session.rollback() -# print(f"An error occurred while removing the program: {e}") - - -# def add_course(self, course_code, course_name, credits): -# try: -# new_course = Course(code=course_code, name=course_name, credits=credits) -# db.session.add(new_course) -# db.session.commit() -# return new_course -# except Exception as e: -# db.session.rollback() -# print(f"An error occurred while adding the course: {e}") - - -# def remove_course(self, course_code): -# try: -# course = Course.query.filter_by(code=course_code).first() -# if course: -# db.session.delete(course) -# db.session.commit() -# else: -# print(f"Course '{course_code}' not found.") -# except Exception as e: -# db.session.rollback() -# print(f"An error occurred while removing the course: {e}") +def add_program(self, program_name, description): + try: + new_program = Program(name=program_name, description=description) + db.session.add(new_program) + db.session.commit() + return new_program + except Exception as e: + db.session.rollback() + print(f"An error occurred while adding the program: {e}") + + +def remove_program(self, program_name): + try: + program = Program.query.filter_by(name=program_name).first() + if program: + db.session.delete(program) + db.session.commit() + else: + print(f"Program '{program_name}' not found.") + except Exception as e: + db.session.rollback() + print(f"An error occurred while removing the program: {e}") + + +def add_course(self, course_code, course_name, credits): + try: + new_course = Course(code=course_code, name=course_name, credits=credits) + db.session.add(new_course) + db.session.commit() + return new_course + except Exception as e: + db.session.rollback() + print(f"An error occurred while adding the course: {e}") + + +def remove_course(self, course_code): + try: + course = Course.query.filter_by(code=course_code).first() + if course: + db.session.delete(course) + db.session.commit() + else: + print(f"Course '{course_code}' not found.") + except Exception as e: + db.session.rollback() + print(f"An error occurred while removing the course: {e}") From 7eb3da9cdc00342c41e996cfb2bf5b75b6d0cbac Mon Sep 17 00:00:00 2001 From: JervalThomas Date: Wed, 4 Oct 2023 13:53:26 -0400 Subject: [PATCH 41/90] merge conflicts --- App/models/student.py | 23 +---------------------- 1 file changed, 1 insertion(+), 22 deletions(-) diff --git a/App/models/student.py b/App/models/student.py index 62ba18cb2..90edaac25 100644 --- a/App/models/student.py +++ b/App/models/student.py @@ -3,46 +3,25 @@ import json class Student(User): - id = db.Column( db.ForeignKey('user.id'), primary_key=True) + id = db.Column(db.String(10), db.ForeignKey('user.id'), primary_key=True) name = db.Column(db.String(50)) course_history = db.Column(db.String(500)) - #CoursePlan -> nextSemCourses nextSemCourses = db.Column(db.String(50)) program_id = db.Column(db.String(10), db.ForeignKey('program.id')) associated_program = db.relationship('Program', back_populates='students', overlaps="program") -<<<<<<< HEAD - - def __init__(self, file_path): - with open(file_path, 'r') as file: - lines = file.readlines() - username = lines[0].strip() - password = lines[1].strip() - super.__init__(username, password) - self.id = lines[0].strip() - self.name = lines[2].strip() - self.program = lines[3].strip() - self.course_history = json.dumps(lines[4].strip().split(',')) -======= def __init__(self, username, password, name, course_history=None, next_sem_courses=None, program_id=None): super().__init__(username, password) self.name = name self.course_history = course_history self.nextSemCourses = next_sem_courses self.program_id = program_id ->>>>>>> development - def str_course_history(self): - return json.loads(self.course_history) if self.course_history else [] -<<<<<<< HEAD - def get_json(self): -======= def str_courseHistory(self): return json.loads(self.course_history) if self.course_history else [] def get_json(self): ->>>>>>> development return{ 'student_id': self.id, 'name': self.name, From 8de83a3780f75c51d8164364408740d3e56401a7 Mon Sep 17 00:00:00 2001 From: Ashley Jacob Date: Wed, 4 Oct 2023 16:23:25 -0400 Subject: [PATCH 42/90] merged updated files --- App/controllers/coursePlan.py | 10 ---------- App/controllers/student.py | 23 ----------------------- App/models/coursePlan.py | 5 ----- App/models/student.py | 21 --------------------- 4 files changed, 59 deletions(-) diff --git a/App/controllers/coursePlan.py b/App/controllers/coursePlan.py index a509d9ad6..78a2e456c 100644 --- a/App/controllers/coursePlan.py +++ b/App/controllers/coursePlan.py @@ -79,13 +79,8 @@ def getRemainingCourses(completed, required): def getRemainingCore(Student): programme=getProgramme(Student) -<<<<<<< HEAD - reqCore=programme.get_level1_courses(programme.name) + programme.get_core_courses(programme.name) - remaining=getRemainingCourses(Student.courseHistory,reqCore) -======= reqCore=programme.get_core_courses(programme.name) remaining=getRemainingCourses(Student.course_history,reqCore) ->>>>>>> fb66afb1efd67da59ad1be48f435f99ff99ed345 return remaining @@ -205,10 +200,6 @@ def fastestGraduation(Student): #get available, required core and foundation courses courses= courses + findAvailable(getRemainingCore(Student)) + findAvailable(getRemainingFoun(Student)) courses=checkPrereq(Student,courses) -<<<<<<< HEAD - updateCoursePlan(Student.id,courses) - return courses -======= return courses def create_easy_plan(studentId): @@ -225,4 +216,3 @@ def create_easy_plan(studentId): db.session.commit() return new_course_plan ->>>>>>> fb66afb1efd67da59ad1be48f435f99ff99ed345 diff --git a/App/controllers/student.py b/App/controllers/student.py index 67c38949c..bfab571ec 100644 --- a/App/controllers/student.py +++ b/App/controllers/student.py @@ -2,14 +2,8 @@ from App.controllers.coursePlan import addCourse, getCoursePlan, removeCourse from App.database import db -<<<<<<< HEAD - -def create_student(file_path): - new_student = Student(file_path) -======= def create_student(student_id, password, name): new_student = Student(username=student_id, password=password, name=name) ->>>>>>> fb66afb1efd67da59ad1be48f435f99ff99ed345 db.session.add(new_student) db.session.commit() return new_student @@ -31,22 +25,6 @@ def get_course_history(username): student = get_student_by_username(username) return student.course_history if student else [] -<<<<<<< HEAD -def get_program(username): - student = get_student_by_username(username) - return student.program if student else "" - -def get_nextSemCourses(username): - student = get_student_by_username(username) - return student.nextSemCourses if student else [] - -# def enroll_in_programme(student, programme_id): -# programme = Program.query.get(programme_id) -# if programme: -# student.programmes.append(programme) -# db.session.add(student) # Add the student object to the session -# db.session.commit() -======= def enroll_in_programme(student_id, programme_id): student = get_student(student_id) if student: @@ -55,7 +33,6 @@ def enroll_in_programme(student_id, programme_id): student.program_id = programme_id db.session.add(student) db.session.commit() ->>>>>>> fb66afb1efd67da59ad1be48f435f99ff99ed345 def add_course_to_plan(student, course_id): addCourse(student,course_id) diff --git a/App/models/coursePlan.py b/App/models/coursePlan.py index cb201ac5e..6d8bee8ce 100644 --- a/App/models/coursePlan.py +++ b/App/models/coursePlan.py @@ -4,15 +4,10 @@ class CoursePlan(db.Model,UserMixin): planId=db.Column(db.Integer, primary_key=True) -<<<<<<< HEAD - studentId=db.Column(db.Integer, db.ForeignKey('student.id'), nullable=False) - courses=db.Column(db.String(200), nullable=True) -======= studentId=db.Column(db.Integer, db.ForeignKey('student.id'), nullable=False) courses=db.Column(db.String(100), nullable=True) #student=db.relationship('Student', db.backref('CoursePlan')) student = db.relationship('Student', backref=db.backref('course_plans', uselist=True)) ->>>>>>> fb66afb1efd67da59ad1be48f435f99ff99ed345 def __init__(self, studentId): diff --git a/App/models/student.py b/App/models/student.py index 28decf054..bf6855a1a 100644 --- a/App/models/student.py +++ b/App/models/student.py @@ -9,22 +9,6 @@ class Student(User): name = db.Column(db.String(50)) course_history = db.Column(db.String(500)) nextSemCourses = db.Column(db.String(50)) -<<<<<<< HEAD - program = db.Column(db.String(50)) - plan=db.relationship('CoursePlan',backref='student',lazy=True) - - def __init__(self, file_path): - with open(file_path, 'r') as file: - lines = file.readlines() - username = lines[0].strip() - password = lines[1].strip() - super.__init__(username, password) - self.id = lines[0].strip() - self.name = lines[2].strip() - self.program = lines[3].strip() - self.course_history = json.dumps(lines[4].strip().split(',')) - self.plan=CoursePlan(id) -======= program_id = db.Column(db.String(10), db.ForeignKey('program.id')) associated_program = db.relationship('Program', back_populates='students', overlaps="program") @@ -34,19 +18,14 @@ def __init__(self, username, password, name, course_history=None, next_sem_cours self.course_history = course_history self.nextSemCourses = next_sem_courses self.program_id = program_id ->>>>>>> fb66afb1efd67da59ad1be48f435f99ff99ed345 def str_course_history(self): return json.loads(self.course_history) if self.course_history else [] -<<<<<<< HEAD - def get_json(self): -======= def str_courseHistory(self): return json.loads(self.course_history) if self.course_history else [] def get_json(self): ->>>>>>> fb66afb1efd67da59ad1be48f435f99ff99ed345 return{ 'student_id': self.id, 'name': self.name, From cfbf387f3a53a63e084ce0ab65a78c8d6b452104 Mon Sep 17 00:00:00 2001 From: Kyle-McIntosh <78955773+Kyle-McIntosh@users.noreply.github.com> Date: Thu, 5 Oct 2023 03:06:47 +0000 Subject: [PATCH 43/90] Created prerequisite model --- App/controllers/__init__.py | 1 + App/controllers/prerequisites.py | 3 +++ App/models/__init__.py | 2 +- App/models/courses.py | 5 ++++- App/models/prerequisites.py | 24 ++++++++++++++++++++++++ 5 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 App/controllers/prerequisites.py create mode 100644 App/models/prerequisites.py diff --git a/App/controllers/__init__.py b/App/controllers/__init__.py index 75b9e83ee..455cad01c 100644 --- a/App/controllers/__init__.py +++ b/App/controllers/__init__.py @@ -7,3 +7,4 @@ from .courses import * from .coursePlan import * from .offeredCourses import * +from .prerequisites import * \ No newline at end of file diff --git a/App/controllers/prerequisites.py b/App/controllers/prerequisites.py new file mode 100644 index 000000000..20b53f0cd --- /dev/null +++ b/App/controllers/prerequisites.py @@ -0,0 +1,3 @@ +from App.models import prerequisites, Course +from App.database import db + diff --git a/App/models/__init__.py b/App/models/__init__.py index 8104b6ecd..723335e44 100644 --- a/App/models/__init__.py +++ b/App/models/__init__.py @@ -6,4 +6,4 @@ from .courses import * from .coursePlan import * from .offeredCourses import * - +from .prerequisites import* diff --git a/App/models/courses.py b/App/models/courses.py index b53c0399f..a670f95ec 100644 --- a/App/models/courses.py +++ b/App/models/courses.py @@ -1,4 +1,5 @@ from App.database import db +from App.models import prerequisites import json class Course(db.Model): @@ -6,7 +7,9 @@ class Course(db.Model): courseName = db.Column(db.String(25)) credits = db.Column(db.Integer) rating = db.Column(db.Integer) - prerequisites = db.Column(db.String(24)) + + #prerequisites_rel = db.relationship('Prerequisites', foreign_keys='Prerequisites.course_id', backref='prerequisite_rels') + #prerequisite_for = db.relationship('Prerequisites', foreign_keys='Prerequisites.prereq_code', back_populates='course', overlaps="prerequisites_rel") def __init__(self): pass diff --git a/App/models/prerequisites.py b/App/models/prerequisites.py new file mode 100644 index 000000000..88838cd9b --- /dev/null +++ b/App/models/prerequisites.py @@ -0,0 +1,24 @@ +from App.database import db + + +class Prerequisites(db.Model): + + id = db.Column(db.Integer, primary_key=True) + course_id = db.Column(db.String(8), db.ForeignKey('course.courseCode'), primary_key=True) + prereq_code = db.Column(db.String(8)) #Maybe also a foreignkey + + + course = db.relationship('Course', foreign_keys=[course_id], backref='prerequisite_rel') + #course = db.relationship('Course', back_populates='prerequisites_rel') + #prereq_course = db.relationship('Course', foreign_keys=[prereq_code], back_populates='prerequisites_for') + + def __init__(self, course_id, prereq_code): + self.course_id = course_id + self.prereq_code = prereq_code + + def get_json(self): + return{ + 'prereq_id': self.id, + 'course_id': self.course_id, + 'prerequisite_course': self.prereq_code, + } \ No newline at end of file From b8e3d2152046ec08a46d118cf64bdd40415d64f9 Mon Sep 17 00:00:00 2001 From: Jerrelle Johnson Date: Thu, 5 Oct 2023 12:59:54 -0400 Subject: [PATCH 44/90] added bridge tables prerequisites and programCourses --- App/Test.txt | 1 - App/controllers/__init__.py | 1 + App/controllers/courses.py | 38 +++++++++++++++++++--------- App/controllers/prerequistes.py | 7 +++++ App/models/__init__.py | 3 ++- App/models/courses.py | 7 ++--- App/models/prerequisites.py | 23 +++++++++++++++++ App/models/program.py | 45 +++++++++++++++------------------ App/models/programCourses.py | 24 ++++++++++++++++++ App/models/student.py | 2 +- App/views/staff.py | 1 + testData/courseData.csv | 5 ++++ testData/courseTest.txt | 7 ++++- wsgi.py | 41 ++++++++++++++++++++---------- 14 files changed, 148 insertions(+), 57 deletions(-) delete mode 100644 App/Test.txt create mode 100644 App/controllers/prerequistes.py create mode 100644 App/models/prerequisites.py create mode 100644 App/models/programCourses.py create mode 100644 testData/courseData.csv diff --git a/App/Test.txt b/App/Test.txt deleted file mode 100644 index cef0690dc..000000000 --- a/App/Test.txt +++ /dev/null @@ -1 +0,0 @@ -CodeCrafters diff --git a/App/controllers/__init__.py b/App/controllers/__init__.py index 75b9e83ee..2b37be3da 100644 --- a/App/controllers/__init__.py +++ b/App/controllers/__init__.py @@ -7,3 +7,4 @@ from .courses import * from .coursePlan import * from .offeredCourses import * +from .prerequistes import * diff --git a/App/controllers/courses.py b/App/controllers/courses.py index 9928a7410..1e31d7fc4 100644 --- a/App/controllers/courses.py +++ b/App/controllers/courses.py @@ -1,22 +1,33 @@ -from App.models import Course +from App.models import Course, Prerequisites +from App.controllers.prerequistes import create_prereq from App.database import db -import json +import json, csv def create_course(file_path): try: with open(file_path, 'r') as file: - lines = file.readlines() - for i in range(0, len(lines), 6): + csv_reader = csv.DictReader(file) + for row in csv_reader: course = Course() - course.courseCode = lines[i].strip() - course.courseName = lines[i + 1].strip() - course.credits = int(lines[i + 2].strip()) - course.rating = int(lines[i + 3].strip()) - course.prerequisites = json.dumps(lines[i + 4].strip().split(',')) + course.courseCode = row["courseCode"] + course.courseName = row["courseName"] + course.credits = int(row["numCredits"]) + course.rating = int(row["rating"]) + + prerequisites_codes = row["preReqs"].split(',') + + + if prerequisites_codes[0]: + prerequisites = [] + for prereq_code in prerequisites_codes: + prereq_course = Course.query.filter_by(courseCode=prereq_code).first() + + if prereq_course: + create_prereq(prereq_code, course.courseName) + else: + print(f"No prerequisites for course {course.courseCode}.") + db.session.add(course) - - db.session.commit() - except FileNotFoundError: print("File not found.") return False @@ -24,6 +35,9 @@ def create_course(file_path): except Exception as e: print(f"An error occurred: {e}") return False + + db.session.commit() + print("Courses added successfully.") def get_course_by_courseCode(code): return Course.query.filter_by(courseCode=code).first() diff --git a/App/controllers/prerequistes.py b/App/controllers/prerequistes.py new file mode 100644 index 000000000..df6c09946 --- /dev/null +++ b/App/controllers/prerequistes.py @@ -0,0 +1,7 @@ +from App.models import Prerequisites +from App.database import db + +def create_prereq(prereqCode, courseName): + prereq = Prerequisites(prereqCode, courseName) + db.session.add(prereq) + db.session.commit() \ No newline at end of file diff --git a/App/models/__init__.py b/App/models/__init__.py index 8104b6ecd..2437a3c14 100644 --- a/App/models/__init__.py +++ b/App/models/__init__.py @@ -6,4 +6,5 @@ from .courses import * from .coursePlan import * from .offeredCourses import * - +from .programCourses import * +from .prerequisites import* diff --git a/App/models/courses.py b/App/models/courses.py index b53c0399f..bde461e30 100644 --- a/App/models/courses.py +++ b/App/models/courses.py @@ -6,12 +6,13 @@ class Course(db.Model): courseName = db.Column(db.String(25)) credits = db.Column(db.Integer) rating = db.Column(db.Integer) - prerequisites = db.Column(db.String(24)) - + programs = db.relationship('ProgramCourses', backref='courses', lazy=True) + prerequisites = db.relationship('Prerequisites', backref='courses', lazy = True) + + def __init__(self): pass - def get_prerequisites(self): return json.loads(self.prerequisites) if self.prerequisites else [] diff --git a/App/models/prerequisites.py b/App/models/prerequisites.py new file mode 100644 index 000000000..a8329c643 --- /dev/null +++ b/App/models/prerequisites.py @@ -0,0 +1,23 @@ +from App.database import db + + +class Prerequisites(db.Model): + + id = db.Column(db.Integer, primary_key=True) + prereq_courseCode = db.Column(db.ForeignKey('course.courseCode')) + courseName = db.Column(db.String(25)) + + associated_course = db.relationship('Course', back_populates='prerequisites', overlaps="courses") + + + + def __init__(self, prereqCode, nameofCourse): + self.prereq_courseCode = prereqCode + self.courseName = nameofCourse + + def get_json(self): + return{ + 'prereq_id': self.id, + 'course_id': self.course_id, + 'prerequisite_course': self.prereq_code, + } \ No newline at end of file diff --git a/App/models/program.py b/App/models/program.py index ff8e536ff..bf6c574a7 100644 --- a/App/models/program.py +++ b/App/models/program.py @@ -4,36 +4,35 @@ class Program(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(50)) level1_credits = db.Column(db.Integer) - level1_courses = db.Column(db.String(200)) core_credits = db.Column(db.Integer) - core_courses = db.Column(db.String(200)) elective_credits = db.Column(db.Integer) - elective_courses = db.Column(db.String(200)) foun_credits = db.Column(db.Integer) - foun_courses = db.Column(db.String(30)) + + students = db.relationship('Student', backref='program', lazy=True) + courses = db.relationship('ProgramCourses', backref='program', lazy=True) def __init__(self, file_path): - try: - with open(file_path, 'r') as file: - lines = file.readlines() - self.name = lines[0].strip() - self.level1_credits = lines[1].strip() - self.level1_courses = json.dumps(lines[2].strip().split(',')) - self.core_credits = lines[3].strip() - self.core_courses = json.dumps(lines[4].strip().split(',')) - self.elective_credits = lines[5].strip() - self.elective_courses = json.dumps(lines[6].strip().split(',')) - self.foun_credits = lines[7].strip() - self.foun_courses = json.dumps(lines[8].strip().split(',')) + # try: + # with open(file_path, 'r') as file: + # lines = file.readlines() + # self.name = lines[0].strip() + # self.level1_credits = lines[1].strip() + # self.level1_courses = json.dumps(lines[2].strip().split(',')) + # self.core_credits = lines[3].strip() + # self.core_courses = json.dumps(lines[4].strip().split(',')) + # self.elective_credits = lines[5].strip() + # self.elective_courses = json.dumps(lines[6].strip().split(',')) + # self.foun_credits = lines[7].strip() + # self.foun_courses = json.dumps(lines[8].strip().split(',')) - except FileNotFoundError: - print("File not found.") + # except FileNotFoundError:l + # print("File not found.") - except Exception as e: - print(f"An error occurred: {e}") + # except Exception as e: + # print(f"An error occurred: {e}") - def str_level1_courses(self): + def str_level1_courses(self): return json.loads(self.level1_courses) if self.level1_courses else [] def str_core_courses(self): @@ -51,12 +50,8 @@ def get_json(self): 'Program ID:': self.id, 'Program Name: ': self.name, 'Level I Credits: ': self.level1_credits, - 'Level I Courses: ': self.level1_courses, 'Core Credits: ': self.core_credits, - 'Core Courses: ': self.core_courses, 'Elective Credits ': self.elective_credits, - 'Elective Courses: ': self.elective_courses, 'Foundation Credits: ': self.foun_credits, - 'Foundation Courses: ': self.foun_courses } \ No newline at end of file diff --git a/App/models/programCourses.py b/App/models/programCourses.py new file mode 100644 index 000000000..0a7bdfa63 --- /dev/null +++ b/App/models/programCourses.py @@ -0,0 +1,24 @@ +from App.database import db +import json + +class ProgramCourses(db.Model): + __tablename__ ='program_courses' + id = db.Column(db.Integer, primary_key=True) + program_id = db.Column(db.ForeignKey('program.id')) + code = db.Column(db.ForeignKey('course.courseCode')) + courseType = db.Column(db.Integer) + + associated_program = db.relationship('Program', back_populates='courses', overlaps="program") + associated_course = db.relationship('Course', back_populates='programs', overlaps="courses") + + def __init__(self, programID, courseCode, num): + self.program_id = programID + self.code = courseCode + self.courseType = num + + def get_json(self): + return{ + 'Program ID:': self.program_id, + 'Course Code: ': self.code, + 'Course Type: ': self.courseType + } \ No newline at end of file diff --git a/App/models/student.py b/App/models/student.py index 90edaac25..d96f20ca7 100644 --- a/App/models/student.py +++ b/App/models/student.py @@ -7,7 +7,7 @@ class Student(User): name = db.Column(db.String(50)) course_history = db.Column(db.String(500)) nextSemCourses = db.Column(db.String(50)) - program_id = db.Column(db.String(10), db.ForeignKey('program.id')) + program_id = db.Column(db.Integer, db.ForeignKey('program.id')) associated_program = db.relationship('Program', back_populates='students', overlaps="program") def __init__(self, username, password, name, course_history=None, next_sem_courses=None, program_id=None): diff --git a/App/views/staff.py b/App/views/staff.py index f87a357d8..2b834cc88 100644 --- a/App/views/staff.py +++ b/App/views/staff.py @@ -17,6 +17,7 @@ @staff_views.route('/staff/addNextSemesterCourse/', methods=['POST']) def addCourse(courseCode): + token =gettoken course = addSemesterCourses(courseCode) return jsonify({'message': f"Course {course['courseName']} added"}) if course else 200 diff --git a/testData/courseData.csv b/testData/courseData.csv new file mode 100644 index 000000000..4a8154dd2 --- /dev/null +++ b/testData/courseData.csv @@ -0,0 +1,5 @@ +courseCode,courseName,numCredits,rating,preReqs +COMP2611,Data Structures,3,5, +MATH2250,Industrial Statistics,3,4, +COMP3605,Data Analytics,3,3,"COMP2611,MATH2250" +COMP3610,Big Data Analytics,3,5,COMP3605 diff --git a/testData/courseTest.txt b/testData/courseTest.txt index 0f3115149..aef0a1b68 100644 --- a/testData/courseTest.txt +++ b/testData/courseTest.txt @@ -8,4 +8,9 @@ COMP3610 Big Data Analytics 3 3 -COMP3605 \ No newline at end of file +COMP3605 + +"COMP2611","Data Structures","3","5","" +"MATH2250","Industrial Statistics","3","4","" +"COMP3605","Data Analytics","3","3","COMP2611, MATH2250" +"COMP3610","Big Data Analytics","3","5","COMP3605" \ No newline at end of file diff --git a/wsgi.py b/wsgi.py index 1e193b2f1..a53ccb224 100644 --- a/wsgi.py +++ b/wsgi.py @@ -1,7 +1,9 @@ import click, pytest, sys +import csv from flask import Flask from flask.cli import with_appcontext, AppGroup + from App.database import db, get_migrate from App.main import create_app from App.controllers import ( @@ -16,7 +18,8 @@ get_prerequisites, get_all_courses, getRemainingCourses, - addSemesterCourses + addSemesterCourses, + create_student ) @@ -32,9 +35,15 @@ def initialize(): db.drop_all() db.create_all() create_user('bob', 'bobpass') - create_course('testData/courseTest.txt') + create_course('testData/courseData.csv') print('database intialized') + # with open('/Users/jerrellejohnson/Desktop/softEng2/flaskmvc/testData/courseData.csv', 'r') as csvfile: + # csv_reader = csv.reader(csvfile) + + # for row in csv_reader: + # print(row) # Display the row + ''' User Commands ''' @@ -75,13 +84,12 @@ def list_user_command(format): # Define the student create command @student_cli.command("create", help="Creates a student") -@click.argument("username") @click.argument("password") @click.argument("student_id") @click.argument("name") -def create_student_command(username, password, student_id, name): - #create_student(username, password, student_id, name) - print(f"Student {username} created.") +def create_student_command(student_id, password, name): + student = create_student(student_id, password, name) + print(f"Student {student.id} created.") app.cli.add_command(student_cli) @@ -165,6 +173,12 @@ def get_course(code): course = get_course_by_courseCode(code) print(f'Course Name: {course.courseName}') if course else print(f'error') +@course.command('getprereqs', help='Get all prerequistes for a course') +@click.argument('code', type=str) +def get_course(code): + course = get_course_by_courseCode(code) + print(f'Course Prerequisites: {course.prerequisites}') if course else print(f'error') + @course.command('nextsem', help='Add a course to offered courses') @click.argument('code', type=str) def add_course(code): @@ -181,13 +195,14 @@ def add_course(code): coursePlan = AppGroup('plan', help = 'Course Plan object commands') -@coursePlan.command('remaining', help='Get remaining program courses') -@click.argument('programname', type=str) -def remaining(programname): - required = get_all_courses(programname) - completed = ['COMP1600'] - newRemaining = getRemainingCourses(completed, required) - print(f'Remaining courses are: {newRemaining}') +# @coursePlan.command('remaining', help='Get remaining program courses') +# @click.argument('programname', type=str) +# def remaining(programname): + +# # required = get_all_courses(programname) +# # completed = ['COMP1600'] +# # newRemaining = getRemainingCourses(completed, required) +# # print(f'Remaining courses are: {newRemaining}') app.cli.add_command(coursePlan) \ No newline at end of file From e9e29f95aea46be90b1c8ca198ea2aab896877e3 Mon Sep 17 00:00:00 2001 From: Jerrelle Johnson Date: Thu, 5 Oct 2023 19:15:45 -0400 Subject: [PATCH 45/90] added alot of bridge tables --- App/controllers/__init__.py | 2 + App/controllers/courses.py | 11 ++-- App/controllers/prerequistes.py | 6 +- App/controllers/program.py | 17 +++--- App/controllers/programCourses.py | 21 +++++++ App/controllers/student.py | 22 ++++---- App/controllers/studentCourseHistory.py | 23 ++++++++ App/models/__init__.py | 4 +- App/models/courses.py | 2 + App/models/program.py | 38 ++----------- App/models/programCourses.py | 1 + App/models/student.py | 27 ++++----- App/models/studentCourseHistory.py | 21 +++++++ wsgi.py | 73 ++++++++++++++++++++----- 14 files changed, 174 insertions(+), 94 deletions(-) create mode 100644 App/controllers/programCourses.py create mode 100644 App/controllers/studentCourseHistory.py create mode 100644 App/models/studentCourseHistory.py diff --git a/App/controllers/__init__.py b/App/controllers/__init__.py index 2b37be3da..77afc6db4 100644 --- a/App/controllers/__init__.py +++ b/App/controllers/__init__.py @@ -8,3 +8,5 @@ from .coursePlan import * from .offeredCourses import * from .prerequistes import * +from .programCourses import * +from .studentCourseHistory import * \ No newline at end of file diff --git a/App/controllers/courses.py b/App/controllers/courses.py index 1e31d7fc4..e9b5ce03b 100644 --- a/App/controllers/courses.py +++ b/App/controllers/courses.py @@ -1,5 +1,5 @@ from App.models import Course, Prerequisites -from App.controllers.prerequistes import create_prereq +from App.controllers.prerequistes import (create_prereq, get_all_prerequisites) from App.database import db import json, csv @@ -13,10 +13,8 @@ def create_course(file_path): course.courseName = row["courseName"] course.credits = int(row["numCredits"]) course.rating = int(row["rating"]) - prerequisites_codes = row["preReqs"].split(',') - if prerequisites_codes[0]: prerequisites = [] for prereq_code in prerequisites_codes: @@ -24,10 +22,8 @@ def create_course(file_path): if prereq_course: create_prereq(prereq_code, course.courseName) - else: - print(f"No prerequisites for course {course.courseCode}.") - db.session.add(course) + except FileNotFoundError: print("File not found.") return False @@ -44,7 +40,8 @@ def get_course_by_courseCode(code): def get_prerequisites(code): course = get_course_by_courseCode(code) - return course.prerequisites if course else None + prereqs = get_all_prerequisites(course.courseName) + return prereqs def get_credits(code): course = get_course_by_courseCode(code) diff --git a/App/controllers/prerequistes.py b/App/controllers/prerequistes.py index df6c09946..f1f305a1a 100644 --- a/App/controllers/prerequistes.py +++ b/App/controllers/prerequistes.py @@ -4,4 +4,8 @@ def create_prereq(prereqCode, courseName): prereq = Prerequisites(prereqCode, courseName) db.session.add(prereq) - db.session.commit() \ No newline at end of file + db.session.commit() + +def get_all_prerequisites(courseName): + return Prerequisites.query.filter(Prerequisites.courseName == courseName).all() + diff --git a/App/controllers/program.py b/App/controllers/program.py index f47cd5436..d4e891b38 100644 --- a/App/controllers/program.py +++ b/App/controllers/program.py @@ -1,17 +1,14 @@ from App.models import Program from App.database import db -def create_program(file_path): - try: - newProgram = Program(file_path) - db.session.add(newProgram) - db.session.commit() - return newProgram +def create_program(name, core, elective, foun): + newProgram = Program(name, core, elective, foun) + db.session.add(newProgram) + print("Program successfully created") + db.session.commit() + return newProgram + - except FileNotFoundError: - print("File not found.") - except Exception as e: - print(f"An error occurred: {e}") def get_program_by_name(programName): return Program.query.filter_by(name=programName).first() diff --git a/App/controllers/programCourses.py b/App/controllers/programCourses.py new file mode 100644 index 000000000..c29fbc0de --- /dev/null +++ b/App/controllers/programCourses.py @@ -0,0 +1,21 @@ +from App.models import ProgramCourses, Program, Course +from App.controllers import (get_program_by_name, get_course_by_courseCode) +from App.database import db + +def create_programCourse(programName, code, num): + program = get_program_by_name(programName) + if program: + course = get_course_by_courseCode(code) + if course: + proCourse = ProgramCourses(program.id, code, num) + db.session.add(proCourse) + db.session.commit() + print("Course successfully added to program") + else: + print("Invalid course code") + else: + print("Invalid program name") + +def get_all_programCourses(programName): + program = get_program_by_name(programName) + return ProgramCourses.query.filter(ProgramCourses.program_id == program.id).all() diff --git a/App/controllers/student.py b/App/controllers/student.py index 45935db7d..97d9d3ad9 100644 --- a/App/controllers/student.py +++ b/App/controllers/student.py @@ -1,17 +1,19 @@ from App.models import Student, CoursePlan, Program +from App.controllers import (get_program_by_name) from App.database import db -def create_student(student_id, password, name): - new_student = Student(username=student_id, password=password, name=name) - db.session.add(new_student) - db.session.commit() - return new_student - -def get_student_by_username(username): - return Student.query.filter_by(username=username).first() +def create_student(student_id, password, name, programname): + program = get_program_by_name(programname) + if program: + new_student = Student(student_id, password, name, program.id) + db.session.add(new_student) + db.session.commit() + print("Student successfully created") + else: + print("Program doesn't exist") -def get_student(id): - return Student.query.get(id) +def get_student_by_id(ID): + return Student.query.filter_by(id=ID).first() def get_all_students(): return Student.query.all() diff --git a/App/controllers/studentCourseHistory.py b/App/controllers/studentCourseHistory.py new file mode 100644 index 000000000..a4046be97 --- /dev/null +++ b/App/controllers/studentCourseHistory.py @@ -0,0 +1,23 @@ +from App.models import StudentCourseHistory +from App.controllers import (get_student_by_id, get_course_by_courseCode) +from App.database import db + +def addCoursetoHistory(studentid, code): + student = get_student_by_id(studentid) + if student: + course = get_course_by_courseCode(code) + if course: + completed = StudentCourseHistory(studentid, code) + db.session.add(completed) + db.session.commit() + print("Course added successfully") + else: + print("Course doesn't exist") + else: + print("Student doesn't exist") + + + +def getCompletedCourses(id): + student = get_student_by_id(id) + return StudentCourseHistory.query.filter(StudentCourseHistory.studentID == id).all() diff --git a/App/models/__init__.py b/App/models/__init__.py index 2437a3c14..eef953f8a 100644 --- a/App/models/__init__.py +++ b/App/models/__init__.py @@ -7,4 +7,6 @@ from .coursePlan import * from .offeredCourses import * from .programCourses import * -from .prerequisites import* +from .prerequisites import * +from .studentCourseHistory import * + diff --git a/App/models/courses.py b/App/models/courses.py index bde461e30..611b7537d 100644 --- a/App/models/courses.py +++ b/App/models/courses.py @@ -6,6 +6,8 @@ class Course(db.Model): courseName = db.Column(db.String(25)) credits = db.Column(db.Integer) rating = db.Column(db.Integer) + + students = db.relationship('StudentCourseHistory', backref='courses', lazy=True) programs = db.relationship('ProgramCourses', backref='courses', lazy=True) prerequisites = db.relationship('Prerequisites', backref='courses', lazy = True) diff --git a/App/models/program.py b/App/models/program.py index bf6c574a7..d301555c3 100644 --- a/App/models/program.py +++ b/App/models/program.py @@ -3,46 +3,18 @@ class Program(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(50)) - level1_credits = db.Column(db.Integer) core_credits = db.Column(db.Integer) elective_credits = db.Column(db.Integer) foun_credits = db.Column(db.Integer) - students = db.relationship('Student', backref='program', lazy=True) courses = db.relationship('ProgramCourses', backref='program', lazy=True) - def __init__(self, file_path): - # try: - # with open(file_path, 'r') as file: - # lines = file.readlines() - # self.name = lines[0].strip() - # self.level1_credits = lines[1].strip() - # self.level1_courses = json.dumps(lines[2].strip().split(',')) - # self.core_credits = lines[3].strip() - # self.core_courses = json.dumps(lines[4].strip().split(',')) - # self.elective_credits = lines[5].strip() - # self.elective_courses = json.dumps(lines[6].strip().split(',')) - # self.foun_credits = lines[7].strip() - # self.foun_courses = json.dumps(lines[8].strip().split(',')) - - # except FileNotFoundError:l - # print("File not found.") - - # except Exception as e: - # print(f"An error occurred: {e}") - - def str_level1_courses(self): - return json.loads(self.level1_courses) if self.level1_courses else [] - - def str_core_courses(self): - return json.loads(self.core_courses) if self.core_courses else [] - - def str_elective_courses(self): - return json.loads(self.elective_courses) if self.elective_courses else [] - - def str_foun_courses(self): - return json.loads(self.foun_courses) if self.foun_courses else [] + def __init__(self, name, core, elective, foun): + self.name = name + self.core_credits = core + self.elective_credits = elective + self.foun_credits = foun def get_json(self): diff --git a/App/models/programCourses.py b/App/models/programCourses.py index 0a7bdfa63..e5eb6cfae 100644 --- a/App/models/programCourses.py +++ b/App/models/programCourses.py @@ -18,6 +18,7 @@ def __init__(self, programID, courseCode, num): def get_json(self): return{ + 'Program Course ID:' : self.id, 'Program ID:': self.program_id, 'Course Code: ': self.code, 'Course Type: ': self.courseType diff --git a/App/models/student.py b/App/models/student.py index d96f20ca7..edc88a0ee 100644 --- a/App/models/student.py +++ b/App/models/student.py @@ -5,28 +5,21 @@ class Student(User): id = db.Column(db.String(10), db.ForeignKey('user.id'), primary_key=True) name = db.Column(db.String(50)) - course_history = db.Column(db.String(500)) - nextSemCourses = db.Column(db.String(50)) program_id = db.Column(db.Integer, db.ForeignKey('program.id')) + associated_program = db.relationship('Program', back_populates='students', overlaps="program") + courses = db.relationship('StudentCourseHistory', backref='student', lazy=True) - def __init__(self, username, password, name, course_history=None, next_sem_courses=None, program_id=None): + def __init__(self, username, password, name, program_id): super().__init__(username, password) + self.id = username self.name = name - self.course_history = course_history - self.nextSemCourses = next_sem_courses self.program_id = program_id - - def str_courseHistory(self): - return json.loads(self.course_history) if self.course_history else [] - -def get_json(self): - return{ - 'student_id': self.id, - 'name': self.name, - 'course history': self.course_history, - 'next semester courses': self.nextSemCourses, - 'program' : self.program - } + def get_json(self): + return{ + 'student_id': self.id, + 'name': self.name, + 'program' : self.program_id + } diff --git a/App/models/studentCourseHistory.py b/App/models/studentCourseHistory.py new file mode 100644 index 000000000..955ee95cd --- /dev/null +++ b/App/models/studentCourseHistory.py @@ -0,0 +1,21 @@ +from App.database import db + +class StudentCourseHistory(db.Model): + __tablename__ = 'studentCourses' + id = db.Column(db.Integer, primary_key=True) + studentID = db.Column(db.ForeignKey('student.id')) + code = db.Column(db.ForeignKey('course.courseCode')) + + associated_course = db.relationship('Course', back_populates='students', overlaps="courses") + associated_student = db.relationship('Student', back_populates='courses', overlaps="student") + + def __init__(self, id, courseCode): + self.studentID = id + self.code = courseCode + + def get_json(self): + return{ + 'Program ID:': self.program_id, + 'Course Code: ': self.code, + 'Course Type: ': self.courseType + } \ No newline at end of file diff --git a/wsgi.py b/wsgi.py index a53ccb224..af737b223 100644 --- a/wsgi.py +++ b/wsgi.py @@ -17,9 +17,13 @@ get_course_by_courseCode, get_prerequisites, get_all_courses, - getRemainingCourses, + create_programCourse, addSemesterCourses, - create_student + create_student, + get_program_by_name, + get_all_programCourses, + addCoursetoHistory, + getCompletedCourses, ) @@ -36,6 +40,8 @@ def initialize(): db.create_all() create_user('bob', 'bobpass') create_course('testData/courseData.csv') + create_program("Computer Science Major", 69, 15, 9) + create_student(816, "boo", "testing", "Computer Science Major") print('database intialized') # with open('/Users/jerrellejohnson/Desktop/softEng2/flaskmvc/testData/courseData.csv', 'r') as csvfile: @@ -84,12 +90,27 @@ def list_user_command(format): # Define the student create command @student_cli.command("create", help="Creates a student") -@click.argument("password") -@click.argument("student_id") -@click.argument("name") -def create_student_command(student_id, password, name): - student = create_student(student_id, password, name) - print(f"Student {student.id} created.") +@click.argument("student_id", type=str) +@click.argument("password", type=str) +@click.argument("name", type=str) +@click.argument("programName", type=str) +def create_student_command(student_id, password, name, programname): + create_student(student_id, password, name, programname) + +@student_cli.command("addCourse", help="Student adds a completed course to their history") +@click.argument("student_id", type=str) +@click.argument("code", type=str) +def addCourse(student_id, code): + addCoursetoHistory(student_id, code) + +@student_cli.command("getCompleted", help="Get all of a student completed courses") +@click.argument("student_id", type=str) +def completed(student_id): + comp = getCompletedCourses(student_id) + for c in comp: + print(f'{c.code}') + + app.cli.add_command(student_cli) @@ -120,11 +141,13 @@ def user_tests_command(type): program = AppGroup('program', help = 'Program object commands') @program.command('create', help='Create a new program') -@click.argument('file_path') -def create_program_command(file_path): - with open(file_path, 'r') as file: - newprogram = create_program(file_path) - print(f'Program created with ID {newprogram.id} and name "{newprogram.name}"') +@click.argument('name', type=str) +@click.argument('core', type=int) +@click.argument('elective', type=int) +@click.argument('foun', type=int) +def create_program_command(name, core, elective, foun): + program = create_program(name, core, elective, foun) + @program.command('core', help='Get program core courses') @click.argument('programname', type=str) @@ -144,6 +167,25 @@ def allCourses(programname): all = get_all_courses(programname) print(f'All courses are = {all}') if credits else print(f'error') +@program.command('getprogram', help='Get a program by name') +@click.argument('programname', type=str) +def getProgram(programname): + program = get_program_by_name(programname) + print(f'{program.id}') + +@program.command('addCourse', help='Add a course to a program') +@click.argument('programname', type=str) +@click.argument('code', type=str) +@click.argument('type', type=int) +def addProgramCourse(programname, code, type): + create_programCourse(programname, code, type) + +@program.command('getprogramCourses', help='Get all courses of a program') +@click.argument('programname', type=str) +def addProgramCourse(programname): + courses = get_all_programCourses(programname) + for c in courses: + print(f'{c.code}') app.cli.add_command(program) ################################################################# @@ -176,8 +218,9 @@ def get_course(code): @course.command('getprereqs', help='Get all prerequistes for a course') @click.argument('code', type=str) def get_course(code): - course = get_course_by_courseCode(code) - print(f'Course Prerequisites: {course.prerequisites}') if course else print(f'error') + prereqs = get_prerequisites(code) + for r in prereqs: + print(f'{r.prereq_courseCode}') @course.command('nextsem', help='Add a course to offered courses') @click.argument('code', type=str) From 39d21018a28783bcd1f7faf59ad4699d08b3a691 Mon Sep 17 00:00:00 2001 From: JervalThomas Date: Thu, 5 Oct 2023 19:19:13 -0400 Subject: [PATCH 46/90] updateing changes from develpment branch --- .DS_Store | Bin 6148 -> 6148 bytes App/.DS_Store | Bin 6148 -> 6148 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/.DS_Store b/.DS_Store index d33561525b977ecafb01ff6cf6587d40bd8c155c..67419bc12ceba66b0b7956d8d160d5a3cacfc393 100644 GIT binary patch delta 38 ucmZoMXfc@J&&atkU^g=(=VTt1>zrvR#mPze`8kZ6Z?Z@;Z)WHC%MSqWvJ7Vc delta 31 ncmZoMXfc@J&&aVcU^g=($7CLs>zlu^2r^G>5Z=tr@s}R}qe2Qs diff --git a/App/.DS_Store b/App/.DS_Store index 611dedb96f2fe70210cea19e5d791c1acacb5791..876c08ef753511b198ca07aa12bc2ae03376e11d 100644 GIT binary patch delta 119 zcmZoMXfc=|#>B!ku~2NHo+2aL#(>?7iv?Ji7}+NCF#X_6ODRrH%FoYX1oEU*%YuvY za`N-i85kHCftZaUmm!}ag&~z8hoKmzl3}v|^KPci>>T_YKw~#EvV3Qr%rD}|0o1?* M)WfhjLSzjy05C=zhyVZp delta 75 zcmZoMXfc=|#>B)qu~2NHo+2a5#(>?7j4YFRS*0ecvD}-i&dR^ppLGY*#s(Xv&Fmcf d96+U;1v$PmPv#eK Date: Thu, 5 Oct 2023 21:29:36 -0400 Subject: [PATCH 47/90] more udpates --- App/controllers/admin.py | 35 ------------------------------- App/controllers/coursePlan.py | 2 +- App/controllers/offeredCourses.py | 2 +- App/controllers/programCourses.py | 25 ++++++++++++++++++++++ App/models/admin.py | 21 ------------------- App/models/courses.py | 1 + App/models/offeredCourses.py | 6 ++++-- App/models/student.py | 2 +- testData/courseData.csv | 1 + wsgi.py | 14 +++++++++---- 10 files changed, 44 insertions(+), 65 deletions(-) delete mode 100644 App/controllers/admin.py delete mode 100644 App/models/admin.py diff --git a/App/controllers/admin.py b/App/controllers/admin.py deleted file mode 100644 index bc78840c7..000000000 --- a/App/controllers/admin.py +++ /dev/null @@ -1,35 +0,0 @@ -from App.models import User -from App.models import Student -from App.models import Staff -from App.database import db - -def addStudent(id,username,password): #creates new student - newstudent=Student(id=id,username=username,password=password) - try: - db.session.add(newstudent) - db.session.commit() - except Exception as e: #student already exists - db.session.rollback() - print(f'Username or ID already taken') - print(f'Student created.') - return newstudent - -def addStaff(id,username,password): #creates new staff member - newstaff=Staff(id=id,username=username,password=password) - try: - db.session.add(newstaff) - db.session.commit() - except Exception as e: #staff already exists - db.session.rollback() - print(f'Username or ID already taken') - print(f'Staff created.') - return newstaff - -def removeAccount(id): #removes account by id - acc=User.query.filter_by(id=id).first() - if not acc: - print(f'Account with ID {id} not found.') - return - db.session.delete(acc) - db.session.commit() - print(f'Account deleted.') diff --git a/App/controllers/coursePlan.py b/App/controllers/coursePlan.py index bb1658574..e2630c6ad 100644 --- a/App/controllers/coursePlan.py +++ b/App/controllers/coursePlan.py @@ -4,7 +4,7 @@ from App.models import CoursePlan from App.models import Program from App.models import Course -from App.models import OfferedCourses +from App.models import CoursesOfferedPerSem def getProgramme(Student): diff --git a/App/controllers/offeredCourses.py b/App/controllers/offeredCourses.py index 0f6bd0fbc..090a87477 100644 --- a/App/controllers/offeredCourses.py +++ b/App/controllers/offeredCourses.py @@ -1,4 +1,4 @@ -from App.models import OfferedCourses +from App.models import CoursesOfferedPerSem from App.controllers import get_course_by_courseCode from App.database import db import json diff --git a/App/controllers/programCourses.py b/App/controllers/programCourses.py index c29fbc0de..6ee65f5ee 100644 --- a/App/controllers/programCourses.py +++ b/App/controllers/programCourses.py @@ -19,3 +19,28 @@ def create_programCourse(programName, code, num): def get_all_programCourses(programName): program = get_program_by_name(programName) return ProgramCourses.query.filter(ProgramCourses.program_id == program.id).all() + +def get_allCore(programName): + program = get_program_by_name(programName) + core = ProgramCourses.query.filter_by( + program_id=program.id, + courseType=1 + ).all() + return core if core else [] + +def get_allElectives(programName): + program = get_program_by_name(programName) + core = ProgramCourses.query.filter_by( + program_id=program.id, + courseType=2 + ).all() + return core if core else [] + +def get_allFoun(programName): + program = get_program_by_name(programName) + core = ProgramCourses.query.filter_by( + program_id=program.id, + courseType=3 + ).all() + return core if core else [] + diff --git a/App/models/admin.py b/App/models/admin.py deleted file mode 100644 index ac857a337..000000000 --- a/App/models/admin.py +++ /dev/null @@ -1,21 +0,0 @@ -from App.database import db -from App.models import User - -class Admin(User): - id=db.Column(db.foreignkey('user.id'), nullable=False) - name=db.Column(db.String(120), nullable=False) - user=db.relationship('User',backref=db.backref('Admin')) - - def __init__(self, username, password, name): - super.__init__(username=username,password=password) - self.name=name - - def get_json(self): - return{ - 'id': self.id, - 'name': self.name - } - - def __repr__(self): - return f'' - diff --git a/App/models/courses.py b/App/models/courses.py index 611b7537d..05af4bf86 100644 --- a/App/models/courses.py +++ b/App/models/courses.py @@ -7,6 +7,7 @@ class Course(db.Model): credits = db.Column(db.Integer) rating = db.Column(db.Integer) + offered = db.relationship('CoursesOfferedPerSem', backref ='courses', lazy=True) students = db.relationship('StudentCourseHistory', backref='courses', lazy=True) programs = db.relationship('ProgramCourses', backref='courses', lazy=True) prerequisites = db.relationship('Prerequisites', backref='courses', lazy = True) diff --git a/App/models/offeredCourses.py b/App/models/offeredCourses.py index fba028955..b6783a495 100644 --- a/App/models/offeredCourses.py +++ b/App/models/offeredCourses.py @@ -1,9 +1,11 @@ import json from App.database import db -class OfferedCourses(db.Model): +class CoursesOfferedPerSem(db.Model): id = db.Column(db.Integer, primary_key=True) - offered = db.Column(db.String(10)) + code = db.Column(db.ForeignKey('course.courseCode')) + + associated_course = db.relationship('Course', back_populates='offered', overlaps="courses") def __init__(self, courseCode): self.offered = courseCode diff --git a/App/models/student.py b/App/models/student.py index edc88a0ee..789699ca0 100644 --- a/App/models/student.py +++ b/App/models/student.py @@ -5,7 +5,7 @@ class Student(User): id = db.Column(db.String(10), db.ForeignKey('user.id'), primary_key=True) name = db.Column(db.String(50)) - program_id = db.Column(db.Integer, db.ForeignKey('program.id')) + program_id = db.Column(db.ForeignKey('program.id')) associated_program = db.relationship('Program', back_populates='students', overlaps="program") courses = db.relationship('StudentCourseHistory', backref='student', lazy=True) diff --git a/testData/courseData.csv b/testData/courseData.csv index 4a8154dd2..22578d705 100644 --- a/testData/courseData.csv +++ b/testData/courseData.csv @@ -3,3 +3,4 @@ COMP2611,Data Structures,3,5, MATH2250,Industrial Statistics,3,4, COMP3605,Data Analytics,3,3,"COMP2611,MATH2250" COMP3610,Big Data Analytics,3,5,COMP3605 +COMP3611,small Data Analytics,3,5,COMP3610 \ No newline at end of file diff --git a/wsgi.py b/wsgi.py index af737b223..962685a02 100644 --- a/wsgi.py +++ b/wsgi.py @@ -24,6 +24,7 @@ get_all_programCourses, addCoursetoHistory, getCompletedCourses, + get_allCore, ) @@ -42,6 +43,7 @@ def initialize(): create_course('testData/courseData.csv') create_program("Computer Science Major", 69, 15, 9) create_student(816, "boo", "testing", "Computer Science Major") + print('database intialized') # with open('/Users/jerrellejohnson/Desktop/softEng2/flaskmvc/testData/courseData.csv', 'r') as csvfile: @@ -150,10 +152,14 @@ def create_program_command(name, core, elective, foun): @program.command('core', help='Get program core courses') -@click.argument('programname', type=str) -def get_CoreCourses(programname): - courses = get_core_courses(programname) - print(f'{courses}') if courses else print(f'error') +#@click.argument('programname', type=str) +def get_CoreCourses(): + create_programCourse("Computer Science Major", "COMP2611", 1) + create_programCourse("Computer Science Major", "COMP3605", 1) + create_programCourse("Computer Science Major", "COMP3610", 2) + core = get_allCore("Computer Science Major") + for c in core: + print({c.code}) @program.command('corecredits', help='Get program core courses') @click.argument('programname', type=str) From ab026cb2add7340dda40a3c5ece05ef11cd502c5 Mon Sep 17 00:00:00 2001 From: Ashley Jacob Date: Fri, 6 Oct 2023 06:59:04 -0400 Subject: [PATCH 48/90] created staff views --- App/controllers/__init__.py | 1 - App/controllers/offeredCourses.py | 2 +- App/models/__init__.py | 1 - App/views/staff.py | 31 +++++++++++----- wsgi.py | 62 +++++++++++++++++-------------- 5 files changed, 57 insertions(+), 40 deletions(-) diff --git a/App/controllers/__init__.py b/App/controllers/__init__.py index d155fc1c3..77afc6db4 100644 --- a/App/controllers/__init__.py +++ b/App/controllers/__init__.py @@ -4,7 +4,6 @@ from .program import * from .staff import * from .student import * -from .admin import * from .courses import * from .coursePlan import * from .offeredCourses import * diff --git a/App/controllers/offeredCourses.py b/App/controllers/offeredCourses.py index 090a87477..160109ba7 100644 --- a/App/controllers/offeredCourses.py +++ b/App/controllers/offeredCourses.py @@ -6,7 +6,7 @@ def addSemesterCourses(courseCode): course = get_course_by_courseCode(courseCode) if course: - semCourses = OfferedCourses(courseCode) + semCourses = CoursesOfferedPerSem(courseCode) db.session.add(semCourses) db.session.commit() return course diff --git a/App/models/__init__.py b/App/models/__init__.py index 372f5400c..eef953f8a 100644 --- a/App/models/__init__.py +++ b/App/models/__init__.py @@ -3,7 +3,6 @@ from .program import * from .staff import * from .student import * -from .admin import * from .courses import * from .coursePlan import * from .offeredCourses import * diff --git a/App/views/staff.py b/App/views/staff.py index 2b834cc88..a966f79b8 100644 --- a/App/views/staff.py +++ b/App/views/staff.py @@ -15,13 +15,26 @@ staff_views = Blueprint('staff_views', __name__, template_folder='../templates') -@staff_views.route('/staff/addNextSemesterCourse/', methods=['POST']) +@staff_views.route('/staff/addProgram////', + methods=['POST']) +@login_required +def addProgram(name, core, elective, foun): + newprogram = create_program(name, core, elective, foun) + return jsonify({'message': f"Program {newprogram['name']} added" + }) if newprogram else 200 + + +@staff_views.route('/staff/addProgramReq///', + methods=['POST']) +@login_required +def addProgramRequirements(name, code, num): + create_programCourse(name, code, num) + return jsonify({'message': f"Program added"}) + + +@staff_views.route('/staff/addNextSemesterCourse/', + methods=['POST']) +@login_required def addCourse(courseCode): - token =gettoken - course = addSemesterCourses(courseCode) - return jsonify({'message': f"Course {course['courseName']} added"}) if course else 200 - - - - - + course = addSemesterCourses(courseCode) + return jsonify({'message': f"Course {course['courseName']} added"}) if course else 200 \ No newline at end of file diff --git a/wsgi.py b/wsgi.py index 3d0f247c4..c6aa35354 100644 --- a/wsgi.py +++ b/wsgi.py @@ -1,7 +1,6 @@ import click, pytest, sys import csv from flask import Flask -from App.controllers.admin import addStaff, createAdmin, removeAccount from App.controllers.student import create_student from flask.cli import with_appcontext, AppGroup @@ -22,6 +21,7 @@ create_programCourse, addSemesterCourses, create_student, + create_staff, get_program_by_name, get_all_programCourses, addCoursetoHistory, @@ -118,35 +118,41 @@ def completed(student_id): app.cli.add_command(student_cli) ''' -Admin Commands +Staff Commands ''' +staff_cli = AppGroup('staff',help='testing staff commands') +@staff_cli.command("create",help="create staff") +@click.argument("id", type=str) +@click.argument("password", type=str) +@click.argument("name", type=str) +def create_staff_command(id, password, name): + newstaff=create_staff(password,id, name) + print(f'Staff {newstaff.name} created') + +@staff_cli.command("addprogram",help='testing add program feature') +@click.argument("name", type=str) +@click.argument("core", type=int) +@click.argument("elective", type=int) +@click.argument("foun", type=int) +def create_program_command(name,core,elective,foun): + newprogram=create_program(name,core,elective,foun) + print(f'{newprogram.get_json()}') + +@staff_cli.command("addprogramcourse",help='testing add program feature') +@click.argument("name", type=str) +@click.argument("code", type=str) +@click.argument("num", type=int) +def add_program_requirements(name,code,num): + create_programCourse(name,code,num) + +@staff_cli.command("addofferedcourse",help='testing add courses offered feature') +@click.argument("code", type=str) +def add_offered_course(code): + course=addSemesterCourses(code) + print(f'Course details: {course}') + -admin_cli = AppGroup("admin", help="Admin object commands") - -# Define the admin create command -@admin_cli.command("create_admin", help="Creates an admin") -@click.argument("id") -@click.argument("username") -@click.argument("password") -@click.argument("name") -def create_admin_command(id, username, password, name): - createAdmin(id, username, password, name) - -@admin_cli.command("create_staff", help="Creates a staff member") -@click.argument("id") -@click.argument("username") -@click.argument("password") -@click.argument("name") -def create_staff_command(id, username, password, name): - addStaff(id, username, password, name) - print(f"Staff member {username} created") - -@admin_cli.command("delete", help="Creates a staff member") -@click.argument("id") -def delete_user_command(id): - removeAccount(id) - -app.cli.add_command(admin_cli) +app.cli.add_command(staff_cli) ''' Test Commands From 2df598b4bbb996dfcf4f3fcb7a00acaec6381f1c Mon Sep 17 00:00:00 2001 From: Ashley Jacob Date: Fri, 6 Oct 2023 07:00:09 -0400 Subject: [PATCH 49/90] updated staff view --- App/views/staff.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/App/views/staff.py b/App/views/staff.py index a966f79b8..3cd5f0fb1 100644 --- a/App/views/staff.py +++ b/App/views/staff.py @@ -6,6 +6,8 @@ from App.controllers import ( create_user, + create_program, + create_programCourse, jwt_authenticate, get_all_users, get_all_users_json, From e1ffeec6661b9a6303b578c1fcc8110f954121af Mon Sep 17 00:00:00 2001 From: Kyle-McIntosh Date: Fri, 6 Oct 2023 13:26:39 -0400 Subject: [PATCH 50/90] Development merge --- App/controllers/prerequisites.py | 3 --- App/models/prerequisites.py | 17 ++++++++--------- 2 files changed, 8 insertions(+), 12 deletions(-) delete mode 100644 App/controllers/prerequisites.py diff --git a/App/controllers/prerequisites.py b/App/controllers/prerequisites.py deleted file mode 100644 index 20b53f0cd..000000000 --- a/App/controllers/prerequisites.py +++ /dev/null @@ -1,3 +0,0 @@ -from App.models import prerequisites, Course -from App.database import db - diff --git a/App/models/prerequisites.py b/App/models/prerequisites.py index 88838cd9b..a8329c643 100644 --- a/App/models/prerequisites.py +++ b/App/models/prerequisites.py @@ -4,21 +4,20 @@ class Prerequisites(db.Model): id = db.Column(db.Integer, primary_key=True) - course_id = db.Column(db.String(8), db.ForeignKey('course.courseCode'), primary_key=True) - prereq_code = db.Column(db.String(8)) #Maybe also a foreignkey + prereq_courseCode = db.Column(db.ForeignKey('course.courseCode')) + courseName = db.Column(db.String(25)) + associated_course = db.relationship('Course', back_populates='prerequisites', overlaps="courses") + - course = db.relationship('Course', foreign_keys=[course_id], backref='prerequisite_rel') - #course = db.relationship('Course', back_populates='prerequisites_rel') - #prereq_course = db.relationship('Course', foreign_keys=[prereq_code], back_populates='prerequisites_for') - def __init__(self, course_id, prereq_code): - self.course_id = course_id - self.prereq_code = prereq_code + def __init__(self, prereqCode, nameofCourse): + self.prereq_courseCode = prereqCode + self.courseName = nameofCourse def get_json(self): return{ 'prereq_id': self.id, 'course_id': self.course_id, 'prerequisite_course': self.prereq_code, - } \ No newline at end of file + } \ No newline at end of file From 9d9fca85e9cf418e8c0e44006362ebff00c0baec Mon Sep 17 00:00:00 2001 From: Jerrelle Johnson Date: Fri, 6 Oct 2023 18:26:52 -0400 Subject: [PATCH 51/90] Code not breaking at this point, just to test courseplan controller --- App/controllers/__init__.py | 8 +- App/controllers/coursePlan.py | 226 ++++++++++++++---------- App/controllers/coursePlanCourses.py | 25 +++ App/controllers/offeredCourses.py | 32 +++- App/controllers/prerequistes.py | 8 + App/controllers/program.py | 3 + App/controllers/programCourses.py | 8 + App/controllers/studentCourseHistory.py | 10 +- App/models/__init__.py | 5 +- App/models/coursePlan.py | 25 +-- App/models/coursePlanCourses.py | 23 +++ App/models/courses.py | 8 +- App/models/offeredCourses.py | 1 - App/models/prerequisites.py | 12 +- App/models/program.py | 1 - App/models/programCourses.py | 2 - App/models/staff.py | 6 +- App/models/student.py | 11 +- App/models/studentCourseHistory.py | 3 +- wsgi.py | 7 +- 20 files changed, 273 insertions(+), 151 deletions(-) create mode 100644 App/controllers/coursePlanCourses.py create mode 100644 App/models/coursePlanCourses.py diff --git a/App/controllers/__init__.py b/App/controllers/__init__.py index 77afc6db4..44cf29964 100644 --- a/App/controllers/__init__.py +++ b/App/controllers/__init__.py @@ -4,9 +4,9 @@ from .program import * from .staff import * from .student import * -from .courses import * -from .coursePlan import * -from .offeredCourses import * from .prerequistes import * from .programCourses import * -from .studentCourseHistory import * \ No newline at end of file +from .studentCourseHistory import * +from .coursePlanCourses import * +from .offeredCourses import * +from .coursePlan import * \ No newline at end of file diff --git a/App/controllers/coursePlan.py b/App/controllers/coursePlan.py index e2630c6ad..4891a4068 100644 --- a/App/controllers/coursePlan.py +++ b/App/controllers/coursePlan.py @@ -1,124 +1,169 @@ -from App.database import db -from App.models import Student -from App.models import Staff from App.models import CoursePlan -from App.models import Program -from App.models import Course -from App.models import CoursesOfferedPerSem - - -def getProgramme(Student): - return Program.query.filter_by(id=Student.program_id).first() +from App.database import db +from App.controllers import ( + get_program_by_id, + get_course_by_courseCode, + get_credits, + getPrereqCodes, + getCompletedCourses, + createPlanCourse, + deleteCourseFromCoursePlan, + get_allCore, + get_allFoun, + get_allElectives, + getCompletedCourseCodes, + convertToList, + get_all_OfferedCodes, + isCourseOffered +) + + +def create_CoursePlan(id): + plan = CoursePlan(id) + db.session.add(plan) + db.session.commit() + return plan +def getCoursePlan(studentid): + return CoursePlan.query.filter_by(CoursePlan.studentId==studentid).first() -def getOfferedCourses(): - staff=Staff.first() - return staff.get_all_courses() +def possessPrereqs(Student, course): + preqs = getPrereqCodes(course.courseName) + completed = getCompletedCourseCodes(Student.id) + for course in preqs: + if course not in completed: + return False + + return True def addCourse(Student, courseCode): - plan=CoursePlan.query.filter_by(studentId=Student.id).first() - course=checkPrereq(Student,[{courseCode}]) #verify prereqs + course = get_course_by_courseCode(courseCode) if course: - validCourse=findAvailable(course)#check availability - else: - print(f'Pre-req unsatisfied') - - if validCourse: - plan.courses.append(courseCode) - print(f'Course added') + offered = isCourseOffered(courseCode) + if offered: + haveAllpreqs = possessPrereqs(Student, course) + if haveAllpreqs: + plan = getCoursePlan(Student.id) + if plan: + createPlanCourse(plan.planid, courseCode) + print("Course successfully added to course plan") + else: + plan = create_CoursePlan(Student.id) + createPlanCourse(plan.planid, courseCode) + print("Plan successfully created and Course was successfully added to course plan") + else: + print("Course is not offered") else: - print(f'Course not available') + print("Course does not exist") def removeCourse(Student, courseCode): - plan=CoursePlan.query.filter_by(studentId=Student.id).first() - if courseCode in plan.courses: - plan.courses.remove(courseCode) - print(f'Course removed') - return - print(f'Course not found') - + plan=getCoursePlan(Student.id) + if plan: + deleteCourseFromCoursePlan(plan.planid, courseCode) def getRemainingCourses(completed, required): - remaining=required.copy() - # Check if either 'completed' or 'required' is None if completed is None or required is None: return [] # Return an empty list or handle it in a way that makes sense for your application - for course in required: - if course in completed: - remaining.remove(course) - return remaining + completedCodes = [] + for c in completed: + completedCodes.append(c.code) + + remainingCodes = [] + for r in required: + remainingCodes.append(r.code) + + + for r in remainingCodes: + if r in completedCodes: + remainingCodes.remove(r) + + return remainingCodes def getRemainingCore(Student): - programme=getProgramme(Student) - reqCore=programme.get_core_courses(programme.name) - remaining=getRemainingCourses(Student.course_history,reqCore) + programme=get_program_by_id(Student.program_id) + remaining = [] + + if programme: + reqCore=get_allCore(programme.name) + completed = getCompletedCourses(Student.id) + remaining=getRemainingCourses(completed,reqCore) + return remaining def getRemainingFoun(Student): - programme=getProgramme(Student) - reqFoun=programme.get_foun_courses(programme.name) - remaining=getRemainingCourses(Student.course_history,reqFoun) + programme = get_program_by_id(Student.program_id) + remaining =[] + + if programme: + reqFoun = get_allFoun(programme.name) + completed = getCompletedCourses(Student.id) + remaining=getRemainingCourses(completed,reqFoun) + return remaining def getRemainingElec(Student): - program = getProgramme(Student) # Get the student's program - if program: - reqElec = program.str_elective_courses() # Use the instance method to get elective courses - if reqElec: - remaining = getRemainingCourses(Student.course_history, reqElec) - return remaining - return [] + programme = get_program_by_id(Student.program_id) # Get the student's program + remaining = [] + + if programme: + reqElec = get_allElectives(programme.name) # Use the instance method to get elective courses + completed = getCompletedCourses(Student.id) + remaining = getRemainingCourses(completed, reqElec) + + return remaining def remElecCredits(Student): - program = getProgramme(Student) # Get the student's program - if program: - requiredCreds = program.elective_credits # Access the elective_credits attribute - elective_courses = program.str_elective_courses() # Use the instance method to get elective courses - if elective_courses: - for course in elective_courses: - if course in Student.course_history: - c = Course.query.filter_by(courseCode=course).first() # Get course + programme = get_program_by_id(Student.program_id) # Get the student's program + completedcourses = getCompletedCourseCodes(Student.id) + requiredCreds = 0 + + if programme: + requiredCreds = programme.elective_credits # Access the elective_credits attribute + elective_courses = get_allElectives(programme.name) # Use the instance method to get elective courses + electCodes = convertToList(elective_courses) + if electCodes: + for code in electCodes: + if code in completedcourses: + c = get_course_by_courseCode(code) # Get course if c: requiredCreds = requiredCreds - c.credits # Subtract credits - return requiredCreds - return 0 + + return requiredCreds def findAvailable(courseList): - listing=getOfferedCourses() + listing=get_all_OfferedCodes() available=[] - for course in courseList: - if course in listing: - c=Course.query.filter_by(courseCode=course).first() #get course - if c: - available.append(c) + + for code in courseList: + if code in listing: + available.append() + return available #returns an array of course objects -def checkPrereq(Student, listing): - completed=Student.courseHistory +def checkPrereq(Student, recommnded): validCourses=[] - - for course in listing: - satisfied=True - prereq=course.get_prerequisites(course.courseCode) - #check if the student did all the prereq courses - for c in prereq: - if c not in completed: #if at least one was not done, the student can't take the course - satisfied=False + for course in recommnded: + c = get_course_by_courseCode(course) + satisfied = possessPrereqs(Student, c) if satisfied: - validCourses.append(c) + validCourses.append(c.courseCode) return validCourses +def getTopfive(list): + return list[:5] + + def prioritizeElectives(Student): #get available electives @@ -130,12 +175,13 @@ def prioritizeElectives(Student): for c in electives: if credits>0: courses.append(c) - credits=credits-c.get_credits(c.courseCode) + credits = credits - get_credits(c) #merge available, required core and foundation courses - courses=courses + findAvailable(getRemainingCore(Student)) + findAvailable(getRemainingFoun(Student)) - courses=checkPrereq(Student,courses) - return courses + courses = courses + findAvailable(getRemainingCore(Student)) + findAvailable(getRemainingFoun(Student)) + courses = checkPrereq(Student,courses) + + return getTopfive(courses) def easyCourses(Student): @@ -176,17 +222,15 @@ def fastestGraduation(Student): courses=checkPrereq(Student,courses) return courses -def create_easy_plan(studentId): - # Get the student object based on studentId - student = Student.query.get(studentId) - # Generate a list of courses using the easyCourses function - courses = easyCourses(student) +def generator(Student, command): + courses = [] - # Create a new CoursePlan for the student with the generated courses - new_course_plan = CoursePlan(studentId=studentId, courses=courses) + if command == "electives": + plan = create_CoursePlan(Student.id) + courses = prioritizeElectives(Student) + + for c in courses: + createPlanCourse(plan.planId, c) - # Add the new course plan to the database and commit the changes - db.session.add(new_course_plan) - db.session.commit() - return new_course_plan \ No newline at end of file + return courses \ No newline at end of file diff --git a/App/controllers/coursePlanCourses.py b/App/controllers/coursePlanCourses.py new file mode 100644 index 000000000..b4d5d0635 --- /dev/null +++ b/App/controllers/coursePlanCourses.py @@ -0,0 +1,25 @@ +from App.models import CoursePlanCourses +from App.database import db + +def createPlanCourse(planid, code): + course = CoursePlanCourses(planid, code) + db.session.add(course) + db.session.commit() + +def getCourseFromCoursePlan(planid, coursecode): + return CoursePlanCourses.query.filter_by( + planId = planid, + code = coursecode + ).first() + +def get_all_courses_by_planid(id): + return CoursePlanCourses.query.filter_by(CoursePlanCourses.planId == id).all() + +def deleteCourseFromCoursePlan(planid, coursecode): + course = getCourseFromCoursePlan(planid, coursecode) + if course: + db.session.delete(course) + db.session.commit() + print("Course succesfully removed from course plan") + else: + print("Course is not in Course Plan") diff --git a/App/controllers/offeredCourses.py b/App/controllers/offeredCourses.py index 090a87477..b10ec11ff 100644 --- a/App/controllers/offeredCourses.py +++ b/App/controllers/offeredCourses.py @@ -1,21 +1,39 @@ from App.models import CoursesOfferedPerSem from App.controllers import get_course_by_courseCode from App.database import db -import json def addSemesterCourses(courseCode): course = get_course_by_courseCode(courseCode) if course: - semCourses = OfferedCourses(courseCode) + semCourses = CoursesOfferedPerSem(courseCode) db.session.add(semCourses) db.session.commit() return course else: print("Course not found") -def removeAllCourses(semCourses): - semCourses.offered = json.dumps([]) - return semCourses +def delete_all_records(): + try: + db.session.query(CoursesOfferedPerSem).delete() + db.session.commit() + print("All records deleted successfully.") + + except Exception as e: + db.session.rollback() + print(f"An error occurred: {str(e)}") + +def isCourseOffered(courseCode): + course = CoursesOfferedPerSem.query.filter_by(code=courseCode).first() + return True if course else False + +def get_all_courses(): + return CoursesOfferedPerSem.query.all() + +def get_all_OfferedCodes(): + offered = get_all_courses() + offeredcodes=[] -def get_all_courses(semCourses): - return semCourses.offeredCourses \ No newline at end of file + for c in offered: + offeredcodes.append(c.code) + + return offeredcodes diff --git a/App/controllers/prerequistes.py b/App/controllers/prerequistes.py index f1f305a1a..671db33c8 100644 --- a/App/controllers/prerequistes.py +++ b/App/controllers/prerequistes.py @@ -9,3 +9,11 @@ def create_prereq(prereqCode, courseName): def get_all_prerequisites(courseName): return Prerequisites.query.filter(Prerequisites.courseName == courseName).all() +def getPrereqCodes(courseName): + prereqs = get_all_prerequisites(courseName) + codes = [] + + for p in prereqs: + codes.append(p.prereq_courseCode) + + return codes \ No newline at end of file diff --git a/App/controllers/program.py b/App/controllers/program.py index d4e891b38..7e080b3d1 100644 --- a/App/controllers/program.py +++ b/App/controllers/program.py @@ -13,6 +13,9 @@ def create_program(name, core, elective, foun): def get_program_by_name(programName): return Program.query.filter_by(name=programName).first() +def get_program_by_id(programId): + return Program.query.filter_by(id=programId).first() + def get_level1_credits(programName): program = get_program_by_name(programName) return program.level1_credits if program else 0 diff --git a/App/controllers/programCourses.py b/App/controllers/programCourses.py index 6ee65f5ee..2fd6e7dbc 100644 --- a/App/controllers/programCourses.py +++ b/App/controllers/programCourses.py @@ -44,3 +44,11 @@ def get_allFoun(programName): ).all() return core if core else [] +def convertToList(list): + codes = [] + + for a in list: + codes.append(a.code) + + return codes + diff --git a/App/controllers/studentCourseHistory.py b/App/controllers/studentCourseHistory.py index a4046be97..b7de3461a 100644 --- a/App/controllers/studentCourseHistory.py +++ b/App/controllers/studentCourseHistory.py @@ -19,5 +19,13 @@ def addCoursetoHistory(studentid, code): def getCompletedCourses(id): - student = get_student_by_id(id) return StudentCourseHistory.query.filter(StudentCourseHistory.studentID == id).all() + +def getCompletedCourseCodes(id): + completed = getCompletedCourseCodes(id) + codes = [] + + for c in completed: + codes.append(c.code) + + return codes diff --git a/App/models/__init__.py b/App/models/__init__.py index eef953f8a..3e21cfcfe 100644 --- a/App/models/__init__.py +++ b/App/models/__init__.py @@ -3,10 +3,9 @@ from .program import * from .staff import * from .student import * -from .courses import * -from .coursePlan import * from .offeredCourses import * from .programCourses import * from .prerequisites import * from .studentCourseHistory import * - +from .coursePlanCourses import * +from .coursePlan import * diff --git a/App/models/coursePlan.py b/App/models/coursePlan.py index 5dc149d0c..e3cfaa1e5 100644 --- a/App/models/coursePlan.py +++ b/App/models/coursePlan.py @@ -1,26 +1,19 @@ -from flask_login import UserMixin from App.database import db -import json -class CoursePlan(db.Model,UserMixin): +class CoursePlan(db.Model): planId=db.Column(db.Integer, primary_key=True) studentId=db.Column(db.Integer, db.ForeignKey('student.id'), nullable=False) - courses=db.Column(db.String(100), nullable=True) - #student=db.relationship('Student', db.backref('CoursePlan')) - student = db.relationship('Student', backref=db.backref('course_plans', uselist=True)) - def __init__(self, studentId, courses=None): - self.studentId = studentId - self.courses=json.dumps(courses) + student = db.relationship('Student', backref=db.backref('course_plans', uselist=True)) + + # courses = db.relationship('CoursePlanCourses', backref = 'coursePlan', lazy=True) + + def __init__(self, studentid, ): + self.studentId = studentid + def get_json(self): return{ 'planId': self.planId, 'studentId': self.studentId, - 'courses': self.courses - } - - def __repr__(self): - return f'' - - + } \ No newline at end of file diff --git a/App/models/coursePlanCourses.py b/App/models/coursePlanCourses.py new file mode 100644 index 000000000..07959fe66 --- /dev/null +++ b/App/models/coursePlanCourses.py @@ -0,0 +1,23 @@ +from App.database import db + + +class CoursePlanCourses(db.Model): + id = db.Column(db.Integer, primary_key=True) + planId = db.Column(db.ForeignKey('course_plan.planId')) + code = db.Column(db.ForeignKey('course.courseCode')) + + # associated_coursePlan = db.relationship('CoursePlan', back_populates='students', overlaps="coursePlan") + # associated_course = db.relationship('Course', back_populates='planIds', overlaps="courses") + + def __init__(self, username, password, name, program_id): + self.id = username + self.name = name + self.program_id = program_id + + def get_json(self): + return{ + 'student_id': self.id, + 'name': self.name, + 'program' : self.program_id + } + diff --git a/App/models/courses.py b/App/models/courses.py index 05af4bf86..2bbf42e4c 100644 --- a/App/models/courses.py +++ b/App/models/courses.py @@ -11,13 +11,12 @@ class Course(db.Model): students = db.relationship('StudentCourseHistory', backref='courses', lazy=True) programs = db.relationship('ProgramCourses', backref='courses', lazy=True) prerequisites = db.relationship('Prerequisites', backref='courses', lazy = True) + + # planIds = db.relationship('CoursePlanCourses', backref='courses', lazy=True) def __init__(self): pass - - def get_prerequisites(self): - return json.loads(self.prerequisites) if self.prerequisites else [] def get_json(self): return{ @@ -26,5 +25,4 @@ def get_json(self): 'Course Rating: ': self.rating, 'No. of Credits: ': self.credits, 'Prerequistes: ': self.prerequisites - } - + } \ No newline at end of file diff --git a/App/models/offeredCourses.py b/App/models/offeredCourses.py index b6783a495..d45d0252a 100644 --- a/App/models/offeredCourses.py +++ b/App/models/offeredCourses.py @@ -1,4 +1,3 @@ -import json from App.database import db class CoursesOfferedPerSem(db.Model): diff --git a/App/models/prerequisites.py b/App/models/prerequisites.py index a8329c643..1909c1c11 100644 --- a/App/models/prerequisites.py +++ b/App/models/prerequisites.py @@ -1,6 +1,4 @@ from App.database import db - - class Prerequisites(db.Model): id = db.Column(db.Integer, primary_key=True) @@ -16,8 +14,8 @@ def __init__(self, prereqCode, nameofCourse): self.courseName = nameofCourse def get_json(self): - return{ - 'prereq_id': self.id, - 'course_id': self.course_id, - 'prerequisite_course': self.prereq_code, - } \ No newline at end of file + return{ + 'prereq_id': self.id, + 'course_id': self.course_id, + 'prerequisite_course': self.prereq_code, + } \ No newline at end of file diff --git a/App/models/program.py b/App/models/program.py index d301555c3..1f2e97db9 100644 --- a/App/models/program.py +++ b/App/models/program.py @@ -1,5 +1,4 @@ from App.database import db -import json class Program(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(50)) diff --git a/App/models/programCourses.py b/App/models/programCourses.py index e5eb6cfae..c74cf1137 100644 --- a/App/models/programCourses.py +++ b/App/models/programCourses.py @@ -1,6 +1,4 @@ from App.database import db -import json - class ProgramCourses(db.Model): __tablename__ ='program_courses' id = db.Column(db.Integer, primary_key=True) diff --git a/App/models/staff.py b/App/models/staff.py index 88bfb8335..8aefb7de0 100644 --- a/App/models/staff.py +++ b/App/models/staff.py @@ -1,12 +1,10 @@ -# staff.py - -from .user import User # Import the User class from user.py +from .user import User from App.database import db class Staff(User): - id = db.Column(db.String(10), db.ForeignKey('user.id'), primary_key=True) #foreign key + id = db.Column(db.String(10), db.ForeignKey('user.id'), primary_key=True) name = db.Column(db.String(50)) def __init__(self, username, password, staff_id, name): diff --git a/App/models/student.py b/App/models/student.py index 789699ca0..134dd78ae 100644 --- a/App/models/student.py +++ b/App/models/student.py @@ -1,6 +1,5 @@ from App.models import User from App.database import db -import json class Student(User): id = db.Column(db.String(10), db.ForeignKey('user.id'), primary_key=True) @@ -17,9 +16,9 @@ def __init__(self, username, password, name, program_id): self.program_id = program_id def get_json(self): - return{ - 'student_id': self.id, - 'name': self.name, - 'program' : self.program_id - } + return{ + 'student_id': self.id, + 'name': self.name, + 'program' : self.program_id + } diff --git a/App/models/studentCourseHistory.py b/App/models/studentCourseHistory.py index 955ee95cd..e93b623c1 100644 --- a/App/models/studentCourseHistory.py +++ b/App/models/studentCourseHistory.py @@ -16,6 +16,5 @@ def __init__(self, id, courseCode): def get_json(self): return{ 'Program ID:': self.program_id, - 'Course Code: ': self.code, - 'Course Type: ': self.courseType + 'Course Code: ': self.code } \ No newline at end of file diff --git a/wsgi.py b/wsgi.py index 962685a02..c24ca0973 100644 --- a/wsgi.py +++ b/wsgi.py @@ -2,7 +2,12 @@ import csv from flask import Flask from flask.cli import with_appcontext, AppGroup - +""" +# add more courses, +# populate student course history 10courses +add courses to program +offered courses +""" from App.database import db, get_migrate from App.main import create_app From bd6d813d3c25a512e927479e183933a6eee4294e Mon Sep 17 00:00:00 2001 From: Kyle-McIntosh <78955773+Kyle-McIntosh@users.noreply.github.com> Date: Fri, 6 Oct 2023 23:29:08 +0000 Subject: [PATCH 52/90] Student views created --- App/views/__init__.py | 4 +-- App/views/student.py | 80 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+), 2 deletions(-) create mode 100644 App/views/student.py diff --git a/App/views/__init__.py b/App/views/__init__.py index 1658f4ee1..cc3af70f9 100644 --- a/App/views/__init__.py +++ b/App/views/__init__.py @@ -5,7 +5,7 @@ from .auth import auth_views from .course import course_views from .staff import staff_views +from .student import student_views - -views = [user_views, index_views, auth_views, course_views, staff_views] +views = [user_views, index_views, auth_views, course_views, staff_views, student_views] # blueprints must be added to this list \ No newline at end of file diff --git a/App/views/student.py b/App/views/student.py new file mode 100644 index 000000000..326c6f645 --- /dev/null +++ b/App/views/student.py @@ -0,0 +1,80 @@ +from flask import Blueprint, render_template, jsonify, request, send_from_directory, flash, redirect, url_for +from flask_jwt_extended import jwt_required, current_user as jwt_current_user +from flask_login import current_user, login_required +from.index import index_views + +from App.controllers import ( + #create_user, + #jwt_authenticate, + #get_all_users, + #get_all_users_json, + jwt_required, + create_student, + get_program_by_name, + get_student_by_id, + get_course_by_courseCode, + addCoursetoHistory, + create_easy_plan, +) + +student_views = Blueprint('student_views', __name__, template_folder='../templates') + +##Create student +@student_views.route('/student', methods=['POST']) +@jwt_required() +def create_student_route(): + student_id = request.json['student_id'] + password = request.json['password'] + name = request.json['name'] + programname = request.json['programname'] + + student = get_student_by_id(student_id) + if student: + return jsonify({'error': 'Student id found'}) + + program = get_program_by_name(programname) + if not program: + return jsonify({'Error': 'Incorrect program name'}) + + create_student(student_id, password, name, programname) + return jsonify({'Success!': f"user {student_id} created"}) + +##Add course to course history + +@student_views.route('/student/add_course', methods=['POST']) +def add_course_to_student_route(): + student_id = request.json['student_id'] + course_code = request.json['course_code'] + + if not student_id or not course_code: + return jsonify({'error': 'Missing required fields'}) + + # Check if the student and course exist + student = get_student_by_id(student_id) + course = get_course_by_courseCode(course_code) + + if not student: + return jsonify({'error': 'Student not found'}) + if not course: + return jsonify({'error': 'Course not found'}) + + ##need error checking for whether course already in history + + addCoursetoHistory(student_id, course_code) + return jsonify({'Success!': f"Course {course_code} added to student {student_id}'s course history"}) + + +##Add course plan + +@student_views.route('/student/add_easy_plan', methods=['POST']) +def add_easy_plan(): + student_id = request.json['student_id'] + #Maybe pass in a string to determine which func to use."easy, fast, elec" + # Check if the student exist + student = get_student_by_id(student_id) + + if not student: + return jsonify({'error': 'Student not found'}) + + create_easy_plan(student) + return jsonify({'Success!': f"Easy plan added to student {student_id} "}) From 7b552af1c783b3a3353647ee9e2c1f8d2786a28a Mon Sep 17 00:00:00 2001 From: Ashley Jacob Date: Fri, 6 Oct 2023 21:42:36 -0400 Subject: [PATCH 53/90] created staff views --- App/views/staff.py | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/App/views/staff.py b/App/views/staff.py index 3cd5f0fb1..26bc2b173 100644 --- a/App/views/staff.py +++ b/App/views/staff.py @@ -17,25 +17,21 @@ staff_views = Blueprint('staff_views', __name__, template_folder='../templates') -@staff_views.route('/staff/addProgram////', - methods=['POST']) +@staff_views.route('/staff/addProgram////', methods=['POST']) @login_required def addProgram(name, core, elective, foun): newprogram = create_program(name, core, elective, foun) - return jsonify({'message': f"Program {newprogram['name']} added" - }) if newprogram else 200 + return jsonify({'message': f"Program {newprogram['name']} added"}) if newprogram else 200 -@staff_views.route('/staff/addProgramReq///', - methods=['POST']) +@staff_views.route('/staff/addProgramReq///', methods=['POST']) @login_required def addProgramRequirements(name, code, num): create_programCourse(name, code, num) return jsonify({'message': f"Program added"}) -@staff_views.route('/staff/addNextSemesterCourse/', - methods=['POST']) +@staff_views.route('/staff/addNextSemesterCourse/', methods=['POST']) @login_required def addCourse(courseCode): course = addSemesterCourses(courseCode) From c028a705db4eb55d8d03ec6eddc8ec18c011f0b9 Mon Sep 17 00:00:00 2001 From: Jerrelle Johnson Date: Sat, 7 Oct 2023 01:23:22 -0400 Subject: [PATCH 54/90] addCourseToPlan method works now, but there is a bug in generate --- App/controllers/__init__.py | 2 +- App/controllers/coursePlan.py | 25 +++---- ...eredCourses.py => coursesOfferedPerSem.py} | 0 App/controllers/programCourses.py | 2 +- App/controllers/student.py | 4 +- App/controllers/studentCourseHistory.py | 6 +- App/models/__init__.py | 2 +- App/models/coursePlanCourses.py | 13 ++-- ...eredCourses.py => coursesOfferedPerSem.py} | 4 +- testData/courseData.csv | 35 +++++++++- testData/test.txt | 44 ++++++++++--- testData/test2.txt | 10 ++- wsgi.py | 65 ++++++++++++++++--- 13 files changed, 161 insertions(+), 51 deletions(-) rename App/controllers/{offeredCourses.py => coursesOfferedPerSem.py} (100%) rename App/models/{offeredCourses.py => coursesOfferedPerSem.py} (83%) diff --git a/App/controllers/__init__.py b/App/controllers/__init__.py index 44cf29964..fc0f1af34 100644 --- a/App/controllers/__init__.py +++ b/App/controllers/__init__.py @@ -8,5 +8,5 @@ from .programCourses import * from .studentCourseHistory import * from .coursePlanCourses import * -from .offeredCourses import * +from .coursesOfferedPerSem import * from .coursePlan import * \ No newline at end of file diff --git a/App/controllers/coursePlan.py b/App/controllers/coursePlan.py index 4891a4068..6ef295649 100644 --- a/App/controllers/coursePlan.py +++ b/App/controllers/coursePlan.py @@ -25,19 +25,18 @@ def create_CoursePlan(id): return plan def getCoursePlan(studentid): - return CoursePlan.query.filter_by(CoursePlan.studentId==studentid).first() + return CoursePlan.query.filter_by(studentId=studentid).first() def possessPrereqs(Student, course): preqs = getPrereqCodes(course.courseName) completed = getCompletedCourseCodes(Student.id) - for course in preqs: if course not in completed: return False return True -def addCourse(Student, courseCode): +def addCourseToPlan(Student, courseCode): course = get_course_by_courseCode(courseCode) if course: offered = isCourseOffered(courseCode) @@ -46,11 +45,11 @@ def addCourse(Student, courseCode): if haveAllpreqs: plan = getCoursePlan(Student.id) if plan: - createPlanCourse(plan.planid, courseCode) + createPlanCourse(plan.planId, courseCode) print("Course successfully added to course plan") else: plan = create_CoursePlan(Student.id) - createPlanCourse(plan.planid, courseCode) + createPlanCourse(plan.planId, courseCode) print("Plan successfully created and Course was successfully added to course plan") else: print("Course is not offered") @@ -76,10 +75,11 @@ def getRemainingCourses(completed, required): for r in required: remainingCodes.append(r.code) - - for r in remainingCodes: - if r in completedCodes: - remainingCodes.remove(r) + for a in remainingCodes: + # print(a) + if a in completedCodes: + # print(a) + remainingCodes.remove(a) return remainingCodes @@ -145,7 +145,7 @@ def findAvailable(courseList): for code in courseList: if code in listing: - available.append() + available.append(code) return available #returns an array of course objects @@ -180,6 +180,9 @@ def prioritizeElectives(Student): #merge available, required core and foundation courses courses = courses + findAvailable(getRemainingCore(Student)) + findAvailable(getRemainingFoun(Student)) courses = checkPrereq(Student,courses) + + for c in courses: + print(c) return getTopfive(courses) @@ -218,7 +221,7 @@ def fastestGraduation(Student): credits=credits-c.get_credits(c.courseCode) #get available, required core and foundation courses - courses= courses + findAvailable(getRemainingCore(Student)) + findAvailable(getRemainingFoun(Student)) + # courses= courses + findAvailable(getRemainingCore(Student)) + findAvailable(getRemainingFoun(Student)) courses=checkPrereq(Student,courses) return courses diff --git a/App/controllers/offeredCourses.py b/App/controllers/coursesOfferedPerSem.py similarity index 100% rename from App/controllers/offeredCourses.py rename to App/controllers/coursesOfferedPerSem.py diff --git a/App/controllers/programCourses.py b/App/controllers/programCourses.py index 2fd6e7dbc..ccd90ae3f 100644 --- a/App/controllers/programCourses.py +++ b/App/controllers/programCourses.py @@ -10,7 +10,7 @@ def create_programCourse(programName, code, num): proCourse = ProgramCourses(program.id, code, num) db.session.add(proCourse) db.session.commit() - print("Course successfully added to program") + #print("Course successfully added to program") else: print("Invalid course code") else: diff --git a/App/controllers/student.py b/App/controllers/student.py index 97d9d3ad9..6e27c48f2 100644 --- a/App/controllers/student.py +++ b/App/controllers/student.py @@ -26,7 +26,7 @@ def get_all_students_json(): return students_json def update_student(id, username): - student = get_student(id) + student = get_student_by_id(id) if student: student.username = username db.session.add(student) @@ -34,7 +34,7 @@ def update_student(id, username): return student def enroll_in_programme(student_id, programme_id): - student = get_student(student_id) + student = get_student_by_id(student_id) if student: programme = Program.query.get(programme_id) if programme: diff --git a/App/controllers/studentCourseHistory.py b/App/controllers/studentCourseHistory.py index b7de3461a..bc98e95f5 100644 --- a/App/controllers/studentCourseHistory.py +++ b/App/controllers/studentCourseHistory.py @@ -10,7 +10,7 @@ def addCoursetoHistory(studentid, code): completed = StudentCourseHistory(studentid, code) db.session.add(completed) db.session.commit() - print("Course added successfully") + #print("Course added successfully") else: print("Course doesn't exist") else: @@ -19,10 +19,10 @@ def addCoursetoHistory(studentid, code): def getCompletedCourses(id): - return StudentCourseHistory.query.filter(StudentCourseHistory.studentID == id).all() + return StudentCourseHistory.query.filter_by(studentID=id).all() def getCompletedCourseCodes(id): - completed = getCompletedCourseCodes(id) + completed = getCompletedCourses(id) codes = [] for c in completed: diff --git a/App/models/__init__.py b/App/models/__init__.py index 3e21cfcfe..c8b645206 100644 --- a/App/models/__init__.py +++ b/App/models/__init__.py @@ -3,7 +3,7 @@ from .program import * from .staff import * from .student import * -from .offeredCourses import * +from .coursesOfferedPerSem import * from .programCourses import * from .prerequisites import * from .studentCourseHistory import * diff --git a/App/models/coursePlanCourses.py b/App/models/coursePlanCourses.py index 07959fe66..e4f982a9f 100644 --- a/App/models/coursePlanCourses.py +++ b/App/models/coursePlanCourses.py @@ -9,15 +9,14 @@ class CoursePlanCourses(db.Model): # associated_coursePlan = db.relationship('CoursePlan', back_populates='students', overlaps="coursePlan") # associated_course = db.relationship('Course', back_populates='planIds', overlaps="courses") - def __init__(self, username, password, name, program_id): - self.id = username - self.name = name - self.program_id = program_id + def __init__(self, plan, courseCode): + self.planId = plan + self.code = courseCode + def get_json(self): return{ - 'student_id': self.id, - 'name': self.name, - 'program' : self.program_id + 'Course Plan ID': self.planId, + 'Course': self.code } diff --git a/App/models/offeredCourses.py b/App/models/coursesOfferedPerSem.py similarity index 83% rename from App/models/offeredCourses.py rename to App/models/coursesOfferedPerSem.py index d45d0252a..5e8b3bc1e 100644 --- a/App/models/offeredCourses.py +++ b/App/models/coursesOfferedPerSem.py @@ -7,9 +7,9 @@ class CoursesOfferedPerSem(db.Model): associated_course = db.relationship('Course', back_populates='offered', overlaps="courses") def __init__(self, courseCode): - self.offered = courseCode + self.code = courseCode def get_json(self): return{ - 'Course Code:': self.offered + 'Course Code:': self.code } diff --git a/testData/courseData.csv b/testData/courseData.csv index 22578d705..c43f418c4 100644 --- a/testData/courseData.csv +++ b/testData/courseData.csv @@ -1,6 +1,35 @@ courseCode,courseName,numCredits,rating,preReqs -COMP2611,Data Structures,3,5, +COMP1600,Introduction to Computing Concepts,3,4, +COMP1601,Programming 1,3,1, +COMP1602,Programming 2,3,4, +COMP1603,Programming 3,3,3, +COMP1604,Mathematics for Computing,3,2, +INFO1600, Introduction to Information Technology Concepts,3,1, +INFO1601,Introduction to WWW Programming,3,1, +MATH1115,Fundamental Mathematics for the General Sciences 1,3,1, +COMP2611,Data Structures,3,5,COMP1602 +COMP2601,Computer Architecture,3,5,COMP1600 MATH2250,Industrial Statistics,3,4, -COMP3605,Data Analytics,3,3,"COMP2611,MATH2250" +COMP3605,Introduction to Data Analytics,3,3,"COMP2611,MATH2250" COMP3610,Big Data Analytics,3,5,COMP3605 -COMP3611,small Data Analytics,3,5,COMP3610 \ No newline at end of file +COMP2602,Computer Networks,3,1,COMP1600 +COMP2603,Object-Oriented Programming 1,3,1,COMP1603 +COMP2604,Operating Systems,3,5,COMP1600 +COMP2605,Enterprise Database Systems,3,2,COMP1602 +COMP2606,Software Engineering 1,3,3,COMP1602 +INFO2602,Web Programming and Technologies 1,3,3,INFO1601 +INFO2604,Information Systems Security,3,3,COMP1602 +COMP3601,Design and Analysis of Algorithms,3,5,COMP2611 +COMP3602,Theory of Computing,3,5,COMP1604 +COMP3603,Human-Computer Interaction,3,1,COMP2606 +INFO3604,Project,3,5,"INFO2600,COMP2606" +FOUN1101,Caribbean Civilization,3,1, +FOUN1105,Scientific and Technical Writing,3,1, +FOUN1301,"Law, Governance, Economy and Society",3,1, +COMP3606,Wireless and Mobile Computing,3,3,"COMP2602,INFO2601" +COMP3607,Object-Oriented Programming II,3,2,COMP2603 +COMP3608,Intelligent Systems,3,4,"COMP2611,MATH2250" +COMP3609,Game Programming,3,1,"COMP2603,COMP2606" +COMP3611,Modelling and Simulation,3,5,MATH2250 +COMP3612,Special Topics in Computer,3,5,"COMP2611,COMP2603" +COMP3613,Software Engineering 2,3,5,COMP2606 diff --git a/testData/test.txt b/testData/test.txt index 6a063e40e..61c292068 100644 --- a/testData/test.txt +++ b/testData/test.txt @@ -1,9 +1,35 @@ -Computer_Science_Special -24 -COMP1600, COMP1601, COMP1602, COMP1603, COMP1604, INFO1600, INFO1601, MATH1115 -45 -COMP2601, COMP2602, COMP2603, COMP2604, COMP2605, COMP2606, COMP2611, COMP3601, COMP3602, COMP3603, INFO2602, INFO2604, INFO3604, MATH2250 -15 -COMP3605, COMP3606, COMP3607, COMP3608, COMP3609, COMP36010, COMP3611, COMP3612, COMP3613, INFO2605, INFO3600, INFO3605, INFO3606, INFO3607, INFO3608, INFO3609, INFO3610, INFO3611 -9 -FOUN1101, FOUN1105, FOUN1301 \ No newline at end of file +Computer Science Major +COMP1600,1 +COMP1601,1 +COMP1602,1 +COMP1603,1 +COMP1604,1 +INFO1600,1 +INFO1601,1 +MATH1115,1 +COMP2601,1 +COMP2602,1 +COMP2603,1 +COMP2604,1 +COMP2605,1 +COMP2606,1 +COMP2611,1 +COMP3601,1 +COMP3602,1 +COMP3603,1 +INFO2602,1 +INFO2604,1 +INFO3604,1 +MATH2250,1 +COMP3605,2 +COMP3606,2 +COMP3607,2 +COMP3608,2 +COMP3609,2 +COMP3610,2 +COMP3611,2 +COMP3612,2 +COMP3613,2 +FOUN1101,3 +FOUN1105,3 +FOUN1301,3 \ No newline at end of file diff --git a/testData/test2.txt b/testData/test2.txt index a383db5db..4f5f3bf12 100644 --- a/testData/test2.txt +++ b/testData/test2.txt @@ -1,4 +1,12 @@ -Computer Science (Major) COMP1600 COMP1601 INFO1600 +INFO1601 +MATH2250 +COMP2611 +COMP2602 +COMP2601 +COMP3602 +COMP3603 +COMP2605 +COMP3605 diff --git a/wsgi.py b/wsgi.py index c24ca0973..578afe64b 100644 --- a/wsgi.py +++ b/wsgi.py @@ -16,7 +16,7 @@ get_all_users_json, get_all_users, create_program, - get_core_courses, + get_all_OfferedCodes, get_core_credits, create_course, get_course_by_courseCode, @@ -28,10 +28,17 @@ get_program_by_name, get_all_programCourses, addCoursetoHistory, - getCompletedCourses, + getCompletedCourseCodes, get_allCore, + addCourseToPlan, + get_student_by_id, + generator ) +test1 = ["COMP1600", "COMP1601", "COMP1602", "COMP1603", "COMP1604", "MATH1115", "INFO1600", "INFO1601"] + +file_path = "/Users/jerrellejohnson/Desktop/softEng2/flaskmvc/testData/test.txt" + # This commands file allow you to create convenient CLI commands for testing controllers @@ -48,14 +55,30 @@ def initialize(): create_course('testData/courseData.csv') create_program("Computer Science Major", 69, 15, 9) create_student(816, "boo", "testing", "Computer Science Major") + + for c in test1: + addCoursetoHistory(816, c) + print('Student course history updated') + + with open(file_path, 'r') as file: + for i, line in enumerate(file): + line = line.strip() + if i ==0: + programName = line + else: + course = line.split(',') + create_programCourse(programName, course[0],int(course[1])) - print('database intialized') + file_path1='/Users/jerrellejohnson/Desktop/softEng2/flaskmvc/testData/test2.txt' + with open(file_path1, 'r') as file: + for i, line in enumerate(file): + line = line.strip() + addSemesterCourses(line) - # with open('/Users/jerrellejohnson/Desktop/softEng2/flaskmvc/testData/courseData.csv', 'r') as csvfile: - # csv_reader = csv.reader(csvfile) - - # for row in csv_reader: - # print(row) # Display the row + + + + print('database intialized') ''' User Commands @@ -113,10 +136,21 @@ def addCourse(student_id, code): @student_cli.command("getCompleted", help="Get all of a student completed courses") @click.argument("student_id", type=str) def completed(student_id): - comp = getCompletedCourses(student_id) + comp = getCompletedCourseCodes(student_id) for c in comp: - print(f'{c.code}') + print(f'{c}') + +@student_cli.command("addCourseToPlan", help="Adds a course to a student's course plan") +def courseToPlan(): + student = get_student_by_id("816") + addCourseToPlan(student, "COMP2611") +@student_cli.command("generate", help="Generates a course plan based on what they request") +def generatePlan(): + student = get_student_by_id("816") + courses = generator(student, "electives") + # for c in courses: + # print(c) app.cli.add_command(student_cli) @@ -239,6 +273,17 @@ def add_course(code): course = addSemesterCourses(code) print(f'Course Name: {course.courseName}') if course else print(f'error') +@course.command('getNextSemCourses', help='Get all the courses offered next semester') +def allSemCourses(): + courses = get_all_OfferedCodes() + + if courses: + for c in courses: + print({c}) + else: + print("empty") + + app.cli.add_command(course) ########################################################### From 7ed10851fb2124f91e7d8b4608e4aebb83912370 Mon Sep 17 00:00:00 2001 From: Jerrelle Johnson Date: Sat, 7 Oct 2023 14:47:07 -0400 Subject: [PATCH 55/90] all controllers done --- App/controllers/coursePlan.py | 135 +++++++++++++++++---------- App/controllers/coursePlanCourses.py | 2 +- App/controllers/courses.py | 11 +++ App/controllers/programCourses.py | 30 +++++- testData/courseData.csv | 1 + testData/test.txt | 3 +- testData/test2.txt | 1 + wsgi.py | 11 ++- 8 files changed, 136 insertions(+), 58 deletions(-) diff --git a/App/controllers/coursePlan.py b/App/controllers/coursePlan.py index 6ef295649..fe123573d 100644 --- a/App/controllers/coursePlan.py +++ b/App/controllers/coursePlan.py @@ -14,7 +14,10 @@ getCompletedCourseCodes, convertToList, get_all_OfferedCodes, - isCourseOffered + isCourseOffered, + programCourses_SortedbyRating, + programCourses_SortedbyHighestCredits, + get_all_courses_by_planid ) @@ -74,14 +77,14 @@ def getRemainingCourses(completed, required): remainingCodes = [] for r in required: remainingCodes.append(r.code) + - for a in remainingCodes: - # print(a) - if a in completedCodes: - # print(a) - remainingCodes.remove(a) + notCompleted = remainingCodes.copy() + for a in completedCodes: + if a in notCompleted: + notCompleted.remove(a) - return remainingCodes + return notCompleted def getRemainingCore(Student): @@ -134,8 +137,7 @@ def remElecCredits(Student): if code in completedcourses: c = get_course_by_courseCode(code) # Get course if c: - requiredCreds = requiredCreds - c.credits # Subtract credits - + requiredCreds = requiredCreds - c.credits # Subtract credits return requiredCreds @@ -147,7 +149,7 @@ def findAvailable(courseList): if code in listing: available.append(code) - return available #returns an array of course objects + return available #returns an array of course codes def checkPrereq(Student, recommnded): @@ -163,8 +165,6 @@ def checkPrereq(Student, recommnded): def getTopfive(list): return list[:5] - - def prioritizeElectives(Student): #get available electives electives=findAvailable(getRemainingElec(Student)) @@ -179,61 +179,96 @@ def prioritizeElectives(Student): #merge available, required core and foundation courses courses = courses + findAvailable(getRemainingCore(Student)) + findAvailable(getRemainingFoun(Student)) - courses = checkPrereq(Student,courses) - for c in courses: - print(c) - + courses = checkPrereq(Student,courses) return getTopfive(courses) +def removeCoursesFromList(list1,list2): + newlist = list2.copy() + for a in list1: + if a in newlist: + newlist.remove(a) + return newlist + + def easyCourses(Student): - #get electives, order by difficulty - electives=findAvailable(getRemainingElec(Student)) - electives.sort(key=lambda x:getattr(x, "rating", 0)) - - #select courses to satisfy the programme's credit requirement - credits=remElecCredits(Student) - courses=[] - for c in electives: - if credits>0: - courses.append(c) - credits=credits-c.get_credits(c.courseCode) + program = get_program_by_id(Student.program_id) + completed = getCompletedCourseCodes(Student.id) + codesSortedbyRating = programCourses_SortedbyRating(Student.program_id) - #merge available core and foundation courses and sort by difficulty - courses= courses + findAvailable(getRemainingCore(Student)) + findAvailable(getRemainingFoun(Student)) - courses.sort(key=lambda x:getattr(x, "rating", 0)) - courses=checkPrereq(Student,courses) - return courses + coursesToDo = removeCoursesFromList(completed, codesSortedbyRating) + + elecCredits = remElecCredits(Student) + + if elecCredits == 0: + allElectives = convertToList(get_allElectives(program.name)) + coursesToDo = removeCoursesFromList(allElectives, coursesToDo) + + coursesToDo = findAvailable(coursesToDo) + + ableToDo = checkPrereq(Student, coursesToDo) + # for a in ableToDo: + # print(a) + + return getTopfive(ableToDo) def fastestGraduation(Student): - #get electives, order by credits (descending order) - electives=findAvailable(getRemainingElec(Student)) - electives.sort(key=lambda x:getattr(x, "credits", 0), reverse=True) + program = get_program_by_id(Student.program_id) + sortedCourses = programCourses_SortedbyHighestCredits(Student.program_id) + completed = getCompletedCourseCodes(Student.id) - #select courses to satisfy the programme's credit requirement - credits=remElecCredits(Student) - courses=[] - for c in electives: - if credits>0: - courses.append(c) - credits=credits-c.get_credits(c.courseCode) + coursesToDo = removeCoursesFromList(completed, sortedCourses) - #get available, required core and foundation courses - # courses= courses + findAvailable(getRemainingCore(Student)) + findAvailable(getRemainingFoun(Student)) - courses=checkPrereq(Student,courses) - return courses + elecCredits = remElecCredits(Student) + + if elecCredits == 0: + allElectives = convertToList(get_allElectives(program.name)) + coursesToDo = removeCoursesFromList(allElectives, coursesToDo) + + coursesToDo = findAvailable(coursesToDo) + ableToDo = checkPrereq(Student, coursesToDo) -def generator(Student, command): + return getTopfive(ableToDo) + +def commandCall(Student, command): courses = [] if command == "electives": - plan = create_CoursePlan(Student.id) courses = prioritizeElectives(Student) + + elif command == "easy": + courses = easyCourses(Student) + + elif command == "fastest": + courses = fastestGraduation(Student) + + else: + print("Invalid command") + + return courses - for c in courses: - createPlanCourse(plan.planId, c) +def generator(Student, command): + courses = [] + + plan = getCoursePlan(Student.id) + + if plan is None: + plan = plan = create_CoursePlan(Student.id) + + + courses = commandCall(Student, command) + + existingPlanCourses = get_all_courses_by_planid(plan.planId) + + planCourses = [] + for q in existingPlanCourses: + planCourses.append(q.code) + + for c in courses: + if c not in planCourses: + createPlanCourse(plan.planId, c) return courses \ No newline at end of file diff --git a/App/controllers/coursePlanCourses.py b/App/controllers/coursePlanCourses.py index b4d5d0635..b3c5bc8b1 100644 --- a/App/controllers/coursePlanCourses.py +++ b/App/controllers/coursePlanCourses.py @@ -13,7 +13,7 @@ def getCourseFromCoursePlan(planid, coursecode): ).first() def get_all_courses_by_planid(id): - return CoursePlanCourses.query.filter_by(CoursePlanCourses.planId == id).all() + return CoursePlanCourses.query.filter_by(planId=id).all() def deleteCourseFromCoursePlan(planid, coursecode): course = getCourseFromCoursePlan(planid, coursecode) diff --git a/App/controllers/courses.py b/App/controllers/courses.py index e9b5ce03b..2a8d3605a 100644 --- a/App/controllers/courses.py +++ b/App/controllers/courses.py @@ -38,6 +38,15 @@ def create_course(file_path): def get_course_by_courseCode(code): return Course.query.filter_by(courseCode=code).first() +def courses_Sorted_byRating(): + courses = Course.query.order_by(Course.rating.asc()).all() + codes = [] + + for c in courses: + codes.append(c.courseCode) + + return codes + def get_prerequisites(code): course = get_course_by_courseCode(code) prereqs = get_all_prerequisites(course.courseName) @@ -51,3 +60,5 @@ def get_ratings(code): course = get_course_by_courseCode(code) return course.rating if course else 0 + + diff --git a/App/controllers/programCourses.py b/App/controllers/programCourses.py index ccd90ae3f..0da6a948f 100644 --- a/App/controllers/programCourses.py +++ b/App/controllers/programCourses.py @@ -1,5 +1,5 @@ from App.models import ProgramCourses, Program, Course -from App.controllers import (get_program_by_name, get_course_by_courseCode) +from App.controllers import (get_program_by_name, get_program_by_id, get_course_by_courseCode) from App.database import db def create_programCourse(programName, code, num): @@ -52,3 +52,31 @@ def convertToList(list): return codes +def programCourses_SortedbyRating(programid): + program = get_program_by_id(programid) + programCourses = get_all_programCourses(program.name) + + sorted_courses = {1: [], 2: [], 3: [], 4: [], 5: []} + + for p in programCourses: + course = get_course_by_courseCode(p.code) + sorted_courses[course.rating].append(course.courseCode) + + sorted_courses_list = [course for rating_courses in sorted_courses.values() for course in rating_courses] + + return sorted_courses_list + +def programCourses_SortedbyHighestCredits(programid): + program = get_program_by_id(programid) + programCourses = get_all_programCourses(program.name) + + highTolow = [] + + for p in programCourses: + course = get_course_by_courseCode(p.code) + if course.credits > 3: + highTolow.insert(0,course.courseCode) + else: + highTolow.append(course.courseCode) + + return highTolow diff --git a/testData/courseData.csv b/testData/courseData.csv index c43f418c4..9ef96328e 100644 --- a/testData/courseData.csv +++ b/testData/courseData.csv @@ -33,3 +33,4 @@ COMP3609,Game Programming,3,1,"COMP2603,COMP2606" COMP3611,Modelling and Simulation,3,5,MATH2250 COMP3612,Special Topics in Computer,3,5,"COMP2611,COMP2603" COMP3613,Software Engineering 2,3,5,COMP2606 +INFO2606, Internship, 6, 1, diff --git a/testData/test.txt b/testData/test.txt index 61c292068..427440bff 100644 --- a/testData/test.txt +++ b/testData/test.txt @@ -32,4 +32,5 @@ COMP3612,2 COMP3613,2 FOUN1101,3 FOUN1105,3 -FOUN1301,3 \ No newline at end of file +FOUN1301,3 +INFO2606,2 \ No newline at end of file diff --git a/testData/test2.txt b/testData/test2.txt index 4f5f3bf12..32a5342e0 100644 --- a/testData/test2.txt +++ b/testData/test2.txt @@ -10,3 +10,4 @@ COMP3602 COMP3603 COMP2605 COMP3605 +INFO2606 \ No newline at end of file diff --git a/wsgi.py b/wsgi.py index 578afe64b..df2165f47 100644 --- a/wsgi.py +++ b/wsgi.py @@ -35,7 +35,7 @@ generator ) -test1 = ["COMP1600", "COMP1601", "COMP1602", "COMP1603", "COMP1604", "MATH1115", "INFO1600", "INFO1601"] +test1 = ["COMP1600", "COMP1601", "COMP1602", "COMP1603", "COMP1604", "MATH1115", "INFO1600", "INFO1601", "FOUN1101", "FOUN1105", "FOUN1301", "COMP3605", "COMP3606", "COMP3607", "COMP3608",] file_path = "/Users/jerrellejohnson/Desktop/softEng2/flaskmvc/testData/test.txt" @@ -146,11 +146,12 @@ def courseToPlan(): addCourseToPlan(student, "COMP2611") @student_cli.command("generate", help="Generates a course plan based on what they request") -def generatePlan(): +@click.argument("command", type=str) +def generatePlan(command): student = get_student_by_id("816") - courses = generator(student, "electives") - # for c in courses: - # print(c) + courses = generator(student, command) + for c in courses: + print(c) app.cli.add_command(student_cli) From 2a8f64db6086ba91ef5d36443fa115d95dc60e95 Mon Sep 17 00:00:00 2001 From: Ashley Jacob Date: Sat, 7 Oct 2023 17:53:08 -0400 Subject: [PATCH 56/90] all staff views are functional --- App/controllers/program.py | 3 +- App/controllers/programCourses.py | 6 +-- App/controllers/staff.py | 7 +++ App/models/program.py | 1 - App/views/staff.py | 77 ++++++++++++++++++++++++++++--- requirements.txt | 3 +- wsgi.py | 13 ++++-- 7 files changed, 91 insertions(+), 19 deletions(-) diff --git a/App/controllers/program.py b/App/controllers/program.py index 7e080b3d1..4f2cdc29f 100644 --- a/App/controllers/program.py +++ b/App/controllers/program.py @@ -53,12 +53,11 @@ def get_foun_courses(programName): return courses if program else [] def get_all_courses(programName): - level1_courses = get_level1_courses(programName) core_courses = get_core_courses(programName) elective_courses = get_elective_courses(programName) foun_courses = get_foun_courses(programName) - all = level1_courses + core_courses + elective_courses + foun_courses + all = core_courses + elective_courses + foun_courses return all diff --git a/App/controllers/programCourses.py b/App/controllers/programCourses.py index ccd90ae3f..ebde2c1f9 100644 --- a/App/controllers/programCourses.py +++ b/App/controllers/programCourses.py @@ -10,11 +10,11 @@ def create_programCourse(programName, code, num): proCourse = ProgramCourses(program.id, code, num) db.session.add(proCourse) db.session.commit() - #print("Course successfully added to program") + return "Course successfully added to program" else: - print("Invalid course code") + return "Invalid course code" else: - print("Invalid program name") + return "Invalid program name" def get_all_programCourses(programName): program = get_program_by_name(programName) diff --git a/App/controllers/staff.py b/App/controllers/staff.py index 22d4506b9..b233c1200 100644 --- a/App/controllers/staff.py +++ b/App/controllers/staff.py @@ -8,6 +8,13 @@ def create_staff(password, staff_id, name): db.session.commit() return new_staff + +def verify_staff(username): + staff=Staff.query.filter_by(id=username).first() + if staff: + return True + return False + # def add_program(self, program_name, description): # try: # new_program = Program(name=program_name, description=description) diff --git a/App/models/program.py b/App/models/program.py index 1f2e97db9..322983bbe 100644 --- a/App/models/program.py +++ b/App/models/program.py @@ -20,7 +20,6 @@ def get_json(self): return{ 'Program ID:': self.id, 'Program Name: ': self.name, - 'Level I Credits: ': self.level1_credits, 'Core Credits: ': self.core_credits, 'Elective Credits ': self.elective_credits, 'Foundation Credits: ': self.foun_credits, diff --git a/App/views/staff.py b/App/views/staff.py index 26bc2b173..f046ea19b 100644 --- a/App/views/staff.py +++ b/App/views/staff.py @@ -1,6 +1,7 @@ from flask import Blueprint, render_template, jsonify, request, send_from_directory, flash, redirect, url_for from flask_jwt_extended import jwt_required, current_user as jwt_current_user from flask_login import current_user, login_required +from App.models import Program from.index import index_views @@ -12,27 +13,89 @@ get_all_users, get_all_users_json, jwt_required, - addSemesterCourses + addSemesterCourses, + get_all_OfferedCodes, + get_all_programCourses, + verify_staff ) staff_views = Blueprint('staff_views', __name__, template_folder='../templates') -@staff_views.route('/staff/addProgram////', methods=['POST']) +@staff_views.route('/staff/offeredCourses', methods=['GET']) +@login_required +def getOfferedCourses(): + username=current_user.username + if not verify_staff(username): #verify that the user is staff + return jsonify({'message': 'You are unauthorized to perform this action. Please login with Staff credentials.'}) + + listing=get_all_OfferedCodes() + return jsonify(listing) + +@staff_views.route('/staff/addProgram////', methods=['POST']) @login_required def addProgram(name, core, elective, foun): + username=current_user.username + if not verify_staff(username): #verify that the user is staff + return jsonify({'message': 'You are unauthorized to perform this action. Please login with Staff credentials.'}) + + #get all programs and check to see if it already exists + programs=Program.query.all() + programNames=[] + for p in programs: + programNames.append(p.name) + if name in programNames: + return jsonify({'message': 'Program already exists'}) + newprogram = create_program(name, core, elective, foun) - return jsonify({'message': f"Program {newprogram['name']} added"}) if newprogram else 200 + return jsonify({'message': f"Program {newprogram.name} added"}) if newprogram else 200 -@staff_views.route('/staff/addProgramReq///', methods=['POST']) +@staff_views.route('/staff/addProgramReq///', methods=['POST']) @login_required def addProgramRequirements(name, code, num): - create_programCourse(name, code, num) - return jsonify({'message': f"Program added"}) + username=current_user.username + if not verify_staff(username): #verify that the user is staff + return jsonify({'message': 'You are unauthorized to perform this action. Please login with Staff credentials.'}) + + #verify program existance + programs=Program.query.all() + programNames=[] + for p in programs: + programNames.append(p.name) + if name not in programNames: + return jsonify({'message': 'Program does not exist'}) + + #verify that the course isn't already a requirement + courseList=get_all_programCourses(name) + courseCodeList=[] + for c in courseList: + courseCodeList.append(c.code) + + code=code.replace(" ","").upper() + if code in courseCodeList: + return jsonify({'message': f'{code} is already a requirement for {name}'}) + + #verify that the course type is valid; Core (1) Elective (2) Foundation (3) + if num<1 or num>3: + return jsonify({'message': 'Invalid course type. Core (1) Elective (2) Foundation (3)'}) + + response=create_programCourse(name, code, num) + return jsonify({'message': response}) @staff_views.route('/staff/addNextSemesterCourse/', methods=['POST']) @login_required def addCourse(courseCode): + username=current_user.username + if not verify_staff(username): #verify that the user is staff + return jsonify({'message': 'You are unauthorized to perform this action. Please login with Staff credentials.'}) + + offeredCourses=get_all_OfferedCodes() + courseCode=courseCode.replace(" ","").upper() #ensure consistent course code format + + #check if course code is already in the list of offered courses + if courseCode in offeredCourses: + return jsonify({'message': f"{courseCode} already exists in the list of offered courses"}) + course = addSemesterCourses(courseCode) - return jsonify({'message': f"Course {course['courseName']} added"}) if course else 200 \ No newline at end of file + return jsonify({'message': f"Course {course.courseCode} - {course.courseName} added"}) if course else 200 \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index a6ad05eeb..ae8e09c0f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -13,4 +13,5 @@ psycopg2-binary==2.9.3 pytest==7.0.1 python-dotenv==0.21.1 Flask-JWT-Extended==4.4.4 -Flask-Migrate==3.1.0 \ No newline at end of file +Flask-Migrate==3.1.0 +Werkzeug==2.2.2 \ No newline at end of file diff --git a/wsgi.py b/wsgi.py index 7a818dd56..2ba72650b 100644 --- a/wsgi.py +++ b/wsgi.py @@ -39,7 +39,7 @@ test1 = ["COMP1600", "COMP1601", "COMP1602", "COMP1603", "COMP1604", "MATH1115", "INFO1600", "INFO1601"] -file_path = "/Users/jerrellejohnson/Desktop/softEng2/flaskmvc/testData/test.txt" +file_path = "testData/test.txt" # This commands file allow you to create convenient CLI commands for testing controllers @@ -57,7 +57,8 @@ def initialize(): create_course('testData/courseData.csv') create_program("Computer Science Major", 69, 15, 9) create_student(816, "boo", "testing", "Computer Science Major") - + create_staff("adminpass","999", "admin") + for c in test1: addCoursetoHistory(816, c) print('Student course history updated') @@ -71,7 +72,7 @@ def initialize(): course = line.split(',') create_programCourse(programName, course[0],int(course[1])) - file_path1='/Users/jerrellejohnson/Desktop/softEng2/flaskmvc/testData/test2.txt' + file_path1='testData/test2.txt' with open(file_path1, 'r') as file: for i, line in enumerate(file): line = line.strip() @@ -183,13 +184,15 @@ def create_program_command(name,core,elective,foun): @click.argument("code", type=str) @click.argument("num", type=int) def add_program_requirements(name,code,num): - create_programCourse(name,code,num) + response=create_programCourse(name, code, num) + print(response) @staff_cli.command("addofferedcourse",help='testing add courses offered feature') @click.argument("code", type=str) def add_offered_course(code): course=addSemesterCourses(code) - print(f'Course details: {course}') + if course: + print(f'Course details: {course}') app.cli.add_command(staff_cli) From 1a324dc8140d0a17dbbbc7a800453a6836c3ae1e Mon Sep 17 00:00:00 2001 From: Ashley Jacob Date: Sat, 7 Oct 2023 18:50:17 -0400 Subject: [PATCH 57/90] updated staff urls --- App/views/staff.py | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/App/views/staff.py b/App/views/staff.py index f046ea19b..394683be9 100644 --- a/App/views/staff.py +++ b/App/views/staff.py @@ -31,9 +31,15 @@ def getOfferedCourses(): listing=get_all_OfferedCodes() return jsonify(listing) -@staff_views.route('/staff/addProgram////', methods=['POST']) +@staff_views.route('/staff/program', methods=['POST']) @login_required -def addProgram(name, core, elective, foun): +def addProgram(): + data=request.json + name=data['name'] + core=data['core'] + elective=data['elective'] + foun=data['foun'] + username=current_user.username if not verify_staff(username): #verify that the user is staff return jsonify({'message': 'You are unauthorized to perform this action. Please login with Staff credentials.'}) @@ -45,14 +51,28 @@ def addProgram(name, core, elective, foun): programNames.append(p.name) if name in programNames: return jsonify({'message': 'Program already exists'}) + + if not isinstance(core, int): + return jsonify({"error": "'core' must be an integer"}), 400 + + if not isinstance(elective, int): + return jsonify({"error": "'elective' must be an integer"}), 400 + + if not isinstance(foun, int): + return jsonify({"error": "'foun' must be an integer"}), 400 newprogram = create_program(name, core, elective, foun) return jsonify({'message': f"Program {newprogram.name} added"}) if newprogram else 200 -@staff_views.route('/staff/addProgramReq///', methods=['POST']) +@staff_views.route('/programRequirement', methods=['POST']) @login_required -def addProgramRequirements(name, code, num): +def addProgramRequirements(): + data=request.json + name=data['name'] + code=data['code'] + num=data['type'] + username=current_user.username if not verify_staff(username): #verify that the user is staff return jsonify({'message': 'You are unauthorized to perform this action. Please login with Staff credentials.'}) @@ -83,9 +103,12 @@ def addProgramRequirements(name, code, num): return jsonify({'message': response}) -@staff_views.route('/staff/addNextSemesterCourse/', methods=['POST']) +@staff_views.route('/staff/addOfferedCourse', methods=['POST']) @login_required -def addCourse(courseCode): +def addCourse(): + data=request.json + courseCode=data['code'] + username=current_user.username if not verify_staff(username): #verify that the user is staff return jsonify({'message': 'You are unauthorized to perform this action. Please login with Staff credentials.'}) From 70da3d6a38d344907b03f987936176a7e9505585 Mon Sep 17 00:00:00 2001 From: Ashley Jacob Date: Sun, 8 Oct 2023 11:57:20 -0400 Subject: [PATCH 58/90] updated status codes and error responses --- App/views/staff.py | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/App/views/staff.py b/App/views/staff.py index 394683be9..6f9c771cb 100644 --- a/App/views/staff.py +++ b/App/views/staff.py @@ -26,10 +26,10 @@ def getOfferedCourses(): username=current_user.username if not verify_staff(username): #verify that the user is staff - return jsonify({'message': 'You are unauthorized to perform this action. Please login with Staff credentials.'}) + return jsonify({'message': 'You are unauthorized to perform this action. Please login with Staff credentials.'}), 401 listing=get_all_OfferedCodes() - return jsonify(listing) + return jsonify(listing), 200 @staff_views.route('/staff/program', methods=['POST']) @login_required @@ -42,7 +42,7 @@ def addProgram(): username=current_user.username if not verify_staff(username): #verify that the user is staff - return jsonify({'message': 'You are unauthorized to perform this action. Please login with Staff credentials.'}) + return jsonify({'message': 'You are unauthorized to perform this action. Please login with Staff credentials.'}), 401 #get all programs and check to see if it already exists programs=Program.query.all() @@ -50,7 +50,7 @@ def addProgram(): for p in programs: programNames.append(p.name) if name in programNames: - return jsonify({'message': 'Program already exists'}) + return jsonify({'message': 'Program already exists'}), 400 if not isinstance(core, int): return jsonify({"error": "'core' must be an integer"}), 400 @@ -62,7 +62,10 @@ def addProgram(): return jsonify({"error": "'foun' must be an integer"}), 400 newprogram = create_program(name, core, elective, foun) - return jsonify({'message': f"Program {newprogram.name} added"}) if newprogram else 200 + if newprogram: + return jsonify({'message': f"Program {newprogram.name} added"}), 200 + else: + return jsonify({'message': "Program creation unsucessful"}), 400 @staff_views.route('/programRequirement', methods=['POST']) @@ -75,7 +78,7 @@ def addProgramRequirements(): username=current_user.username if not verify_staff(username): #verify that the user is staff - return jsonify({'message': 'You are unauthorized to perform this action. Please login with Staff credentials.'}) + return jsonify({'message': 'You are unauthorized to perform this action. Please login with Staff credentials.'}), 401 #verify program existance programs=Program.query.all() @@ -83,7 +86,7 @@ def addProgramRequirements(): for p in programs: programNames.append(p.name) if name not in programNames: - return jsonify({'message': 'Program does not exist'}) + return jsonify({'message': 'Program does not exist'}), 400 #verify that the course isn't already a requirement courseList=get_all_programCourses(name) @@ -93,14 +96,14 @@ def addProgramRequirements(): code=code.replace(" ","").upper() if code in courseCodeList: - return jsonify({'message': f'{code} is already a requirement for {name}'}) + return jsonify({'message': f'{code} is already a requirement for {name}'}), 400 #verify that the course type is valid; Core (1) Elective (2) Foundation (3) if num<1 or num>3: - return jsonify({'message': 'Invalid course type. Core (1) Elective (2) Foundation (3)'}) + return jsonify({'message': 'Invalid course type. Core (1) Elective (2) Foundation (3)'}), 400 response=create_programCourse(name, code, num) - return jsonify({'message': response}) + return jsonify({'message': response}), 200 @staff_views.route('/staff/addOfferedCourse', methods=['POST']) @@ -111,14 +114,17 @@ def addCourse(): username=current_user.username if not verify_staff(username): #verify that the user is staff - return jsonify({'message': 'You are unauthorized to perform this action. Please login with Staff credentials.'}) + return jsonify({'message': 'You are unauthorized to perform this action. Please login with Staff credentials.'}), 401 offeredCourses=get_all_OfferedCodes() courseCode=courseCode.replace(" ","").upper() #ensure consistent course code format #check if course code is already in the list of offered courses if courseCode in offeredCourses: - return jsonify({'message': f"{courseCode} already exists in the list of offered courses"}) + return jsonify({'message': f"{courseCode} already exists in the list of offered courses"}), 400 course = addSemesterCourses(courseCode) - return jsonify({'message': f"Course {course.courseCode} - {course.courseName} added"}) if course else 200 \ No newline at end of file + if course: + return jsonify({'message': f"Course {courseCode} added"}), 200 + else: + return jsonify({'message': "Course addition unsucessful"}), 400 \ No newline at end of file From a21975b7c09f3c885f6929aeb1d3515d89eca231 Mon Sep 17 00:00:00 2001 From: Kyle-McIntosh <78955773+Kyle-McIntosh@users.noreply.github.com> Date: Sun, 8 Oct 2023 16:44:27 +0000 Subject: [PATCH 59/90] Updated student views --- App/views/student.py | 41 +++++++++++++++++++++++++++-------------- wsgi.py | 15 ++++++--------- 2 files changed, 33 insertions(+), 23 deletions(-) diff --git a/App/views/student.py b/App/views/student.py index 326c6f645..131c2a2f5 100644 --- a/App/views/student.py +++ b/App/views/student.py @@ -14,23 +14,27 @@ get_student_by_id, get_course_by_courseCode, addCoursetoHistory, - create_easy_plan, + getCompletedCourseCodes, + generator ) student_views = Blueprint('student_views', __name__, template_folder='../templates') ##Create student @student_views.route('/student', methods=['POST']) -@jwt_required() +#@jwt_required() def create_student_route(): student_id = request.json['student_id'] password = request.json['password'] name = request.json['name'] programname = request.json['programname'] + if not all([student_id, password, name, programname]): + return jsonify({'Error': 'Missing required fields. Please provide student id, password, name, and program name.'}) + student = get_student_by_id(student_id) if student: - return jsonify({'error': 'Student id found'}) + return jsonify({'Error': 'Student id found'}) program = get_program_by_name(programname) if not program: @@ -47,18 +51,22 @@ def add_course_to_student_route(): course_code = request.json['course_code'] if not student_id or not course_code: - return jsonify({'error': 'Missing required fields'}) + return jsonify({'Error': 'Missing required fields'}) # Check if the student and course exist student = get_student_by_id(student_id) course = get_course_by_courseCode(course_code) if not student: - return jsonify({'error': 'Student not found'}) + return jsonify({'Error': 'Student not found'}) if not course: - return jsonify({'error': 'Course not found'}) + return jsonify({'Error': 'Course not found'}) - ##need error checking for whether course already in history + + # Check if the course is already in the student's completed courses + completed_courses = getCompletedCourseCodes(student_id) + if course_code in completed_courses: + return jsonify({'Error': 'Course already completed'}) addCoursetoHistory(student_id, course_code) return jsonify({'Success!': f"Course {course_code} added to student {student_id}'s course history"}) @@ -66,15 +74,20 @@ def add_course_to_student_route(): ##Add course plan -@student_views.route('/student/add_easy_plan', methods=['POST']) -def add_easy_plan(): +@student_views.route('/student/create_student_plan', methods=['POST']) +def create_student_plan_route(): student_id = request.json['student_id'] - #Maybe pass in a string to determine which func to use."easy, fast, elec" - # Check if the student exist + command = request.json['command'] + student = get_student_by_id(student_id) if not student: - return jsonify({'error': 'Student not found'}) + return jsonify({'Error': 'Student not found'}) - create_easy_plan(student) - return jsonify({'Success!': f"Easy plan added to student {student_id} "}) + valid_command = ["electives", "easy", "fastest"] + + if command not in valid_command: + return jsonify("Invalid command. Please enter 'electives', 'easy', or 'fastest'.") + + courses = generator(student, command) + return jsonify({'Success!': f"{command} plan added to student {student_id} ", "courses" : courses}) diff --git a/wsgi.py b/wsgi.py index fa1858332..e11194a7a 100644 --- a/wsgi.py +++ b/wsgi.py @@ -37,7 +37,8 @@ test1 = ["COMP1600", "COMP1601", "COMP1602", "COMP1603", "COMP1604", "MATH1115", "INFO1600", "INFO1601", "FOUN1101", "FOUN1105", "FOUN1301", "COMP3605", "COMP3606", "COMP3607", "COMP3608",] -file_path = "/Users/jerrellejohnson/Desktop/softEng2/flaskmvc/testData/test.txt" +##Change the file path +file_path = "/workspaces/flaskmvc/testData/test.txt" # This commands file allow you to create convenient CLI commands for testing controllers @@ -69,7 +70,7 @@ def initialize(): course = line.split(',') create_programCourse(programName, course[0],int(course[1])) - file_path1='/Users/jerrellejohnson/Desktop/softEng2/flaskmvc/testData/test2.txt' + file_path1='/workspaces/flaskmvc/testData/test2.txt' with open(file_path1, 'r') as file: for i, line in enumerate(file): line = line.strip() @@ -146,9 +147,10 @@ def courseToPlan(): addCourseToPlan(student, "COMP2611") @student_cli.command("generate", help="Generates a course plan based on what they request") +@click.argument("student_id", type=str) @click.argument("command", type=str) -def generatePlan(command): - student = get_student_by_id("816") +def generatePlan(student_id, command): + student = get_student_by_id(student_id) courses = generator(student, command) for c in courses: print(c) @@ -306,11 +308,6 @@ def allSemCourses(): # Define the course plan create command -@coursePlan.command("create_easy", help="Creates a course plan") -@click.argument("student_id") -def create_plan(student_id): - create_easy_plan(student_id) - print(f"Course plan created for {student_id}.") app.cli.add_command(coursePlan) \ No newline at end of file From c4ba4edc6ab12ce52497b85970f8ce44bfec923a Mon Sep 17 00:00:00 2001 From: Jerrelle Johnson Date: Sun, 8 Oct 2023 12:52:46 -0400 Subject: [PATCH 60/90] updates to programcourses and coursesoffered model --- App/controllers/programCourses.py | 1 + App/models/coursesOfferedPerSem.py | 1 + 2 files changed, 2 insertions(+) diff --git a/App/controllers/programCourses.py b/App/controllers/programCourses.py index 0da6a948f..32bd9908b 100644 --- a/App/controllers/programCourses.py +++ b/App/controllers/programCourses.py @@ -10,6 +10,7 @@ def create_programCourse(programName, code, num): proCourse = ProgramCourses(program.id, code, num) db.session.add(proCourse) db.session.commit() + return proCourse #print("Course successfully added to program") else: print("Invalid course code") diff --git a/App/models/coursesOfferedPerSem.py b/App/models/coursesOfferedPerSem.py index 5e8b3bc1e..b3dcb1f5d 100644 --- a/App/models/coursesOfferedPerSem.py +++ b/App/models/coursesOfferedPerSem.py @@ -11,5 +11,6 @@ def __init__(self, courseCode): def get_json(self): return{ + 'ID:': self.id, 'Course Code:': self.code } From 08408a35dbf4e4d40222634250f544f9c607d415 Mon Sep 17 00:00:00 2001 From: Jerrelle Johnson Date: Sun, 8 Oct 2023 12:58:36 -0400 Subject: [PATCH 61/90] corrected file paths in wsgi --- wsgi.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wsgi.py b/wsgi.py index e11194a7a..d25434500 100644 --- a/wsgi.py +++ b/wsgi.py @@ -38,7 +38,7 @@ test1 = ["COMP1600", "COMP1601", "COMP1602", "COMP1603", "COMP1604", "MATH1115", "INFO1600", "INFO1601", "FOUN1101", "FOUN1105", "FOUN1301", "COMP3605", "COMP3606", "COMP3607", "COMP3608",] ##Change the file path -file_path = "/workspaces/flaskmvc/testData/test.txt" +file_path = "testData/test.txt" # This commands file allow you to create convenient CLI commands for testing controllers @@ -70,7 +70,7 @@ def initialize(): course = line.split(',') create_programCourse(programName, course[0],int(course[1])) - file_path1='/workspaces/flaskmvc/testData/test2.txt' + file_path1='testData/test2.txt' with open(file_path1, 'r') as file: for i, line in enumerate(file): line = line.strip() From 6366744003d370a3d0d19d13e8918ff9df4de608 Mon Sep 17 00:00:00 2001 From: Kyle-McIntosh <78955773+Kyle-McIntosh@users.noreply.github.com> Date: Sun, 8 Oct 2023 23:36:09 +0000 Subject: [PATCH 62/90] Student view status codes added --- App/views/student.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/App/views/student.py b/App/views/student.py index 131c2a2f5..f5d367b12 100644 --- a/App/views/student.py +++ b/App/views/student.py @@ -30,18 +30,18 @@ def create_student_route(): programname = request.json['programname'] if not all([student_id, password, name, programname]): - return jsonify({'Error': 'Missing required fields. Please provide student id, password, name, and program name.'}) + return jsonify({'Error': 'Missing required fields. Please provide student id, password, name, and program name.'}), 400 student = get_student_by_id(student_id) if student: - return jsonify({'Error': 'Student id found'}) + return jsonify({'Error': 'Student id found'}), 400 program = get_program_by_name(programname) if not program: - return jsonify({'Error': 'Incorrect program name'}) + return jsonify({'Error': 'Incorrect program name'}), 400 create_student(student_id, password, name, programname) - return jsonify({'Success!': f"user {student_id} created"}) + return jsonify({'Success!': f"user {student_id} created"}), 201 ##Add course to course history @@ -51,25 +51,25 @@ def add_course_to_student_route(): course_code = request.json['course_code'] if not student_id or not course_code: - return jsonify({'Error': 'Missing required fields'}) + return jsonify({'Error': 'Missing required fields'}), 400 # Check if the student and course exist student = get_student_by_id(student_id) course = get_course_by_courseCode(course_code) if not student: - return jsonify({'Error': 'Student not found'}) + return jsonify({'Error': 'Student not found'}), 400 if not course: - return jsonify({'Error': 'Course not found'}) + return jsonify({'Error': 'Course not found'}), 400 # Check if the course is already in the student's completed courses completed_courses = getCompletedCourseCodes(student_id) if course_code in completed_courses: - return jsonify({'Error': 'Course already completed'}) + return jsonify({'Error': 'Course already completed'}), 400 addCoursetoHistory(student_id, course_code) - return jsonify({'Success!': f"Course {course_code} added to student {student_id}'s course history"}) + return jsonify({'Success!': f"Course {course_code} added to student {student_id}'s course history"}), 200 ##Add course plan @@ -82,12 +82,12 @@ def create_student_plan_route(): student = get_student_by_id(student_id) if not student: - return jsonify({'Error': 'Student not found'}) + return jsonify({'Error': 'Student not found'}), 400 valid_command = ["electives", "easy", "fastest"] if command not in valid_command: - return jsonify("Invalid command. Please enter 'electives', 'easy', or 'fastest'.") + return jsonify("Invalid command. Please enter 'electives', 'easy', or 'fastest'."), 400 courses = generator(student, command) - return jsonify({'Success!': f"{command} plan added to student {student_id} ", "courses" : courses}) + return jsonify({'Success!': f"{command} plan added to student {student_id} ", "courses" : courses}), 200 From ff833f2010319040519f7608deb50bd5e02a95aa Mon Sep 17 00:00:00 2001 From: Jerrelle Johnson Date: Sun, 8 Oct 2023 21:19:54 -0400 Subject: [PATCH 63/90] removed adminfile and course file from views --- App/controllers/admin.py | 49 ---------------------------------------- App/models/admin.py | 23 ------------------- App/views/__init__.py | 3 +-- App/views/course.py | 24 -------------------- wsgi.py | 31 +------------------------ 5 files changed, 2 insertions(+), 128 deletions(-) delete mode 100644 App/controllers/admin.py delete mode 100644 App/models/admin.py delete mode 100644 App/views/course.py diff --git a/App/controllers/admin.py b/App/controllers/admin.py deleted file mode 100644 index 3c53f36b2..000000000 --- a/App/controllers/admin.py +++ /dev/null @@ -1,49 +0,0 @@ -from App.models import User -from App.models import Student -from App.models import Staff -from App.models import Admin -from App.database import db -from App.models import OfferedCourses -# from App.controllers import removeAllCourses -from App.controllers.staff import create_staff -import json - - -def createAdmin(id, username, password, name): - newadmin = Admin(id, username, password, name) - try: - db.session.add(newadmin) - db.session.commit() - except Exception as e: #admin already exists - db.session.rollback() - print(f'Username already taken') - print(f'Admin created.') - return newadmin - - -def addStaff(id,username,password,name): #creates new staff member - newstaff = create_staff(password, id, name) - return newstaff - - -def removeCourseListing(): - semcourses=OfferedCourses.query.first() - removeAllCourses(semcourses) - print(f'Course listing removed') - - -def removeAccount(id): #removes account by id - acc=User.query.filter_by(id=id).first() - if not acc: - print(f'Account with ID {id} not found.') - return - student=Student.query.filter_by(id=id).first() - staff=Staff.query.filter_by(id=id).first() - if student: - db.session.delete(student) - else: - db.session.delete(staff) - db.session.delete(acc) - db.session.commit() - print(f'Account deleted.') - diff --git a/App/models/admin.py b/App/models/admin.py deleted file mode 100644 index c77a93434..000000000 --- a/App/models/admin.py +++ /dev/null @@ -1,23 +0,0 @@ -from App.database import db -from App.models import User - -class Admin(User): - id=db.Column(db.ForeignKey('user.id'), primary_key=True) - name=db.Column(db.String(120), nullable=False) - # user=db.relationship('User',backref=db.backref('Admin')) - - def __init__(self, username, password, name): - super().__init__(username,password) - self.name=name - self.id=id - - def get_json(self): - return{ - 'id': self.id, - 'name': self.name - } - - def __repr__(self): - return f'' - - diff --git a/App/views/__init__.py b/App/views/__init__.py index cc3af70f9..756127bb3 100644 --- a/App/views/__init__.py +++ b/App/views/__init__.py @@ -3,9 +3,8 @@ from .user import user_views from .index import index_views from .auth import auth_views -from .course import course_views from .staff import staff_views from .student import student_views -views = [user_views, index_views, auth_views, course_views, staff_views, student_views] +views = [user_views, index_views, auth_views, staff_views, student_views] # blueprints must be added to this list \ No newline at end of file diff --git a/App/views/course.py b/App/views/course.py deleted file mode 100644 index 1716ecc15..000000000 --- a/App/views/course.py +++ /dev/null @@ -1,24 +0,0 @@ -from flask import Blueprint, jsonify, request - -from App.controllers import create_course - -course_views = Blueprint('course_views', __name__, template_folder='../templates') - -@course_views.route('/courses/', methods=['POST']) -def upload_course(): - try: - data = request.get_json() - - if not all(key in data for key in ('file_path',)): - return jsonify({'error': 'Invalid request data'}), 400 - - file_path = data['file_path'] - new_course = create_course(file_path) - - return jsonify({'message': f'Course {new_course.courseCode} created successfully'}), 201 - - except Exception as e: - return jsonify({'error': f'An error occurred: {str(e)}'}), 50 - - - \ No newline at end of file diff --git a/wsgi.py b/wsgi.py index 4a578e79b..9ea59b8cd 100644 --- a/wsgi.py +++ b/wsgi.py @@ -3,12 +3,6 @@ from flask import Flask from App.controllers.student import create_student from flask.cli import with_appcontext, AppGroup -""" -# add more courses, -# populate student course history 10courses -add courses to program -offered courses -""" from App.database import db, get_migrate from App.main import create_app @@ -328,27 +322,4 @@ def allSemCourses(): print("empty") -app.cli.add_command(course) - -########################################################### - -''' -Course Plan Commands -''' - -coursePlan = AppGroup('plan', help = 'Course Plan object commands') - -# @coursePlan.command('remaining', help='Get remaining program courses') -# @click.argument('programname', type=str) -# def remaining(programname): - -# # required = get_all_courses(programname) -# # completed = ['COMP1600'] -# # newRemaining = getRemainingCourses(completed, required) -# # print(f'Remaining courses are: {newRemaining}') - - -# Define the course plan create command - - -app.cli.add_command(coursePlan) \ No newline at end of file +app.cli.add_command(course) \ No newline at end of file From f6d7d8179046f9c14c458980fda8f9f9344088fc Mon Sep 17 00:00:00 2001 From: Kyle-McIntosh <78955773+Kyle-McIntosh@users.noreply.github.com> Date: Mon, 9 Oct 2023 05:57:43 +0000 Subject: [PATCH 64/90] Student views auth --- App/controllers/student.py | 6 +++++ App/views/student.py | 49 ++++++++++++++++++++++++++++---------- 2 files changed, 43 insertions(+), 12 deletions(-) diff --git a/App/controllers/student.py b/App/controllers/student.py index f4e4d8145..843c056b2 100644 --- a/App/controllers/student.py +++ b/App/controllers/student.py @@ -54,6 +54,12 @@ def view_course_plan(student): plan=getCoursePlan(student.id) return plan +def verify_student(username): + student=Student.query.filter_by(id=username).first() + if student: + return True + return False + # def add_courses_from_file(student, file_path): # try: # with open(file_path, 'r') as file: diff --git a/App/views/student.py b/App/views/student.py index f5d367b12..e47ae8dfe 100644 --- a/App/views/student.py +++ b/App/views/student.py @@ -4,10 +4,10 @@ from.index import index_views from App.controllers import ( - #create_user, - #jwt_authenticate, - #get_all_users, - #get_all_users_json, + create_user, + jwt_authenticate, + get_all_users, + get_all_users_json, jwt_required, create_student, get_program_by_name, @@ -15,26 +15,33 @@ get_course_by_courseCode, addCoursetoHistory, getCompletedCourseCodes, - generator + generator, + addCourseToPlan, + verify_student, + verify_staff ) student_views = Blueprint('student_views', __name__, template_folder='../templates') ##Create student @student_views.route('/student', methods=['POST']) -#@jwt_required() +@login_required def create_student_route(): student_id = request.json['student_id'] password = request.json['password'] name = request.json['name'] programname = request.json['programname'] + username=current_user.username + if not verify_staff(username): #verify that the user is a student + return jsonify({'message': 'You are unauthorized to perform this action. Please login with Staff credentials.'}), 401 + if not all([student_id, password, name, programname]): return jsonify({'Error': 'Missing required fields. Please provide student id, password, name, and program name.'}), 400 student = get_student_by_id(student_id) if student: - return jsonify({'Error': 'Student id found'}), 400 + return jsonify({'Error': 'Student ID taken'}), 400 program = get_program_by_name(programname) if not program: @@ -46,10 +53,15 @@ def create_student_route(): ##Add course to course history @student_views.route('/student/add_course', methods=['POST']) +@login_required def add_course_to_student_route(): student_id = request.json['student_id'] course_code = request.json['course_code'] + username=current_user.username + if not verify_student(username): #verify that the user is logged in + return jsonify({'message': 'You are unauthorized to perform this action. Please login.'}), 401 + if not student_id or not course_code: return jsonify({'Error': 'Missing required fields'}), 400 @@ -62,7 +74,6 @@ def add_course_to_student_route(): if not course: return jsonify({'Error': 'Course not found'}), 400 - # Check if the course is already in the student's completed courses completed_courses = getCompletedCourseCodes(student_id) if course_code in completed_courses: @@ -75,9 +86,14 @@ def add_course_to_student_route(): ##Add course plan @student_views.route('/student/create_student_plan', methods=['POST']) +@login_required def create_student_plan_route(): student_id = request.json['student_id'] command = request.json['command'] + + username=current_user.username + if not verify_student(username): #verify that the user is logged in + return jsonify({'message': 'You are unauthorized to perform this action. Please login.'}), 401 student = get_student_by_id(student_id) @@ -86,8 +102,17 @@ def create_student_plan_route(): valid_command = ["electives", "easy", "fastest"] - if command not in valid_command: - return jsonify("Invalid command. Please enter 'electives', 'easy', or 'fastest'."), 400 + if command in valid_command: + courses = generator(student, command) + return jsonify({'Success!': f"{command} plan added to student {student_id} ", "courses" : courses}), 200 - courses = generator(student, command) - return jsonify({'Success!': f"{command} plan added to student {student_id} ", "courses" : courses}), 200 + course = get_course_by_courseCode(command) + if course: + addCourseToPlan(student, command) + return jsonify({'Success!': f"Course {command} added to student {student_id} plan"}), 200 + + return jsonify("Invalid command. Please enter 'electives', 'easy', 'fastest', or a valid course code."), 400 + + + + From aedbb251dd02683eaa9cc580562ede9d9c36398f Mon Sep 17 00:00:00 2001 From: Jerrelle Johnson Date: Mon, 9 Oct 2023 07:41:10 -0400 Subject: [PATCH 65/90] added create staff to index init --- App/views/index.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/App/views/index.py b/App/views/index.py index cff58abd9..3ca2c584f 100644 --- a/App/views/index.py +++ b/App/views/index.py @@ -1,6 +1,6 @@ from flask import Blueprint, redirect, render_template, request, send_from_directory, jsonify from App.models import db -from App.controllers import create_user +from App.controllers import (create_user, create_staff) index_views = Blueprint('index_views', __name__, template_folder='../templates') @@ -13,6 +13,7 @@ def init(): db.drop_all() db.create_all() create_user('bob', 'bobpass') + create_staff("adminpass","999", "admin") return jsonify(message='db initialized!') @index_views.route('/health', methods=['GET']) From cb978d2c7ce84c4cc0d6db93d604e0ceb20511ff Mon Sep 17 00:00:00 2001 From: Jerrelle Johnson Date: Mon, 9 Oct 2023 08:01:12 -0400 Subject: [PATCH 66/90] updates --- App/views/index.py | 1 - 1 file changed, 1 deletion(-) diff --git a/App/views/index.py b/App/views/index.py index 3ca2c584f..0711be8ac 100644 --- a/App/views/index.py +++ b/App/views/index.py @@ -12,7 +12,6 @@ def index_page(): def init(): db.drop_all() db.create_all() - create_user('bob', 'bobpass') create_staff("adminpass","999", "admin") return jsonify(message='db initialized!') From ebe17fdce9c697cc385065336cdf3464cb841c5f Mon Sep 17 00:00:00 2001 From: Kyle-McIntosh <78955773+Kyle-McIntosh@users.noreply.github.com> Date: Mon, 9 Oct 2023 13:55:20 +0000 Subject: [PATCH 67/90] Student auth changes --- App/views/student.py | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/App/views/student.py b/App/views/student.py index e47ae8dfe..b514508ac 100644 --- a/App/views/student.py +++ b/App/views/student.py @@ -17,25 +17,19 @@ getCompletedCourseCodes, generator, addCourseToPlan, - verify_student, - verify_staff + verify_student ) student_views = Blueprint('student_views', __name__, template_folder='../templates') ##Create student @student_views.route('/student', methods=['POST']) -@login_required def create_student_route(): student_id = request.json['student_id'] password = request.json['password'] name = request.json['name'] programname = request.json['programname'] - username=current_user.username - if not verify_staff(username): #verify that the user is a student - return jsonify({'message': 'You are unauthorized to perform this action. Please login with Staff credentials.'}), 401 - if not all([student_id, password, name, programname]): return jsonify({'Error': 'Missing required fields. Please provide student id, password, name, and program name.'}), 400 @@ -60,7 +54,7 @@ def add_course_to_student_route(): username=current_user.username if not verify_student(username): #verify that the user is logged in - return jsonify({'message': 'You are unauthorized to perform this action. Please login.'}), 401 + return jsonify({'message': 'You are unauthorized to perform this action. Please login with Student credentials.'}), 401 if not student_id or not course_code: return jsonify({'Error': 'Missing required fields'}), 400 @@ -92,8 +86,8 @@ def create_student_plan_route(): command = request.json['command'] username=current_user.username - if not verify_student(username): #verify that the user is logged in - return jsonify({'message': 'You are unauthorized to perform this action. Please login.'}), 401 + if not verify_student(username): #verify that the student is logged in + return jsonify({'message': 'You are unauthorized to perform this action. Please login with Student credentials.'}), 401 student = get_student_by_id(student_id) From 9c44a7bd9a3158f22db7a9f1360107269949d018 Mon Sep 17 00:00:00 2001 From: Jerrelle Johnson Date: Mon, 9 Oct 2023 12:52:07 -0400 Subject: [PATCH 68/90] updates --- App/views/index.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/App/views/index.py b/App/views/index.py index 0711be8ac..9c969302c 100644 --- a/App/views/index.py +++ b/App/views/index.py @@ -13,7 +13,7 @@ def init(): db.drop_all() db.create_all() create_staff("adminpass","999", "admin") - return jsonify(message='db initialized!') + return jsonify(message='staff created, db initialized!') @index_views.route('/health', methods=['GET']) def health_check(): From 84c73ffffa61149708634ac83e2083c3924b50e6 Mon Sep 17 00:00:00 2001 From: Jerrelle Johnson Date: Tue, 10 Oct 2023 08:38:08 -0400 Subject: [PATCH 69/90] added create courses to idex views --- App/views/index.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/App/views/index.py b/App/views/index.py index 9c969302c..197763395 100644 --- a/App/views/index.py +++ b/App/views/index.py @@ -1,6 +1,6 @@ from flask import Blueprint, redirect, render_template, request, send_from_directory, jsonify from App.models import db -from App.controllers import (create_user, create_staff) +from App.controllers import (create_course, create_staff) index_views = Blueprint('index_views', __name__, template_folder='../templates') @@ -13,7 +13,8 @@ def init(): db.drop_all() db.create_all() create_staff("adminpass","999", "admin") - return jsonify(message='staff created, db initialized!') + create_course('testData/courseData.csv') + return jsonify(message='staff created, courses created, db initialized!') @index_views.route('/health', methods=['GET']) def health_check(): From cfd609cd2156cffd2d94ceb399e963ae8de854cd Mon Sep 17 00:00:00 2001 From: JervalThomas Date: Mon, 16 Oct 2023 12:03:20 -0400 Subject: [PATCH 70/90] merge conflicts --- App/controllers/staff.py | 70 ++++++++++++++++++++-------------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/App/controllers/staff.py b/App/controllers/staff.py index 4819023c4..d13b97cad 100644 --- a/App/controllers/staff.py +++ b/App/controllers/staff.py @@ -26,38 +26,38 @@ def verify_staff(username): # print(f"An error occurred while adding the program: {e}") -def remove_program(self, program_name): - try: - program = Program.query.filter_by(name=program_name).first() - if program: - db.session.delete(program) - db.session.commit() - else: - print(f"Program '{program_name}' not found.") - except Exception as e: - db.session.rollback() - print(f"An error occurred while removing the program: {e}") - - -def add_course(self, course_code, course_name, credits): - try: - new_course = Course(code=course_code, name=course_name, credits=credits) - db.session.add(new_course) - db.session.commit() - return new_course - except Exception as e: - db.session.rollback() - print(f"An error occurred while adding the course: {e}") - - -def remove_course(self, course_code): - try: - course = Course.query.filter_by(code=course_code).first() - if course: - db.session.delete(course) - db.session.commit() - else: - print(f"Course '{course_code}' not found.") - except Exception as e: - db.session.rollback() - print(f"An error occurred while removing the course: {e}") +# def remove_program(self, program_name): +# try: +# program = Program.query.filter_by(name=program_name).first() +# if program: +# db.session.delete(program) +# db.session.commit() +# else: +# print(f"Program '{program_name}' not found.") +# except Exception as e: +# db.session.rollback() +# print(f"An error occurred while removing the program: {e}") + + +# def add_course(self, course_code, course_name, credits): +# try: +# new_course = Course(code=course_code, name=course_name, credits=credits) +# db.session.add(new_course) +# db.session.commit() +# return new_course +# except Exception as e: +# db.session.rollback() +# print(f"An error occurred while adding the course: {e}") + + +# def remove_course(self, course_code): +# try: +# course = Course.query.filter_by(code=course_code).first() +# if course: +# db.session.delete(course) +# db.session.commit() +# else: +# print(f"Course '{course_code}' not found.") +# except Exception as e: +# db.session.rollback() +# print(f"An error occurred while removing the course: {e}") From 24c80e2d28310077d48cc330fe7ad45baf06ea30 Mon Sep 17 00:00:00 2001 From: JervalThomas Date: Mon, 16 Oct 2023 12:03:59 -0400 Subject: [PATCH 71/90] merge conflicts --- App/controllers/staff.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/App/controllers/staff.py b/App/controllers/staff.py index d13b97cad..b233c1200 100644 --- a/App/controllers/staff.py +++ b/App/controllers/staff.py @@ -1,4 +1,4 @@ -from App.models import Program, Course +from App.models import Program, Course, Staff from App.database import db From f48b1bd5d27b91c96627b002bdf54a241a7b808f Mon Sep 17 00:00:00 2001 From: JervalThomas Date: Mon, 16 Oct 2023 19:49:44 -0400 Subject: [PATCH 72/90] Student unit test --- App/controllers/student.py | 6 +++- App/tests/test_app.py | 56 +++++++++++++++++++++++++++++++++++--- 2 files changed, 57 insertions(+), 5 deletions(-) diff --git a/App/controllers/student.py b/App/controllers/student.py index 9bc5e7778..5ce88522d 100644 --- a/App/controllers/student.py +++ b/App/controllers/student.py @@ -1,5 +1,5 @@ from App.models import Student, CoursePlan, Program -from App.controllers import (get_program_by_name) +from App.controllers import (get_program_by_name, addCourse, removeCourse, getCoursePlan) from App.database import db def create_student(student_id, password, name, programname): @@ -8,6 +8,7 @@ def create_student(student_id, password, name, programname): new_student = Student(student_id, password, name, program.id) db.session.add(new_student) db.session.commit() + return new_student print("Student successfully created") else: print("Program doesn't exist") @@ -45,6 +46,9 @@ def enroll_in_programme(student_id, programme_id): db.session.add(student) db.session.commit() +def hasCourseInPlan(student, course_code): + return any(course.course_code == course_code for course in getCoursePlan(student.id)) + def add_course_to_plan(student, course_id): addCourse(student,course_id) return diff --git a/App/tests/test_app.py b/App/tests/test_app.py index ed1fac9b1..9faf99c70 100644 --- a/App/tests/test_app.py +++ b/App/tests/test_app.py @@ -3,15 +3,20 @@ from App.main import create_app from App.database import db, create_db -from App.models import User +from App.models import User, Student, Program from App.controllers import ( create_user, get_all_users_json, login, get_user, - get_user_by_username, - update_user -) + update_user, + create_student, + addCoursetoHistory, + create_program, + addCourseToPlan, + create_course, + hasCourseInPlan, + ) LOGGER = logging.getLogger(__name__) @@ -75,3 +80,46 @@ def test_update_user(self): update_user(1, "ronnie") user = get_user(1) assert user.username == "ronnie" + +class StudentIntegrationTests(unittest.TestCase): + + def setUp(self): + app = create_app({'TESTING': True, 'SQLALCHEMY_DATABASE_URI': 'sqlite:///test.db'}) + self.app = app.test_client() + + with app.app_context(): + create_db() + db.create_all() + + def tearDown(self): + with self.app: + db.session.remove() + db.drop_all() + db.engine.dispose() + + def test_create_student(self): + program = create_program("Computer Science Major", 3,4,5) + student = create_student("816025522", "Password", "Jerval", program.name) + assert student.name == "Jerval" + + def test_add_course_to_plan(self): + create_course("/Users/jervalthomas/Desktop/Programming /Year 4 Sem 1/COMP 3613/flaskmvc/testData/courseData.csv") + program = create_program("Computer Science Major", 3,4,5) + student = create_student("816025522", "Password", "Jerval", program.name) + course_code = "MATH2250" + addCourseToPlan(student, course_code) + self.assertTrue(hasCourseInPlan(course_code)) + + def test_remove_course_from_plan(self): + student = create_student("816025522", "Password", "Jerval", "Computer Science") + course_code = "COMP101" + addCourseToPlan(student, course_code) + self.assertTrue(hasCourseInPlan(course_code)) + student.removeCourseFromPlan(course_code) + self.assertFalse(hasCourseInPlan(course_code)) + + def test_enroll_in_programme(self): + student = create_student("816025522", "Password", "Jerval", "Computer Science") + program_name = "Computer Science Program" + student.enroll_in_programme(program_name) + self.assertEqual(student.program.name, program_name) From 187b3c95f914b904ae322d882e42e3a10ef7f011 Mon Sep 17 00:00:00 2001 From: Jerrelle Johnson Date: Mon, 16 Oct 2023 21:51:56 -0400 Subject: [PATCH 73/90] did program and course tests --- App/tests/__init__.py | 4 +++- App/tests/courses.py | 22 ++++++++++++++++++++++ App/tests/program.py | 32 ++++++++++++++++++++++++++++++++ wsgi.py | 14 +++++++++++++- 4 files changed, 70 insertions(+), 2 deletions(-) create mode 100644 App/tests/courses.py create mode 100644 App/tests/program.py diff --git a/App/tests/__init__.py b/App/tests/__init__.py index f5c872faf..0af8b2746 100644 --- a/App/tests/__init__.py +++ b/App/tests/__init__.py @@ -1 +1,3 @@ -from .test_app import * \ No newline at end of file +from .test_app import * +from .courses import * +from .program import * \ No newline at end of file diff --git a/App/tests/courses.py b/App/tests/courses.py new file mode 100644 index 000000000..2a5794a95 --- /dev/null +++ b/App/tests/courses.py @@ -0,0 +1,22 @@ +import pytest, unittest +from App.models import Course + +class CourseUnitTests(unittest.TestCase): + + def test_new_course(self): + course = Course() + self.assertIsInstance(course, Course) + + def test_course_json(self): + course = Course() + course_json = course.get_json() + self.assertDictEqual(course_json, { + 'Course Code:': None, + 'Course Name: ': None, + 'Course Rating: ': None, + 'No. of Credits: ': None, + 'Prerequistes: ': []}) + + # def test_get_course_credits(self): + + \ No newline at end of file diff --git a/App/tests/program.py b/App/tests/program.py new file mode 100644 index 000000000..8267e83d1 --- /dev/null +++ b/App/tests/program.py @@ -0,0 +1,32 @@ +import unittest +from App.models import Program + +class ProgramUnitTests(unittest.TestCase): + + def test_new_program(self): + programname = "Information Technology Special" + core_credits = 69 + elective_credits = 15 + foun_credits = 9 + program = Program(programname, core_credits, elective_credits, foun_credits) + self.assertEqual(program.name, programname) + self.assertEqual(program.core_credits, core_credits) + self.assertEqual(program.elective_credits, elective_credits) + self.assertEqual(program.foun_credits, foun_credits) + + def test_program_toJSON(self): + programname = "Information Technology Special" + core_credits = 69 + elective_credits = 15 + foun_credits = 9 + + program = Program(programname, core_credits, elective_credits, foun_credits) + program_json = program.get_json() + + self.assertDictEqual(program_json, { + 'Program ID:': None, + 'Program Name: ': programname, + 'Core Credits: ': core_credits, + 'Elective Credits ': elective_credits, + 'Foundation Credits: ': foun_credits, + }) diff --git a/wsgi.py b/wsgi.py index 9ea59b8cd..12bcbce9f 100644 --- a/wsgi.py +++ b/wsgi.py @@ -203,11 +203,23 @@ def add_offered_course(code): @click.argument("type", default="all") def user_tests_command(type): if type == "unit": - sys.exit(pytest.main(["-k", "UserUnitTests"])) + sys.exit(pytest.main(["-k", "UnitTests"])) elif type == "int": sys.exit(pytest.main(["-k", "UserIntegrationTests"])) else: sys.exit(pytest.main(["-k", "App"])) + +@test.command("course", help="Run Course tests") +def courses_tests_command(): + sys.exit(pytest.main(["App/tests/courses.py::CourseUnitTests"])) + + +@test.command("program", help="Run Program tests") +def courses_tests_command(): + sys.exit(pytest.main(["App/tests/program.py::ProgramUnitTests"])) + + + app.cli.add_command(test) From 2a075bcf7875c5f04c13a651a250e3fc8e83461d Mon Sep 17 00:00:00 2001 From: ashleyjacob Date: Tue, 17 Oct 2023 10:04:44 +0000 Subject: [PATCH 74/90] unit tests for program courses and prerequisites --- App/models/prerequisites.py | 4 ++-- App/tests/test_app.py | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/App/models/prerequisites.py b/App/models/prerequisites.py index 1909c1c11..4858c747a 100644 --- a/App/models/prerequisites.py +++ b/App/models/prerequisites.py @@ -16,6 +16,6 @@ def __init__(self, prereqCode, nameofCourse): def get_json(self): return{ 'prereq_id': self.id, - 'course_id': self.course_id, - 'prerequisite_course': self.prereq_code, + 'prerequisite_courseCode': self.prereq_courseCode, + 'prerequisite_course':self.courseName } \ No newline at end of file diff --git a/App/tests/test_app.py b/App/tests/test_app.py index ed1fac9b1..bb6551331 100644 --- a/App/tests/test_app.py +++ b/App/tests/test_app.py @@ -4,6 +4,7 @@ from App.main import create_app from App.database import db, create_db from App.models import User +from App.models import Prerequisites, ProgramCourses, StudentCourseHistory from App.controllers import ( create_user, get_all_users_json, @@ -42,6 +43,24 @@ def test_check_password(self): user = User("bob", password) assert user.check_password(password) + def test_new_prerequisite(self): + prereq=Prerequisites("INFO2605","Introduction to Information Technology Concepts") + assert prereq.prereq_courseCode=="INFO2605" + + def test_prerequisite_toJSON(self): + prereq=Prerequisites("INFO2605","Introduction to Information Technology Concepts") + prereq_json=prereq.get_json() + self.assertDictEqual(prereq_json,{'prereq_id': None, 'prerequisite_courseCode': 'INFO2605', 'prerequisite_course': 'Introduction to Information Technology Concepts'}) + + def test_new_program_course(self): + programcourse=ProgramCourses("1","INFO2605","2") + assert programcourse.code=="INFO2605" + + def test_program_course_toJSON(self): + programcourse=ProgramCourses("1","INFO2605","2") + programcourse_json=programcourse.get_json() + self.assertDictEqual(programcourse_json,{'Program Course ID:':None, 'Program ID:':'1','Course Code: ':'INFO2605','Course Type: ':'2'}) + ''' Integration Tests ''' From c2ed419aa7d28f0bf7d36c399900d6d7fe2c57fd Mon Sep 17 00:00:00 2001 From: JervalThomas Date: Tue, 17 Oct 2023 08:30:00 -0400 Subject: [PATCH 75/90] Student unit and integration test --- App/controllers/coursePlan.py | 6 +++- App/controllers/student.py | 8 ++--- App/models/student.py | 4 +-- App/tests/test_app.py | 66 ++++++++++++++++++++++++++++------- 4 files changed, 63 insertions(+), 21 deletions(-) diff --git a/App/controllers/coursePlan.py b/App/controllers/coursePlan.py index fe123573d..88ba9517a 100644 --- a/App/controllers/coursePlan.py +++ b/App/controllers/coursePlan.py @@ -17,10 +17,12 @@ isCourseOffered, programCourses_SortedbyRating, programCourses_SortedbyHighestCredits, - get_all_courses_by_planid + get_all_courses_by_planid, + ) + def create_CoursePlan(id): plan = CoursePlan(id) db.session.add(plan) @@ -50,10 +52,12 @@ def addCourseToPlan(Student, courseCode): if plan: createPlanCourse(plan.planId, courseCode) print("Course successfully added to course plan") + return plan else: plan = create_CoursePlan(Student.id) createPlanCourse(plan.planId, courseCode) print("Plan successfully created and Course was successfully added to course plan") + return plan else: print("Course is not offered") else: diff --git a/App/controllers/student.py b/App/controllers/student.py index 5ce88522d..3b1f7ae57 100644 --- a/App/controllers/student.py +++ b/App/controllers/student.py @@ -1,5 +1,5 @@ from App.models import Student, CoursePlan, Program -from App.controllers import (get_program_by_name, addCourse, removeCourse, getCoursePlan) +from App.controllers import (get_program_by_name) from App.database import db def create_student(student_id, password, name, programname): @@ -32,7 +32,7 @@ def get_all_students_json(): def update_student(id, username): student = get_student_by_id(id) if student: - student.username = username + student.name = username db.session.add(student) db.session.commit() return student @@ -45,9 +45,7 @@ def enroll_in_programme(student_id, programme_id): student.program_id = programme_id db.session.add(student) db.session.commit() - -def hasCourseInPlan(student, course_code): - return any(course.course_code == course_code for course in getCoursePlan(student.id)) + return student.program_id def add_course_to_plan(student, course_id): addCourse(student,course_id) diff --git a/App/models/student.py b/App/models/student.py index 134dd78ae..a0445ecb1 100644 --- a/App/models/student.py +++ b/App/models/student.py @@ -16,9 +16,9 @@ def __init__(self, username, password, name, program_id): self.program_id = program_id def get_json(self): - return{ - 'student_id': self.id, + return{'student_id': self.id, 'name': self.name, 'program' : self.program_id + } diff --git a/App/tests/test_app.py b/App/tests/test_app.py index 9faf99c70..76dd4f566 100644 --- a/App/tests/test_app.py +++ b/App/tests/test_app.py @@ -15,7 +15,13 @@ create_program, addCourseToPlan, create_course, - hasCourseInPlan, + addSemesterCourses, + getCourseFromCoursePlan, + removeCourse, + enroll_in_programme, + get_all_students_json, + update_student, + get_student_by_id ) @@ -81,6 +87,38 @@ def test_update_user(self): user = get_user(1) assert user.username == "ronnie" +class StudentUnitTest(unittest.TestCase): + def setUp(self): + app = create_app({'TESTING': True, 'SQLALCHEMY_DATABASE_URI': 'sqlite:///test.db'}) + self.app = app.test_client() + + with app.app_context(): + create_db() + db.create_all() + + def tearDown(self): + with self.app: + db.session.remove() + db.drop_all() + db.engine.dispose() + + def test_create_student(self): + program = create_program("Computer Science Major", 3,4,5) + student = create_student("816025522", "Password", "Jerval", program.name) + assert student.name == "Jerval" + + def test_get_all_student_json(self): + users_json = get_all_students_json() + self.assertListEqual([{"id":"816025522", "name":"Jerval", "program_id":"" }], users_json) + + + def test_update_student(self): + program = create_program("Computer Science Major", 3,4,5) + create_student("816025522", "Password", "Jerval", program.name) + student = update_student("816025522", "Bill") + assert student.name == "Bill" + + class StudentIntegrationTests(unittest.TestCase): def setUp(self): @@ -103,23 +141,25 @@ def test_create_student(self): assert student.name == "Jerval" def test_add_course_to_plan(self): + course_code = "MATH2250" create_course("/Users/jervalthomas/Desktop/Programming /Year 4 Sem 1/COMP 3613/flaskmvc/testData/courseData.csv") + addSemesterCourses(course_code) program = create_program("Computer Science Major", 3,4,5) student = create_student("816025522", "Password", "Jerval", program.name) - course_code = "MATH2250" - addCourseToPlan(student, course_code) - self.assertTrue(hasCourseInPlan(course_code)) + self.assertTrue(addCourseToPlan(student, course_code)) def test_remove_course_from_plan(self): - student = create_student("816025522", "Password", "Jerval", "Computer Science") - course_code = "COMP101" - addCourseToPlan(student, course_code) - self.assertTrue(hasCourseInPlan(course_code)) - student.removeCourseFromPlan(course_code) - self.assertFalse(hasCourseInPlan(course_code)) + course_code = "MATH2250" + create_course("/Users/jervalthomas/Desktop/Programming /Year 4 Sem 1/COMP 3613/flaskmvc/testData/courseData.csv") + addSemesterCourses(course_code) + program = create_program("Computer Science Major", 3,4,5) + student = create_student("816025522", "Password", "Jerval", program.name) + plan = addCourseToPlan(student, course_code) + removeCourse(student, course_code) + self.assertFalse(getCourseFromCoursePlan(plan, course_code) == "COMP101") def test_enroll_in_programme(self): student = create_student("816025522", "Password", "Jerval", "Computer Science") - program_name = "Computer Science Program" - student.enroll_in_programme(program_name) - self.assertEqual(student.program.name, program_name) + program_id = 24 + enroll_in_programme(student, program_id) + self.assertEqual(enroll_in_programme(student, program_id), program_id) From f74cd68a84ed4fc176554179d9be5cd5d66532e3 Mon Sep 17 00:00:00 2001 From: Jerrelle Johnson Date: Tue, 17 Oct 2023 10:02:53 -0400 Subject: [PATCH 76/90] staff unit tests --- App/tests/__init__.py | 3 ++- App/tests/staff.py | 36 ++++++++++++++++++++++++++++++++++++ wsgi.py | 4 ++++ 3 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 App/tests/staff.py diff --git a/App/tests/__init__.py b/App/tests/__init__.py index 0af8b2746..c3c0114f6 100644 --- a/App/tests/__init__.py +++ b/App/tests/__init__.py @@ -1,3 +1,4 @@ from .test_app import * from .courses import * -from .program import * \ No newline at end of file +from .program import * +from .staff import * \ No newline at end of file diff --git a/App/tests/staff.py b/App/tests/staff.py new file mode 100644 index 000000000..e336b8767 --- /dev/null +++ b/App/tests/staff.py @@ -0,0 +1,36 @@ +import unittest +from App.models import Staff +from werkzeug.security import generate_password_hash + +class StaffUnitTests(unittest.TestCase): + + def test_new_staff(self): + staffid = 999 + staffName = "Jane Doe" + staffpass = "janepass" + staff = Staff(staffpass, staffid, staffName) + self.assertEqual(staff.name, staffName) + self.assertEqual(staff.id, staffid) + + def test_staff_toJSON(self): + staffid = 999 + staffName = "Jane Doe" + staffpass = "janepass" + + staff = Staff(staffpass, staffid, staffName) + staff_json = staff.get_json() + + self.assertDictEqual(staff_json, { + 'staff_id': staffid, + 'name': staffName, + }) + + def test_set_password(self): + password = "mypass" + staff = Staff(password, 999, "Jane Doe") + assert staff.password != password + + def test_check_password(self): + password = "mypass" + staff = Staff(password, 999, "Jane Doe") + assert staff.check_password(password) \ No newline at end of file diff --git a/wsgi.py b/wsgi.py index 12bcbce9f..223e9a0c9 100644 --- a/wsgi.py +++ b/wsgi.py @@ -218,6 +218,10 @@ def courses_tests_command(): def courses_tests_command(): sys.exit(pytest.main(["App/tests/program.py::ProgramUnitTests"])) +@test.command("staff", help="Run Staff tests") +def courses_tests_command(): + sys.exit(pytest.main(["App/tests/staff.py::StaffUnitTests"])) + From f69d9016c61083ea6c78e65a3a51daf819cf50c4 Mon Sep 17 00:00:00 2001 From: ashleyjacob Date: Wed, 18 Oct 2023 02:05:06 +0000 Subject: [PATCH 77/90] int. tests for prereqs & program requirements --- App/tests/test_app.py | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/App/tests/test_app.py b/App/tests/test_app.py index bb6551331..2cfb313d1 100644 --- a/App/tests/test_app.py +++ b/App/tests/test_app.py @@ -4,14 +4,23 @@ from App.main import create_app from App.database import db, create_db from App.models import User -from App.models import Prerequisites, ProgramCourses, StudentCourseHistory +from App.models import Prerequisites, ProgramCourses, StudentCourseHistory, Course from App.controllers import ( create_user, get_all_users_json, login, get_user, get_user_by_username, - update_user + update_user, + create_course, + create_prereq, + getPrereqCodes, + create_program, + create_programCourse, + get_all_programCourses, + get_program_by_name, + programCourses_SortedbyRating, + programCourses_SortedbyHighestCredits ) @@ -94,3 +103,29 @@ def test_update_user(self): update_user(1, "ronnie") user = get_user(1) assert user.username == "ronnie" + + def test_create_prerequisite(self): + file_path="testData/courseData.csv" + create_course(file_path) + + create_prereq("MATH1115","Industrial Statistics") + prereqs=getPrereqCodes("Industrial Statistics") + self.assertEqual(['MATH1115'],prereqs) + + def test_create_program_requirement(self): + program=create_program("Computer Science and Statistics",51,30,9) + create_programCourse("Computer Science and Statistics","MATH1115",1) + program_courses=get_all_programCourses("Computer Science and Statistics") + assert any(course.code == "MATH1115" for course in program_courses) + + def test_programCourses_sorted_by_credits(self): + create_programCourse("Computer Science and Statistics","INFO2606",2) + program=get_program_by_name("Computer Science and Statistics") + credits_sorted=programCourses_SortedbyHighestCredits(program.id) + self.assertListEqual(credits_sorted,['INFO2606', 'MATH1115']) + + def test_programCourses_sorted_by_rating(self): + create_programCourse("Computer Science and Statistics","MATH2250",1) + program=get_program_by_name("Computer Science and Statistics") + rating_list=programCourses_SortedbyRating(program.id) + self.assertListEqual(rating_list,['MATH1115', 'INFO2606', 'MATH2250']) \ No newline at end of file From 7e5474f2c1c6391e8ed324a971e8c387984781cd Mon Sep 17 00:00:00 2001 From: JervalThomas Date: Wed, 18 Oct 2023 08:01:44 -0400 Subject: [PATCH 78/90] Student unit and integration test --- App/tests/test_app.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/App/tests/test_app.py b/App/tests/test_app.py index 76dd4f566..95283418f 100644 --- a/App/tests/test_app.py +++ b/App/tests/test_app.py @@ -107,11 +107,6 @@ def test_create_student(self): student = create_student("816025522", "Password", "Jerval", program.name) assert student.name == "Jerval" - def test_get_all_student_json(self): - users_json = get_all_students_json() - self.assertListEqual([{"id":"816025522", "name":"Jerval", "program_id":"" }], users_json) - - def test_update_student(self): program = create_program("Computer Science Major", 3,4,5) create_student("816025522", "Password", "Jerval", program.name) @@ -140,6 +135,12 @@ def test_create_student(self): student = create_student("816025522", "Password", "Jerval", program.name) assert student.name == "Jerval" + def test_get_all_student_json(self): + program = create_program("Computer Science Major", 3,4,5) + create_student("816025522", "Password", "Jerval", program.name) + users_json = get_all_students_json() + self.assertListEqual([{"name":"Jerval", "student_id":"816025522", "program":1 }], users_json) + def test_add_course_to_plan(self): course_code = "MATH2250" create_course("/Users/jervalthomas/Desktop/Programming /Year 4 Sem 1/COMP 3613/flaskmvc/testData/courseData.csv") @@ -159,7 +160,7 @@ def test_remove_course_from_plan(self): self.assertFalse(getCourseFromCoursePlan(plan, course_code) == "COMP101") def test_enroll_in_programme(self): - student = create_student("816025522", "Password", "Jerval", "Computer Science") - program_id = 24 - enroll_in_programme(student, program_id) - self.assertEqual(enroll_in_programme(student, program_id), program_id) + create_program("Computer Science Major", 3,4,5) + student = create_student("816025522", "Password", "Jerval", "Computer Science Major") + enroll_in_programme(student.id, 1) + assert enroll_in_programme(student.id, 1) == 1 From ce068e745485cbcffaee723c9495315a7da73051 Mon Sep 17 00:00:00 2001 From: JervalThomas Date: Wed, 18 Oct 2023 11:18:30 -0400 Subject: [PATCH 79/90] Student course history unit and integration test --- App/controllers/coursePlan.py | 2 +- App/controllers/courses.py | 1 + App/controllers/studentCourseHistory.py | 3 +- App/models/studentCourseHistory.py | 4 +- App/tests/test_app.py | 201 +++++++++++++++++++----- 5 files changed, 166 insertions(+), 45 deletions(-) diff --git a/App/controllers/coursePlan.py b/App/controllers/coursePlan.py index 88ba9517a..50ffab72a 100644 --- a/App/controllers/coursePlan.py +++ b/App/controllers/coursePlan.py @@ -67,7 +67,7 @@ def addCourseToPlan(Student, courseCode): def removeCourse(Student, courseCode): plan=getCoursePlan(Student.id) if plan: - deleteCourseFromCoursePlan(plan.planid, courseCode) + deleteCourseFromCoursePlan(plan.planId, courseCode) def getRemainingCourses(completed, required): # Check if either 'completed' or 'required' is None diff --git a/App/controllers/courses.py b/App/controllers/courses.py index 50df09e0e..b08334f38 100644 --- a/App/controllers/courses.py +++ b/App/controllers/courses.py @@ -33,6 +33,7 @@ def create_course(file_path): db.session.commit() print("Courses added successfully.") + return course def get_course_by_courseCode(code): return Course.query.filter_by(courseCode=code).first() diff --git a/App/controllers/studentCourseHistory.py b/App/controllers/studentCourseHistory.py index bc98e95f5..1f0001549 100644 --- a/App/controllers/studentCourseHistory.py +++ b/App/controllers/studentCourseHistory.py @@ -10,7 +10,8 @@ def addCoursetoHistory(studentid, code): completed = StudentCourseHistory(studentid, code) db.session.add(completed) db.session.commit() - #print("Course added successfully") + print("Course added successfully") + return else: print("Course doesn't exist") else: diff --git a/App/models/studentCourseHistory.py b/App/models/studentCourseHistory.py index e93b623c1..b5d9e8528 100644 --- a/App/models/studentCourseHistory.py +++ b/App/models/studentCourseHistory.py @@ -15,6 +15,6 @@ def __init__(self, id, courseCode): def get_json(self): return{ - 'Program ID:': self.program_id, - 'Course Code: ': self.code + 'Program ID': self.id, #is this suppose to be id or program_id alone + 'Course Code': self.code } \ No newline at end of file diff --git a/App/tests/test_app.py b/App/tests/test_app.py index 95283418f..a63b1884c 100644 --- a/App/tests/test_app.py +++ b/App/tests/test_app.py @@ -1,9 +1,13 @@ -import os, tempfile, pytest, logging, unittest +import os +import tempfile +import pytest +import logging +import unittest from werkzeug.security import check_password_hash, generate_password_hash from App.main import create_app from App.database import db, create_db -from App.models import User, Student, Program +from App.models import User, Student, Program, StudentCourseHistory from App.controllers import ( create_user, get_all_users_json, @@ -21,8 +25,11 @@ enroll_in_programme, get_all_students_json, update_student, - get_student_by_id - ) + get_student_by_id, + getCompletedCourses, + create_CoursePlan, + view_course_plan +) LOGGER = logging.getLogger(__name__) @@ -30,6 +37,8 @@ ''' Unit Tests ''' + + class UserUnitTests(unittest.TestCase): def test_new_user(self): @@ -40,8 +49,8 @@ def test_new_user(self): def test_get_json(self): user = User("bob", "bobpass") user_json = user.get_json() - self.assertDictEqual(user_json, {"id":None, "username":"bob"}) - + self.assertDictEqual(user_json, {"id": None, "username": "bob"}) + def test_hashed_password(self): password = "mypass" hashed = generate_password_hash(password, method='sha256') @@ -53,15 +62,19 @@ def test_check_password(self): user = User("bob", password) assert user.check_password(password) + ''' Integration Tests ''' # This fixture creates an empty database for the test and deletes it after the test # scope="class" would execute the fixture once and resued for all methods in the class + + @pytest.fixture(autouse=True, scope="module") def empty_db(): - app = create_app({'TESTING': True, 'SQLALCHEMY_DATABASE_URI': 'sqlite:///test.db'}) + app = create_app( + {'TESTING': True, 'SQLALCHEMY_DATABASE_URI': 'sqlite:///test.db'}) create_db() yield app.test_client() db.drop_all() @@ -71,6 +84,7 @@ def test_authenticate(): user = create_user("bob", "bobpass") assert login("bob", "bobpass") != None + class UsersIntegrationTests(unittest.TestCase): def test_create_user(self): @@ -79,7 +93,8 @@ def test_create_user(self): def test_get_all_users_json(self): users_json = get_all_users_json() - self.assertListEqual([{"id":1, "username":"bob"}, {"id":2, "username":"rick"}], users_json) + self.assertListEqual([{"id": 1, "username": "bob"}, { + "id": 2, "username": "rick"}], users_json) # Tests data changes in the database def test_update_user(self): @@ -87,9 +102,11 @@ def test_update_user(self): user = get_user(1) assert user.username == "ronnie" + class StudentUnitTest(unittest.TestCase): def setUp(self): - app = create_app({'TESTING': True, 'SQLALCHEMY_DATABASE_URI': 'sqlite:///test.db'}) + app = create_app( + {'TESTING': True, 'SQLALCHEMY_DATABASE_URI': 'sqlite:///test.db'}) self.app = app.test_client() with app.app_context(): @@ -103,12 +120,20 @@ def tearDown(self): db.engine.dispose() def test_create_student(self): - program = create_program("Computer Science Major", 3,4,5) - student = create_student("816025522", "Password", "Jerval", program.name) - assert student.name == "Jerval" + program = create_program("Computer Science Major", 3, 4, 5) + student = create_student( + "816025522", "Password", "Jerval", program.name) + assert student.name == "Jerval" + + def test_get_all_student_json(self): + program = create_program("Computer Science Major", 3, 4, 5) + create_student("816025522", "Password", "Jerval", program.name) + users_json = get_all_students_json() + self.assertListEqual( + [{"name": "Jerval", "student_id": "816025522", "program": 1}], users_json) def test_update_student(self): - program = create_program("Computer Science Major", 3,4,5) + program = create_program("Computer Science Major", 3, 4, 5) create_student("816025522", "Password", "Jerval", program.name) student = update_student("816025522", "Bill") assert student.name == "Bill" @@ -117,7 +142,8 @@ def test_update_student(self): class StudentIntegrationTests(unittest.TestCase): def setUp(self): - app = create_app({'TESTING': True, 'SQLALCHEMY_DATABASE_URI': 'sqlite:///test.db'}) + app = create_app( + {'TESTING': True, 'SQLALCHEMY_DATABASE_URI': 'sqlite:///test.db'}) self.app = app.test_client() with app.app_context(): @@ -131,36 +157,129 @@ def tearDown(self): db.engine.dispose() def test_create_student(self): - program = create_program("Computer Science Major", 3,4,5) - student = create_student("816025522", "Password", "Jerval", program.name) - assert student.name == "Jerval" - - def test_get_all_student_json(self): - program = create_program("Computer Science Major", 3,4,5) - create_student("816025522", "Password", "Jerval", program.name) - users_json = get_all_students_json() - self.assertListEqual([{"name":"Jerval", "student_id":"816025522", "program":1 }], users_json) + program = create_program("Computer Science Major", 3, 4, 5) + student = create_student( + "816025522", "Password", "Jerval", program.name) + assert student.name == "Jerval" def test_add_course_to_plan(self): - course_code = "MATH2250" - create_course("/Users/jervalthomas/Desktop/Programming /Year 4 Sem 1/COMP 3613/flaskmvc/testData/courseData.csv") - addSemesterCourses(course_code) - program = create_program("Computer Science Major", 3,4,5) - student = create_student("816025522", "Password", "Jerval", program.name) - self.assertTrue(addCourseToPlan(student, course_code)) + course_code = "MATH2250" + create_course( + "/Users/jervalthomas/Desktop/Programming /Year 4 Sem 1/COMP 3613/flaskmvc/testData/courseData.csv") + addSemesterCourses(course_code) + program = create_program("Computer Science Major", 3, 4, 5) + student = create_student( + "816025522", "Password", "Jerval", program.name) + self.assertTrue(addCourseToPlan(student, course_code)) def test_remove_course_from_plan(self): - course_code = "MATH2250" - create_course("/Users/jervalthomas/Desktop/Programming /Year 4 Sem 1/COMP 3613/flaskmvc/testData/courseData.csv") - addSemesterCourses(course_code) - program = create_program("Computer Science Major", 3,4,5) - student = create_student("816025522", "Password", "Jerval", program.name) - plan = addCourseToPlan(student, course_code) - removeCourse(student, course_code) - self.assertFalse(getCourseFromCoursePlan(plan, course_code) == "COMP101") + course_code = "MATH2250" + create_course( + "/Users/jervalthomas/Desktop/Programming /Year 4 Sem 1/COMP 3613/flaskmvc/testData/courseData.csv") + addSemesterCourses(course_code) + program = create_program("Computer Science Major", 3, 4, 5) + student = create_student( + "816025522", "Password", "Jerval", program.name) + plan = create_CoursePlan(1) + addSemesterCourses(course_code) + addCourseToPlan(student, course_code) + enroll_in_programme(student.id, 1) + removeCourse(student, course_code) + course_from_course_plan = getCourseFromCoursePlan(plan.planId, course_code) + self.assertEqual(course_from_course_plan.planId, 1) + self.assertEqual(course_from_course_plan.code, "MATH2250") + def test_enroll_in_programme(self): - create_program("Computer Science Major", 3,4,5) - student = create_student("816025522", "Password", "Jerval", "Computer Science Major") - enroll_in_programme(student.id, 1) - assert enroll_in_programme(student.id, 1) == 1 + create_program("Computer Science Major", 3, 4, 5) + student = create_student( + "816025522", "Password", "Jerval", "Computer Science Major") + enroll_in_programme(student.id, 1) + assert enroll_in_programme(student.id, 1) == 1 + + def test_view_course_plan(self): + course_code = "MATH2250" + create_course( + "/Users/jervalthomas/Desktop/Programming /Year 4 Sem 1/COMP 3613/flaskmvc/testData/courseData.csv") + addSemesterCourses(course_code) + program = create_program("Computer Science Major", 3, 4, 5) + student = create_student( + "816025522", "Password", "Jerval", program.name) + create_CoursePlan(1) + addSemesterCourses(course_code) + addCourseToPlan(student, course_code) + enroll_in_programme(student.id, 1) + plan_json = view_course_plan(student) + self.assertListEqual( + [{"name": "Jerval", "student_id": "816025522", "program": 1}], plan_json) + + +class CourseHistoryUnitTest(unittest.TestCase): + + def setUp(self): + app = create_app( + {'TESTING': True, 'SQLALCHEMY_DATABASE_URI': 'sqlite:///test.db'}) + self.app = app.test_client() + + with app.app_context(): + create_db() + db.create_all() + + def tearDown(self): + with self.app: + db.session.remove() + db.drop_all() + db.engine.dispose() + + def test_create_course_history(self): + student_course_history = StudentCourseHistory(123, 'MATH1115') + + # Assert that the attributes are set correctly + self.assertEqual(student_course_history.studentID, 123) + self.assertEqual(student_course_history.code, 'MATH1115') + + def test_get_json(self): + create_program("Computer Science Major", 3, 4, 5) + create_course( + "/Users/jervalthomas/Desktop/Programming /Year 4 Sem 1/COMP 3613/flaskmvc/testData/courseData.csv") + student = create_student("816025522", "Password", + "Jerval", "Computer Science Major") + student_course_history = StudentCourseHistory(123, 'MATH1115') + addCoursetoHistory(student.id, "MATH1115") + + result = student_course_history.get_json() + + expected_result = {"Program ID": None, "Course Code": "MATH1115"} + + self.assertDictEqual(expected_result, result) + + +class CourseHistoryIntegrationTests(unittest.TestCase): + + def setUp(self): + app = create_app( + {'TESTING': True, 'SQLALCHEMY_DATABASE_URI': 'sqlite:///test.db'}) + self.app = app.test_client() + + with app.app_context(): + create_db() + db.create_all() + + def tearDown(self): + with self.app: + db.session.remove() + db.drop_all() + db.engine.dispose() + + def test_add_Course_to_History(self): + create_program("Computer Science Major", 3, 4, 5) + student = create_student( + "816025522", "Password", "Jerval", "Computer Science Major") + create_course( + "/Users/jervalthomas/Desktop/Programming /Year 4 Sem 1/COMP 3613/flaskmvc/testData/courseData.csv") + addCoursetoHistory(student.id, "INFO1601") + completed_courses = getCompletedCourses(student.id) + assert len(completed_courses) == 1 + for course_history in completed_courses: + self.assertIsInstance(course_history, StudentCourseHistory) + self.assertEqual(course_history.studentID, student.id) From 61b3d4ddc04c27cc1b57667f08f3f8ca3b544a91 Mon Sep 17 00:00:00 2001 From: Jerrelle Johnson Date: Wed, 18 Oct 2023 22:06:34 -0400 Subject: [PATCH 80/90] finished staff program and course tests --- App/controllers/courses.py | 51 +++++++++++++++++++---------- App/controllers/staff.py | 4 +++ App/models/courses.py | 8 +++-- App/tests/courses.py | 66 ++++++++++++++++++++++++++++++++------ App/tests/program.py | 17 +++++++++- App/tests/staff.py | 27 ++++++++++++++-- wsgi.py | 54 +++++++++++++++++++++---------- 7 files changed, 177 insertions(+), 50 deletions(-) diff --git a/App/controllers/courses.py b/App/controllers/courses.py index 50df09e0e..3d285f0f1 100644 --- a/App/controllers/courses.py +++ b/App/controllers/courses.py @@ -3,26 +3,40 @@ from App.database import db import json, csv -def create_course(file_path): +def createPrerequistes(prereqs, courseName): + for prereq_code in prereqs: + prereq_course = Course.query.filter_by(courseCode=prereq_code).first() + + if prereq_course: + create_prereq(prereq_code,courseName) + +def create_course(code, name, rating, credits, prereqs): + already = get_course_by_courseCode(code) + if already is None: + course = Course(code, name, rating, credits) + + if prereqs: + createPrerequistes(prereqs, name) + + db.session.add(course) + db.session.commit() + return course + else: + return None + + +def createCoursesfromFile(file_path): try: with open(file_path, 'r') as file: csv_reader = csv.DictReader(file) for row in csv_reader: - course = Course() - course.courseCode = row["courseCode"] - course.courseName = row["courseName"] - course.credits = int(row["numCredits"]) - course.rating = int(row["rating"]) + courseCode = row["courseCode"] + courseName = row["courseName"] + credits = int(row["numCredits"]) + rating = int(row["rating"]) prerequisites_codes = row["preReqs"].split(',') - - if prerequisites_codes[0]: - prerequisites = [] - for prereq_code in prerequisites_codes: - prereq_course = Course.query.filter_by(courseCode=prereq_code).first() - - if prereq_course: - create_prereq(prereq_code, course.courseName) - db.session.add(course) + + create_course(courseCode, courseName, rating, credits, prerequisites_codes) except FileNotFoundError: print("File not found.") @@ -30,8 +44,7 @@ def create_course(file_path): except Exception as e: print(f"An error occurred: {e}") return False - - db.session.commit() + print("Courses added successfully.") def get_course_by_courseCode(code): @@ -46,6 +59,10 @@ def courses_Sorted_byRating(): return codes +def courses_Sorted_byRating_Objects(): + return Course.query.order_by(Course.rating.asc()).all() + + def get_prerequisites(code): course = get_course_by_courseCode(code) prereqs = get_all_prerequisites(course.courseName) diff --git a/App/controllers/staff.py b/App/controllers/staff.py index b233c1200..c90b3eec1 100644 --- a/App/controllers/staff.py +++ b/App/controllers/staff.py @@ -15,6 +15,10 @@ def verify_staff(username): return True return False +def get_staff_by_id(ID): + return Staff.query.filter_by(id=ID).first() + + # def add_program(self, program_name, description): # try: # new_program = Program(name=program_name, description=description) diff --git a/App/models/courses.py b/App/models/courses.py index 386b59102..c198814c0 100644 --- a/App/models/courses.py +++ b/App/models/courses.py @@ -16,8 +16,11 @@ class Course(db.Model): # planIds = db.relationship('CoursePlanCourses', backref='courses', lazy=True) - def __init__(self): - pass + def __init__(self, code, name, rating, credits): + self.courseCode = code + self.courseName = name + self.rating = rating + self.credits = credits def get_json(self): return{ @@ -25,5 +28,4 @@ def get_json(self): 'Course Name: ': self.courseName, 'Course Rating: ': self.rating, 'No. of Credits: ': self.credits, - 'Prerequistes: ': self.prerequisites } \ No newline at end of file diff --git a/App/tests/courses.py b/App/tests/courses.py index 2a5794a95..27ab8687e 100644 --- a/App/tests/courses.py +++ b/App/tests/courses.py @@ -1,22 +1,68 @@ import pytest, unittest from App.models import Course +from App.controllers import create_course, courses_Sorted_byRating_Objects, get_course_by_courseCode +from App.main import create_app +from App.database import db, create_db class CourseUnitTests(unittest.TestCase): def test_new_course(self): - course = Course() - self.assertIsInstance(course, Course) + courseCode = "INFO2605" + courseName = "Professional Ethics and Law" + credits = 3 + rating = 4 + + course = Course(courseCode, courseName, rating, credits) + + self.assertEqual(course.courseCode, courseCode) + self.assertEqual(course.courseName, courseName) + self.assertEqual(course.credits, credits) + self.assertEqual(course.rating, rating) def test_course_json(self): - course = Course() + courseCode = "INFO2605" + courseName = "Professional Ethics and Law" + credits = 3 + rating = 4 + + course = Course(courseCode, courseName, rating, credits) course_json = course.get_json() + self.assertDictEqual(course_json, { - 'Course Code:': None, - 'Course Name: ': None, - 'Course Rating: ': None, - 'No. of Credits: ': None, - 'Prerequistes: ': []}) + 'Course Code:': courseCode, + 'Course Name: ': courseName, + 'Course Rating: ': rating, + 'No. of Credits: ': credits + }) - # def test_get_course_credits(self): +@pytest.fixture(autouse=True, scope="module") +def empty_db(): + app = create_app({'TESTING': True, 'SQLALCHEMY_DATABASE_URI': 'sqlite:///test.db'}) + create_db() + yield app.test_client() + db.drop_all() + +def test_create_course(): + courseCode = "INFO2605" + courseName = "Professional Ethics and Law" + credits = 3 + rating = 4 + prereqs=[] + + course = create_course(courseCode, courseName, rating, credits, prereqs) + + assert get_course_by_courseCode("INFO2605") != None + + +class CourseIntegrationTests(unittest.TestCase): + def test_courses_sorted_by_rating(self): + prereqs=[] + + create_course("COMP6000", "DNS", 3, 3, prereqs) + create_course("COMP6001", "DSN", 1, 3, prereqs) + sortedCourses = courses_Sorted_byRating_Objects() + + self.assertTrue(sortedCourses) - \ No newline at end of file + for i in range(len(sortedCourses) - 1): + self.assertLessEqual(sortedCourses[i].rating, sortedCourses[i + 1].rating) diff --git a/App/tests/program.py b/App/tests/program.py index 8267e83d1..7fd762af4 100644 --- a/App/tests/program.py +++ b/App/tests/program.py @@ -1,5 +1,8 @@ -import unittest +import unittest, pytest from App.models import Program +from App.main import create_app +from App.database import db, create_db +from App.controllers import create_program, get_program_by_name class ProgramUnitTests(unittest.TestCase): @@ -30,3 +33,15 @@ def test_program_toJSON(self): 'Elective Credits ': elective_credits, 'Foundation Credits: ': foun_credits, }) + +@pytest.fixture(autouse=True, scope="module") +def empty_db(): + app = create_app({'TESTING': True, 'SQLALCHEMY_DATABASE_URI': 'sqlite:///test.db'}) + create_db() + yield app.test_client() + db.drop_all() + +class ProgramIntegrationTests(unittest.TestCase): + def test_create_program(self): + program = create_program("IT", 69, 15, 9) + assert get_program_by_name("IT") != None \ No newline at end of file diff --git a/App/tests/staff.py b/App/tests/staff.py index e336b8767..47d04e78d 100644 --- a/App/tests/staff.py +++ b/App/tests/staff.py @@ -1,5 +1,8 @@ -import unittest +import unittest, pytest +from App.main import create_app +from App.database import db, create_db from App.models import Staff +from App.controllers import create_staff, get_staff_by_id, login from werkzeug.security import generate_password_hash class StaffUnitTests(unittest.TestCase): @@ -33,4 +36,24 @@ def test_set_password(self): def test_check_password(self): password = "mypass" staff = Staff(password, 999, "Jane Doe") - assert staff.check_password(password) \ No newline at end of file + assert staff.check_password(password) + +@pytest.fixture(autouse=True, scope="module") +def empty_db(): + app = create_app({'TESTING': True, 'SQLALCHEMY_DATABASE_URI': 'sqlite:///test.db'}) + create_db() + yield app.test_client() + db.drop_all() + +class StaffIntegrationTests(unittest.TestCase): + def test_create_staff(self): + staffid = 9 + staffName = "Jane Doe" + staffpass = "janepass" + staff = create_staff(staffpass, staffid, staffName) + + assert staff is not None + assert get_staff_by_id(9) != None + + + \ No newline at end of file diff --git a/wsgi.py b/wsgi.py index 223e9a0c9..fa2eab189 100644 --- a/wsgi.py +++ b/wsgi.py @@ -13,7 +13,7 @@ create_program, get_all_OfferedCodes, get_core_credits, - create_course, + createCoursesfromFile, get_course_by_courseCode, get_prerequisites, get_all_courses, @@ -48,7 +48,7 @@ def initialize(): db.drop_all() db.create_all() create_user('bob', 'bobpass') - create_course('testData/courseData.csv') + createCoursesfromFile('testData/courseData.csv') create_program("Computer Science Major", 69, 15, 9) create_student(816, "boo", "testing", "Computer Science Major") create_staff("adminpass","999", "admin") @@ -210,21 +210,40 @@ def user_tests_command(type): sys.exit(pytest.main(["-k", "App"])) @test.command("course", help="Run Course tests") -def courses_tests_command(): - sys.exit(pytest.main(["App/tests/courses.py::CourseUnitTests"])) +@click.argument("type", default="all") +def courses_tests_command(type): + if type == "unit": + sys.exit(pytest.main(["App/tests/courses.py::CourseUnitTests"])) + + elif type == "int": + sys.exit(pytest.main(["App/tests/courses.py::CourseIntegrationTests"])) + + else: + sys.exit(pytest.main(["App/tests/courses.py"])) + @test.command("program", help="Run Program tests") -def courses_tests_command(): - sys.exit(pytest.main(["App/tests/program.py::ProgramUnitTests"])) +@click.argument("type", default="all") +def courses_tests_command(type): + if type == "unit": + sys.exit(pytest.main(["App/tests/program.py::ProgramUnitTests"])) + elif type == "int": + sys.exit(pytest.main(["App/tests/program.py::ProgramIntegrationTests"])) + else: + sys.exit(pytest.main(["App/tests/program.py"])) + @test.command("staff", help="Run Staff tests") -def courses_tests_command(): - sys.exit(pytest.main(["App/tests/staff.py::StaffUnitTests"])) +@click.argument("type", default="all") +def courses_tests_command(type): + if type == "unit": + sys.exit(pytest.main(["App/tests/staff.py::StaffUnitTests"])) + elif type == "int": + sys.exit(pytest.main(["App/tests/staff.py::StaffIntegrationTests"])) + else: + sys.exit(pytest.main(["App/tests/staff.py"])) - - - app.cli.add_command(test) ################################################################# @@ -295,11 +314,11 @@ def addProgramCourse(programname): course = AppGroup('course', help = 'Program object commands') -@course.command('create', help='Create a new course') -@click.argument('file_path') -def create_course_command(file_path): - newcourse = create_course(file_path) - print(f'Course created with course code "{newcourse.courseCode}", name "{newcourse.courseName}", credits "{newcourse.credits}", ratings "{newcourse.rating}" and prerequites "{newcourse.prerequisites}"') +# @course.command('create', help='Create a new course') +# @click.argument('file_path') +# def create_course_command(file_path): +# newcourse = create_course(file_path) +# print(f'Course created with course code "{newcourse.courseCode}", name "{newcourse.courseName}", credits "{newcourse.credits}", ratings "{newcourse.rating}" and prerequites "{newcourse.prerequisites}"') @course.command('prereqs', help='Create a new course') @@ -312,7 +331,8 @@ def create_course_command(code): @click.argument('code', type=str) def get_course(code): course = get_course_by_courseCode(code) - print(f'Course Name: {course.courseName}') if course else print(f'error') + course_json = course.get_json() + print(f'{course_json}') if course else print(f'error') @course.command('getprereqs', help='Get all prerequistes for a course') @click.argument('code', type=str) From 9ec6d467d9d8def8b4446f438ae3ff26ac97b496 Mon Sep 17 00:00:00 2001 From: ashleyjacob Date: Thu, 19 Oct 2023 09:51:07 +0000 Subject: [PATCH 81/90] separated programCourse tests from test_app updated wsgi to run programCourse tests --- App/tests/test_app.py | 56 +------------------------ App/tests/test_programCourses.py | 72 ++++++++++++++++++++++++++++++++ wsgi.py | 16 ++++--- 3 files changed, 84 insertions(+), 60 deletions(-) create mode 100644 App/tests/test_programCourses.py diff --git a/App/tests/test_app.py b/App/tests/test_app.py index 2cfb313d1..21473dabf 100644 --- a/App/tests/test_app.py +++ b/App/tests/test_app.py @@ -4,7 +4,6 @@ from App.main import create_app from App.database import db, create_db from App.models import User -from App.models import Prerequisites, ProgramCourses, StudentCourseHistory, Course from App.controllers import ( create_user, get_all_users_json, @@ -12,15 +11,6 @@ get_user, get_user_by_username, update_user, - create_course, - create_prereq, - getPrereqCodes, - create_program, - create_programCourse, - get_all_programCourses, - get_program_by_name, - programCourses_SortedbyRating, - programCourses_SortedbyHighestCredits ) @@ -52,24 +42,6 @@ def test_check_password(self): user = User("bob", password) assert user.check_password(password) - def test_new_prerequisite(self): - prereq=Prerequisites("INFO2605","Introduction to Information Technology Concepts") - assert prereq.prereq_courseCode=="INFO2605" - - def test_prerequisite_toJSON(self): - prereq=Prerequisites("INFO2605","Introduction to Information Technology Concepts") - prereq_json=prereq.get_json() - self.assertDictEqual(prereq_json,{'prereq_id': None, 'prerequisite_courseCode': 'INFO2605', 'prerequisite_course': 'Introduction to Information Technology Concepts'}) - - def test_new_program_course(self): - programcourse=ProgramCourses("1","INFO2605","2") - assert programcourse.code=="INFO2605" - - def test_program_course_toJSON(self): - programcourse=ProgramCourses("1","INFO2605","2") - programcourse_json=programcourse.get_json() - self.assertDictEqual(programcourse_json,{'Program Course ID:':None, 'Program ID:':'1','Course Code: ':'INFO2605','Course Type: ':'2'}) - ''' Integration Tests ''' @@ -102,30 +74,4 @@ def test_get_all_users_json(self): def test_update_user(self): update_user(1, "ronnie") user = get_user(1) - assert user.username == "ronnie" - - def test_create_prerequisite(self): - file_path="testData/courseData.csv" - create_course(file_path) - - create_prereq("MATH1115","Industrial Statistics") - prereqs=getPrereqCodes("Industrial Statistics") - self.assertEqual(['MATH1115'],prereqs) - - def test_create_program_requirement(self): - program=create_program("Computer Science and Statistics",51,30,9) - create_programCourse("Computer Science and Statistics","MATH1115",1) - program_courses=get_all_programCourses("Computer Science and Statistics") - assert any(course.code == "MATH1115" for course in program_courses) - - def test_programCourses_sorted_by_credits(self): - create_programCourse("Computer Science and Statistics","INFO2606",2) - program=get_program_by_name("Computer Science and Statistics") - credits_sorted=programCourses_SortedbyHighestCredits(program.id) - self.assertListEqual(credits_sorted,['INFO2606', 'MATH1115']) - - def test_programCourses_sorted_by_rating(self): - create_programCourse("Computer Science and Statistics","MATH2250",1) - program=get_program_by_name("Computer Science and Statistics") - rating_list=programCourses_SortedbyRating(program.id) - self.assertListEqual(rating_list,['MATH1115', 'INFO2606', 'MATH2250']) \ No newline at end of file + assert user.username == "ronnie" \ No newline at end of file diff --git a/App/tests/test_programCourses.py b/App/tests/test_programCourses.py new file mode 100644 index 000000000..7f8805d4d --- /dev/null +++ b/App/tests/test_programCourses.py @@ -0,0 +1,72 @@ +import pytest, unittest + +from App.main import create_app +from App.database import db, create_db +from App.models import Prerequisites, ProgramCourses, StudentCourseHistory, Course +from App.controllers import ( + create_course, + create_prereq, + getPrereqCodes, + create_program, + create_programCourse, + get_all_programCourses, + get_program_by_name, + programCourses_SortedbyRating, + programCourses_SortedbyHighestCredits +) + + +class ProgramCoursesUnitTests(unittest.TestCase): + def test_new_prerequisite(self): + prereq=Prerequisites("INFO2605","Introduction to Information Technology Concepts") + assert prereq.prereq_courseCode=="INFO2605" + + def test_prerequisite_toJSON(self): + prereq=Prerequisites("INFO2605","Introduction to Information Technology Concepts") + prereq_json=prereq.get_json() + self.assertDictEqual(prereq_json,{'prereq_id': None, 'prerequisite_courseCode': 'INFO2605', 'prerequisite_course': 'Introduction to Information Technology Concepts'}) + + def test_new_program_course(self): + programcourse=ProgramCourses("1","INFO2605","2") + assert programcourse.code=="INFO2605" + + def test_program_course_toJSON(self): + programcourse=ProgramCourses("1","INFO2605","2") + programcourse_json=programcourse.get_json() + self.assertDictEqual(programcourse_json,{'Program Course ID:':None, 'Program ID:':'1','Course Code: ':'INFO2605','Course Type: ':'2'}) + + +@pytest.fixture(autouse=True, scope="module") +def empty_db(): + app = create_app({'TESTING': True, 'SQLALCHEMY_DATABASE_URI': 'sqlite:///test.db'}) + create_db() + yield app.test_client() + db.drop_all() + +class ProgramCoursesIntegrationTests(unittest.TestCase): + + def test_create_prerequisite(self): + file_path="testData/courseData.csv" + create_course(file_path) + + create_prereq("MATH1115","Industrial Statistics") + prereqs=getPrereqCodes("Industrial Statistics") + self.assertEqual(['MATH1115'],prereqs) + + def test_create_program_requirement(self): + program=create_program("Computer Science and Statistics",51,30,9) + create_programCourse("Computer Science and Statistics","MATH1115",1) + program_courses=get_all_programCourses("Computer Science and Statistics") + assert any(course.code == "MATH1115" for course in program_courses) + + def test_programCourses_sorted_by_credits(self): + create_programCourse("Computer Science and Statistics","INFO2606",2) + program=get_program_by_name("Computer Science and Statistics") + credits_sorted=programCourses_SortedbyHighestCredits(program.id) + self.assertListEqual(credits_sorted,['INFO2606', 'MATH1115']) + + def test_programCourses_sorted_by_rating(self): + create_programCourse("Computer Science and Statistics","MATH2250",1) + program=get_program_by_name("Computer Science and Statistics") + rating_list=programCourses_SortedbyRating(program.id) + self.assertListEqual(rating_list,['MATH1115', 'INFO2606', 'MATH2250']) \ No newline at end of file diff --git a/wsgi.py b/wsgi.py index 9ea59b8cd..fa7b41fbe 100644 --- a/wsgi.py +++ b/wsgi.py @@ -196,19 +196,25 @@ def add_offered_course(code): ''' Test Commands ''' - +usercode=programCoursescode=0 test = AppGroup('test', help='Testing commands') @test.command("user", help="Run User tests") @click.argument("type", default="all") def user_tests_command(type): if type == "unit": - sys.exit(pytest.main(["-k", "UserUnitTests"])) + usercode=pytest.main(["-k", "UserUnitTests"]) + programCoursescode=(pytest.main(["App/tests/test_programCourses.py::ProgramCoursesUnitTests"])) elif type == "int": - sys.exit(pytest.main(["-k", "UserIntegrationTests"])) + usercode=pytest.main(["-k", "UserIntegrationTests"]) + programCoursescode=(pytest.main(["App/tests/test_programCourses.py::ProgramCoursesIntegrationTests"])) else: - sys.exit(pytest.main(["-k", "App"])) - + usercode=pytest.main(["-k", "App"]) + programCoursescode=(pytest.main(["App/tests/test_programCourses.py"])) + +status=usercode + programCoursescode +if(status==1): + sys.exit(status) app.cli.add_command(test) ################################################################# From eafcd597f71101889b9b850dc7661d197bab7c3f Mon Sep 17 00:00:00 2001 From: ashleyjacob Date: Thu, 19 Oct 2023 10:42:46 +0000 Subject: [PATCH 82/90] all programCourse and prereq tests working --- App/tests/test_programCourses.py | 9 +++--- wsgi.py | 52 +++++++++++++++++++++++++++----- 2 files changed, 49 insertions(+), 12 deletions(-) diff --git a/App/tests/test_programCourses.py b/App/tests/test_programCourses.py index 7f8805d4d..10b7e615a 100644 --- a/App/tests/test_programCourses.py +++ b/App/tests/test_programCourses.py @@ -12,7 +12,7 @@ get_all_programCourses, get_program_by_name, programCourses_SortedbyRating, - programCourses_SortedbyHighestCredits + programCourses_SortedbyHighestCredits, ) @@ -46,9 +46,10 @@ def empty_db(): class ProgramCoursesIntegrationTests(unittest.TestCase): def test_create_prerequisite(self): - file_path="testData/courseData.csv" - create_course(file_path) - + create_course("MATH1115", "Fundamental Mathematics for the General Sciences 1",1,6,[]) + create_course("MATH2250", "Industrial Statistics",4,3,[]) + create_course("INFO2606", "Internship",1,6,[]) + create_prereq("MATH1115","Industrial Statistics") prereqs=getPrereqCodes("Industrial Statistics") self.assertEqual(['MATH1115'],prereqs) diff --git a/wsgi.py b/wsgi.py index fa7b41fbe..e509da377 100644 --- a/wsgi.py +++ b/wsgi.py @@ -13,7 +13,7 @@ create_program, get_all_OfferedCodes, get_core_credits, - create_course, + createCoursesfromFile, get_course_by_courseCode, get_prerequisites, get_all_courses, @@ -48,7 +48,7 @@ def initialize(): db.drop_all() db.create_all() create_user('bob', 'bobpass') - create_course('testData/courseData.csv') + createCoursesfromFile('testData/courseData.csv') create_program("Computer Science Major", 69, 15, 9) create_student(816, "boo", "testing", "Computer Science Major") create_staff("adminpass","999", "admin") @@ -212,6 +212,41 @@ def user_tests_command(type): usercode=pytest.main(["-k", "App"]) programCoursescode=(pytest.main(["App/tests/test_programCourses.py"])) +@test.command("course", help="Run Course tests") +@click.argument("type", default="all") +def courses_tests_command(type): + if type == "unit": + sys.exit(pytest.main(["App/tests/courses.py::CourseUnitTests"])) + + elif type == "int": + sys.exit(pytest.main(["App/tests/courses.py::CourseIntegrationTests"])) + + else: + sys.exit(pytest.main(["App/tests/courses.py"])) + + + +@test.command("program", help="Run Program tests") +@click.argument("type", default="all") +def courses_tests_command(type): + if type == "unit": + sys.exit(pytest.main(["App/tests/program.py::ProgramUnitTests"])) + elif type == "int": + sys.exit(pytest.main(["App/tests/program.py::ProgramIntegrationTests"])) + else: + sys.exit(pytest.main(["App/tests/program.py"])) + + +@test.command("staff", help="Run Staff tests") +@click.argument("type", default="all") +def courses_tests_command(type): + if type == "unit": + sys.exit(pytest.main(["App/tests/staff.py::StaffUnitTests"])) + elif type == "int": + sys.exit(pytest.main(["App/tests/staff.py::StaffIntegrationTests"])) + else: + sys.exit(pytest.main(["App/tests/staff.py"])) + status=usercode + programCoursescode if(status==1): sys.exit(status) @@ -285,11 +320,11 @@ def addProgramCourse(programname): course = AppGroup('course', help = 'Program object commands') -@course.command('create', help='Create a new course') -@click.argument('file_path') -def create_course_command(file_path): - newcourse = create_course(file_path) - print(f'Course created with course code "{newcourse.courseCode}", name "{newcourse.courseName}", credits "{newcourse.credits}", ratings "{newcourse.rating}" and prerequites "{newcourse.prerequisites}"') +# @course.command('create', help='Create a new course') +# @click.argument('file_path') +# def create_course_command(file_path): +# newcourse = create_course(file_path) +# print(f'Course created with course code "{newcourse.courseCode}", name "{newcourse.courseName}", credits "{newcourse.credits}", ratings "{newcourse.rating}" and prerequites "{newcourse.prerequisites}"') @course.command('prereqs', help='Create a new course') @@ -302,7 +337,8 @@ def create_course_command(code): @click.argument('code', type=str) def get_course(code): course = get_course_by_courseCode(code) - print(f'Course Name: {course.courseName}') if course else print(f'error') + course_json = course.get_json() + print(f'{course_json}') if course else print(f'error') @course.command('getprereqs', help='Get all prerequistes for a course') @click.argument('code', type=str) From 7bed6e7245e6df23c5166bff3db4e1ffa9089b7f Mon Sep 17 00:00:00 2001 From: ashleyjacob Date: Thu, 19 Oct 2023 17:37:20 +0000 Subject: [PATCH 83/90] adjusted views so postman tests match api spec --- App/controllers/coursesOfferedPerSem.py | 2 +- App/views/index.py | 4 ++-- App/views/staff.py | 8 ++++---- App/views/student.py | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/App/controllers/coursesOfferedPerSem.py b/App/controllers/coursesOfferedPerSem.py index b10ec11ff..d82985c6e 100644 --- a/App/controllers/coursesOfferedPerSem.py +++ b/App/controllers/coursesOfferedPerSem.py @@ -8,7 +8,7 @@ def addSemesterCourses(courseCode): semCourses = CoursesOfferedPerSem(courseCode) db.session.add(semCourses) db.session.commit() - return course + return semCourses else: print("Course not found") diff --git a/App/views/index.py b/App/views/index.py index 197763395..0f7ca6adc 100644 --- a/App/views/index.py +++ b/App/views/index.py @@ -1,6 +1,6 @@ from flask import Blueprint, redirect, render_template, request, send_from_directory, jsonify from App.models import db -from App.controllers import (create_course, create_staff) +from App.controllers import (create_course, create_staff,createCoursesfromFile) index_views = Blueprint('index_views', __name__, template_folder='../templates') @@ -13,7 +13,7 @@ def init(): db.drop_all() db.create_all() create_staff("adminpass","999", "admin") - create_course('testData/courseData.csv') + createCoursesfromFile('testData/courseData.csv') return jsonify(message='staff created, courses created, db initialized!') @index_views.route('/health', methods=['GET']) diff --git a/App/views/staff.py b/App/views/staff.py index 6f9c771cb..91b134725 100644 --- a/App/views/staff.py +++ b/App/views/staff.py @@ -1,7 +1,7 @@ from flask import Blueprint, render_template, jsonify, request, send_from_directory, flash, redirect, url_for from flask_jwt_extended import jwt_required, current_user as jwt_current_user from flask_login import current_user, login_required -from App.models import Program +from App.models import Program, ProgramCourses from.index import index_views @@ -29,7 +29,7 @@ def getOfferedCourses(): return jsonify({'message': 'You are unauthorized to perform this action. Please login with Staff credentials.'}), 401 listing=get_all_OfferedCodes() - return jsonify(listing), 200 + return jsonify({'message':'Success', 'offered_courses':listing}), 200 @staff_views.route('/staff/program', methods=['POST']) @login_required @@ -103,7 +103,7 @@ def addProgramRequirements(): return jsonify({'message': 'Invalid course type. Core (1) Elective (2) Foundation (3)'}), 400 response=create_programCourse(name, code, num) - return jsonify({'message': response}), 200 + return jsonify({'message': response.get_json()}), 200 @staff_views.route('/staff/addOfferedCourse', methods=['POST']) @@ -125,6 +125,6 @@ def addCourse(): course = addSemesterCourses(courseCode) if course: - return jsonify({'message': f"Course {courseCode} added"}), 200 + return jsonify(course.get_json()), 200 else: return jsonify({'message': "Course addition unsucessful"}), 400 \ No newline at end of file diff --git a/App/views/student.py b/App/views/student.py index b514508ac..927928cc5 100644 --- a/App/views/student.py +++ b/App/views/student.py @@ -35,7 +35,7 @@ def create_student_route(): student = get_student_by_id(student_id) if student: - return jsonify({'Error': 'Student ID taken'}), 400 + return jsonify({'Error': 'Student id found'}), 400 program = get_program_by_name(programname) if not program: From 7c9ced153e8ed594bc54b37d312a2bc0da66550d Mon Sep 17 00:00:00 2001 From: JervalThomas Date: Thu, 19 Oct 2023 16:00:51 -0400 Subject: [PATCH 84/90] Student and student course history unit and integration test finished --- App/tests/test_app.py | 192 +----------------------------------------- wsgi.py | 20 +++++ 2 files changed, 21 insertions(+), 191 deletions(-) diff --git a/App/tests/test_app.py b/App/tests/test_app.py index a63b1884c..154d04b48 100644 --- a/App/tests/test_app.py +++ b/App/tests/test_app.py @@ -17,18 +17,11 @@ create_student, addCoursetoHistory, create_program, - addCourseToPlan, create_course, - addSemesterCourses, - getCourseFromCoursePlan, - removeCourse, enroll_in_programme, get_all_students_json, update_student, - get_student_by_id, getCompletedCourses, - create_CoursePlan, - view_course_plan ) @@ -96,190 +89,7 @@ def test_get_all_users_json(self): self.assertListEqual([{"id": 1, "username": "bob"}, { "id": 2, "username": "rick"}], users_json) - # Tests data changes in the database def test_update_user(self): update_user(1, "ronnie") user = get_user(1) - assert user.username == "ronnie" - - -class StudentUnitTest(unittest.TestCase): - def setUp(self): - app = create_app( - {'TESTING': True, 'SQLALCHEMY_DATABASE_URI': 'sqlite:///test.db'}) - self.app = app.test_client() - - with app.app_context(): - create_db() - db.create_all() - - def tearDown(self): - with self.app: - db.session.remove() - db.drop_all() - db.engine.dispose() - - def test_create_student(self): - program = create_program("Computer Science Major", 3, 4, 5) - student = create_student( - "816025522", "Password", "Jerval", program.name) - assert student.name == "Jerval" - - def test_get_all_student_json(self): - program = create_program("Computer Science Major", 3, 4, 5) - create_student("816025522", "Password", "Jerval", program.name) - users_json = get_all_students_json() - self.assertListEqual( - [{"name": "Jerval", "student_id": "816025522", "program": 1}], users_json) - - def test_update_student(self): - program = create_program("Computer Science Major", 3, 4, 5) - create_student("816025522", "Password", "Jerval", program.name) - student = update_student("816025522", "Bill") - assert student.name == "Bill" - - -class StudentIntegrationTests(unittest.TestCase): - - def setUp(self): - app = create_app( - {'TESTING': True, 'SQLALCHEMY_DATABASE_URI': 'sqlite:///test.db'}) - self.app = app.test_client() - - with app.app_context(): - create_db() - db.create_all() - - def tearDown(self): - with self.app: - db.session.remove() - db.drop_all() - db.engine.dispose() - - def test_create_student(self): - program = create_program("Computer Science Major", 3, 4, 5) - student = create_student( - "816025522", "Password", "Jerval", program.name) - assert student.name == "Jerval" - - def test_add_course_to_plan(self): - course_code = "MATH2250" - create_course( - "/Users/jervalthomas/Desktop/Programming /Year 4 Sem 1/COMP 3613/flaskmvc/testData/courseData.csv") - addSemesterCourses(course_code) - program = create_program("Computer Science Major", 3, 4, 5) - student = create_student( - "816025522", "Password", "Jerval", program.name) - self.assertTrue(addCourseToPlan(student, course_code)) - - def test_remove_course_from_plan(self): - course_code = "MATH2250" - create_course( - "/Users/jervalthomas/Desktop/Programming /Year 4 Sem 1/COMP 3613/flaskmvc/testData/courseData.csv") - addSemesterCourses(course_code) - program = create_program("Computer Science Major", 3, 4, 5) - student = create_student( - "816025522", "Password", "Jerval", program.name) - plan = create_CoursePlan(1) - addSemesterCourses(course_code) - addCourseToPlan(student, course_code) - enroll_in_programme(student.id, 1) - removeCourse(student, course_code) - course_from_course_plan = getCourseFromCoursePlan(plan.planId, course_code) - self.assertEqual(course_from_course_plan.planId, 1) - self.assertEqual(course_from_course_plan.code, "MATH2250") - - - def test_enroll_in_programme(self): - create_program("Computer Science Major", 3, 4, 5) - student = create_student( - "816025522", "Password", "Jerval", "Computer Science Major") - enroll_in_programme(student.id, 1) - assert enroll_in_programme(student.id, 1) == 1 - - def test_view_course_plan(self): - course_code = "MATH2250" - create_course( - "/Users/jervalthomas/Desktop/Programming /Year 4 Sem 1/COMP 3613/flaskmvc/testData/courseData.csv") - addSemesterCourses(course_code) - program = create_program("Computer Science Major", 3, 4, 5) - student = create_student( - "816025522", "Password", "Jerval", program.name) - create_CoursePlan(1) - addSemesterCourses(course_code) - addCourseToPlan(student, course_code) - enroll_in_programme(student.id, 1) - plan_json = view_course_plan(student) - self.assertListEqual( - [{"name": "Jerval", "student_id": "816025522", "program": 1}], plan_json) - - -class CourseHistoryUnitTest(unittest.TestCase): - - def setUp(self): - app = create_app( - {'TESTING': True, 'SQLALCHEMY_DATABASE_URI': 'sqlite:///test.db'}) - self.app = app.test_client() - - with app.app_context(): - create_db() - db.create_all() - - def tearDown(self): - with self.app: - db.session.remove() - db.drop_all() - db.engine.dispose() - - def test_create_course_history(self): - student_course_history = StudentCourseHistory(123, 'MATH1115') - - # Assert that the attributes are set correctly - self.assertEqual(student_course_history.studentID, 123) - self.assertEqual(student_course_history.code, 'MATH1115') - - def test_get_json(self): - create_program("Computer Science Major", 3, 4, 5) - create_course( - "/Users/jervalthomas/Desktop/Programming /Year 4 Sem 1/COMP 3613/flaskmvc/testData/courseData.csv") - student = create_student("816025522", "Password", - "Jerval", "Computer Science Major") - student_course_history = StudentCourseHistory(123, 'MATH1115') - addCoursetoHistory(student.id, "MATH1115") - - result = student_course_history.get_json() - - expected_result = {"Program ID": None, "Course Code": "MATH1115"} - - self.assertDictEqual(expected_result, result) - - -class CourseHistoryIntegrationTests(unittest.TestCase): - - def setUp(self): - app = create_app( - {'TESTING': True, 'SQLALCHEMY_DATABASE_URI': 'sqlite:///test.db'}) - self.app = app.test_client() - - with app.app_context(): - create_db() - db.create_all() - - def tearDown(self): - with self.app: - db.session.remove() - db.drop_all() - db.engine.dispose() - - def test_add_Course_to_History(self): - create_program("Computer Science Major", 3, 4, 5) - student = create_student( - "816025522", "Password", "Jerval", "Computer Science Major") - create_course( - "/Users/jervalthomas/Desktop/Programming /Year 4 Sem 1/COMP 3613/flaskmvc/testData/courseData.csv") - addCoursetoHistory(student.id, "INFO1601") - completed_courses = getCompletedCourses(student.id) - assert len(completed_courses) == 1 - for course_history in completed_courses: - self.assertIsInstance(course_history, StudentCourseHistory) - self.assertEqual(course_history.studentID, student.id) + assert user.username == "ronnie" \ No newline at end of file diff --git a/wsgi.py b/wsgi.py index fa2eab189..dc6f4db3d 100644 --- a/wsgi.py +++ b/wsgi.py @@ -244,6 +244,26 @@ def courses_tests_command(type): else: sys.exit(pytest.main(["App/tests/staff.py"])) +@test.command("student", help="Run Program tests") +@click.argument("type", default="all") +def courses_tests_command(type): + if type == "unit": + sys.exit(pytest.main(["App/tests/student.py::StudentUnitTest"])) + elif type == "int": + sys.exit(pytest.main(["App/tests/student.py::StudentIntegrationTests"])) + else: + sys.exit(pytest.main(["App/tests/student.py"])) + +@test.command("studentCH", help="Run Student Course History tests") +@click.argument("type", default="all") +def courses_tests_command(type): + if type == "unit": + sys.exit(pytest.main(["App/tests/studentCourseHistory.py::CourseHistoryUnitTest"])) + elif type == "int": + sys.exit(pytest.main(["App/tests/studentCourseHistory.py::CourseHistoryIntegrationTests"])) + else: + sys.exit(pytest.main(["App/tests/studentCourseHistory.py"])) + app.cli.add_command(test) ################################################################# From a51d5aca3e5108a936b0c2dcdf8e6bf2e7e3968f Mon Sep 17 00:00:00 2001 From: JervalThomas Date: Thu, 19 Oct 2023 16:02:10 -0400 Subject: [PATCH 85/90] Student and student course history unit and integration test finished --- .vscode/settings.json | 5 ++ App/tests/student.py | 128 ++++++++++++++++++++++++++++++ App/tests/studentCourseHistory.py | 72 +++++++++++++++++ 3 files changed, 205 insertions(+) create mode 100644 .vscode/settings.json create mode 100644 App/tests/student.py create mode 100644 App/tests/studentCourseHistory.py diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..86b58d041 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "python.testing.unittestArgs": ["-v", "-s", "./App", "-p", "test_*.py"], + "python.testing.pytestEnabled": false, + "python.testing.unittestEnabled": true +} diff --git a/App/tests/student.py b/App/tests/student.py new file mode 100644 index 000000000..768033673 --- /dev/null +++ b/App/tests/student.py @@ -0,0 +1,128 @@ +import os +import tempfile +import pytest +import logging +import unittest +from werkzeug.security import check_password_hash, generate_password_hash + +from App.main import create_app +from App.database import db, create_db +from App.models import User, Student, Program, StudentCourseHistory +from App.controllers import ( + create_user, + get_all_users_json, + login, + get_user, + update_user, + create_student, + addCoursetoHistory, + create_program, + create_course, + enroll_in_programme, + get_all_students_json, + update_student, + getCompletedCourses, +) + + +LOGGER = logging.getLogger(__name__) + + +class StudentUnitTest(unittest.TestCase): + + def test_new_student(self): + student = Student("01234", "johnpass", "John Doe", 1) + assert student.name == "John Doe" + + def test_student_toJSON(self): + student = Student("01234", "johnpass", "John Doe", 1) + student_json = student.get_json() + self.assertDictEqual( + {"name": "John Doe", "student_id": "01234", "program": 1}, student_json) + + +class StudentIntegrationTests(unittest.TestCase): + + def setUp(self): + app = create_app( + {'TESTING': True, 'SQLALCHEMY_DATABASE_URI': 'sqlite:///test.db'}) + self.app = app.test_client() + + with app.app_context(): + create_db() + db.create_all() + + def tearDown(self): + with self.app: + db.session.remove() + db.drop_all() + db.engine.dispose() + + def test_create_student(self): + program = create_program("Computer Science Major", 3, 4, 5) + student = create_student( + "01234", "johnpass", "John Doe", program.name) + assert student.name == "John Doe" + + def test_get_all_student_json(self): + program = create_program("Computer Science Major", 3, 4, 5) + create_student("01234", "johnpass", "John Doe", program.name) + users_json = get_all_students_json() + self.assertListEqual( + [{"name": "John Doe", "student_id": "01234", "program": 1}], users_json) + + def test_update_student(self): + program = create_program("Computer Science Major", 3, 4, 5) + create_student("01234", "johnpass", "John Doe", program.name) + student = update_student("01234", "Bill") + assert student.name == "Bill" + + # def test_add_course_to_plan(self): + # course_code = "INFO2605" + # prereqs = [] + # create_course("INFO2605", "Professional Ethics and Law", 3, 4, prereqs) + # addSemesterCourses(course_code) + # program = create_program("Computer Science Major", 3, 4, 5) + # student = create_student( + # "01234", "johnpass", "John Doe", program.name) + # self.assertTrue(addCourseToPlan(student, course_code)) + + # def test_remove_course_from_plan(self): + # course_code = "INFO2605" + # prereqs = [] + # create_course("INFO2605", "Professional Ethics and Law", 3, 4, prereqs) + # addSemesterCourses(course_code) + # program = create_program("Computer Science Major", 3, 4, 5) + # student = create_student( + # "01234", "johnpass", "John Doe", program.name) + # plan = create_CoursePlan(1) + # addSemesterCourses(course_code) + # addCourseToPlan(student, course_code) + # enroll_in_programme(student.id, 1) + # removeCourse(student, course_code) + # course_from_course_plan = getCourseFromCoursePlan(plan.planId, course_code) + # self.assertEqual(course_from_course_plan.planId, 1) + # self.assertEqual(course_from_course_plan.code, "INFO2605") + + def test_enroll_in_programme(self): + program = create_program("Computer Science Major", 3, 4, 5) + student = create_student( + "01234", "johnpass", "John Doe", program.name) + enroll_in_programme(student.id, 1) + assert enroll_in_programme(student.id, 1) == 1 + + # def test_view_course_plan(self): + # course_code = "MATH2250" + # create_course( + # "/Users/jervalthomas/Desktop/Programming /Year 4 Sem 1/COMP 3613/flaskmvc/testData/courseData.csv") + # addSemesterCourses(course_code) + # program = create_program("Computer Science Major", 3, 4, 5) + # student = create_student( + # "816025522", "Password", "Jerval", program.name) + # create_CoursePlan(1) + # addSemesterCourses(course_code) + # addCourseToPlan(student, course_code) + # enroll_in_programme(student.id, 1) + # plan_json = view_course_plan(student) + # self.assertListEqual( + # [{"name": "Jerval", "student_id": "816025522", "program": 1}], plan_json) \ No newline at end of file diff --git a/App/tests/studentCourseHistory.py b/App/tests/studentCourseHistory.py new file mode 100644 index 000000000..abf7e473b --- /dev/null +++ b/App/tests/studentCourseHistory.py @@ -0,0 +1,72 @@ +import os +import tempfile +import pytest +import logging +import unittest +from werkzeug.security import check_password_hash, generate_password_hash + +from App.main import create_app +from App.database import db, create_db +from App.models import User, Student, Program, StudentCourseHistory +from App.controllers import ( + create_user, + get_all_users_json, + login, + get_user, + update_user, + create_student, + addCoursetoHistory, + create_program, + create_course, + enroll_in_programme, + get_all_students_json, + update_student, + getCompletedCourses, +) + + +LOGGER = logging.getLogger(__name__) + +class CourseHistoryUnitTest(unittest.TestCase): + + def test_create_course_history(self): + student_course_history = StudentCourseHistory(123, "INFO2605") + self.assertEqual(student_course_history.studentID, 123) + self.assertEqual(student_course_history.code, "INFO2605") + + def test_course_history_toJSON(self): + student_course_history = StudentCourseHistory(123, 'MATH1115') + result = student_course_history.get_json() + expected_result = {"Program ID": None, "Course Code": "MATH1115"} + self.assertDictEqual(expected_result, result) + + +class CourseHistoryIntegrationTests(unittest.TestCase): + + def setUp(self): + app = create_app( + {'TESTING': True, 'SQLALCHEMY_DATABASE_URI': 'sqlite:///test.db'}) + self.app = app.test_client() + + with app.app_context(): + create_db() + db.create_all() + + def tearDown(self): + with self.app: + db.session.remove() + db.drop_all() + db.engine.dispose() + + def test_add_Course_to_History(self): + program = create_program("Computer Science Major", 3, 4, 5) + student = create_student( + "01234", "johnpass", "John Doe", program.name) + prereqs = [] + create_course("INFO2605", "Professional Ethics and Law", 3, 4, prereqs) + addCoursetoHistory(student.id, "INFO2605") + completed_courses = getCompletedCourses(student.id) + assert len(completed_courses) == 1 + for course_history in completed_courses: + self.assertIsInstance(course_history, StudentCourseHistory) + self.assertEqual(course_history.studentID, student.id) From d2d8bf145782022e39c8c206f9cf028377e969f1 Mon Sep 17 00:00:00 2001 From: Jerrelle Johnson Date: Thu, 19 Oct 2023 16:17:22 -0400 Subject: [PATCH 86/90] updates --- App/controllers/courses.py | 1 - App/controllers/studentCourseHistory.py | 2 -- 2 files changed, 3 deletions(-) diff --git a/App/controllers/courses.py b/App/controllers/courses.py index a8df358b8..3d285f0f1 100644 --- a/App/controllers/courses.py +++ b/App/controllers/courses.py @@ -46,7 +46,6 @@ def createCoursesfromFile(file_path): return False print("Courses added successfully.") - return course def get_course_by_courseCode(code): return Course.query.filter_by(courseCode=code).first() diff --git a/App/controllers/studentCourseHistory.py b/App/controllers/studentCourseHistory.py index 1f0001549..a93a68efb 100644 --- a/App/controllers/studentCourseHistory.py +++ b/App/controllers/studentCourseHistory.py @@ -10,8 +10,6 @@ def addCoursetoHistory(studentid, code): completed = StudentCourseHistory(studentid, code) db.session.add(completed) db.session.commit() - print("Course added successfully") - return else: print("Course doesn't exist") else: From e054a20f9467fefbae8bc05a44b7baeb31807a62 Mon Sep 17 00:00:00 2001 From: Jerrelle Johnson Date: Thu, 19 Oct 2023 16:17:59 -0400 Subject: [PATCH 87/90] updates --- App/controllers/studentCourseHistory.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/App/controllers/studentCourseHistory.py b/App/controllers/studentCourseHistory.py index a93a68efb..cb157ee69 100644 --- a/App/controllers/studentCourseHistory.py +++ b/App/controllers/studentCourseHistory.py @@ -14,8 +14,7 @@ def addCoursetoHistory(studentid, code): print("Course doesn't exist") else: print("Student doesn't exist") - - + def getCompletedCourses(id): return StudentCourseHistory.query.filter_by(studentID=id).all() From 8f3f62cc7b2dcc36a2952f40636853726802c664 Mon Sep 17 00:00:00 2001 From: ashleyjacob Date: Fri, 20 Oct 2023 17:50:44 +0000 Subject: [PATCH 88/90] merged tests - prereqs + courses, program req + program --- App/tests/courses.py | 28 +++++++++++- App/tests/program.py | 39 +++++++++++++++-- App/tests/test_programCourses.py | 73 -------------------------------- wsgi.py | 14 ++---- 4 files changed, 66 insertions(+), 88 deletions(-) delete mode 100644 App/tests/test_programCourses.py diff --git a/App/tests/courses.py b/App/tests/courses.py index 27ab8687e..2d0a17b63 100644 --- a/App/tests/courses.py +++ b/App/tests/courses.py @@ -1,6 +1,6 @@ import pytest, unittest -from App.models import Course -from App.controllers import create_course, courses_Sorted_byRating_Objects, get_course_by_courseCode +from App.models import Course, Prerequisites +from App.controllers import create_course, courses_Sorted_byRating_Objects, get_course_by_courseCode, create_prereq, getPrereqCodes from App.main import create_app from App.database import db, create_db @@ -34,7 +34,22 @@ def test_course_json(self): 'Course Rating: ': rating, 'No. of Credits: ': credits }) + + + def test_new_prerequisite(self): + prereq=Prerequisites("INFO2605","Introduction to Information Technology Concepts") + assert prereq.prereq_courseCode=="INFO2605" + + def test_prerequisite_toJSON(self): + prereq=Prerequisites("INFO2605","Introduction to Information Technology Concepts") + prereq_json=prereq.get_json() + self.assertDictEqual(prereq_json,{ + 'prereq_id': None, + 'prerequisite_courseCode': 'INFO2605', + 'prerequisite_course': 'Introduction to Information Technology Concepts' + }) + @pytest.fixture(autouse=True, scope="module") def empty_db(): app = create_app({'TESTING': True, 'SQLALCHEMY_DATABASE_URI': 'sqlite:///test.db'}) @@ -66,3 +81,12 @@ def test_courses_sorted_by_rating(self): for i in range(len(sortedCourses) - 1): self.assertLessEqual(sortedCourses[i].rating, sortedCourses[i + 1].rating) + + + def test_create_prerequisite(self): + create_course("MATH1115", "Fundamental Mathematics for the General Sciences 1",1,6,[]) + create_course("MATH2250", "Industrial Statistics",4,3,[]) + + create_prereq("MATH1115","Industrial Statistics") + prereqs=getPrereqCodes("Industrial Statistics") + self.assertEqual(['MATH1115'],prereqs) diff --git a/App/tests/program.py b/App/tests/program.py index 7fd762af4..e8784dc24 100644 --- a/App/tests/program.py +++ b/App/tests/program.py @@ -1,8 +1,8 @@ import unittest, pytest -from App.models import Program +from App.models import Program, ProgramCourses from App.main import create_app from App.database import db, create_db -from App.controllers import create_program, get_program_by_name +from App.controllers import create_program, get_program_by_name,create_course, create_programCourse, get_all_programCourses, programCourses_SortedbyRating,programCourses_SortedbyHighestCredits class ProgramUnitTests(unittest.TestCase): @@ -34,6 +34,18 @@ def test_program_toJSON(self): 'Foundation Credits: ': foun_credits, }) + def test_new_program_course(self): + programcourse=ProgramCourses("1","INFO2605","2") + assert programcourse.code=="INFO2605" + + def test_program_course_toJSON(self): + programcourse=ProgramCourses("1","INFO2605","2") + programcourse_json=programcourse.get_json() + self.assertDictEqual(programcourse_json,{'Program Course ID:':None, 'Program ID:':'1','Course Code: ':'INFO2605','Course Type: ':'2'}) + + + + @pytest.fixture(autouse=True, scope="module") def empty_db(): app = create_app({'TESTING': True, 'SQLALCHEMY_DATABASE_URI': 'sqlite:///test.db'}) @@ -44,4 +56,25 @@ def empty_db(): class ProgramIntegrationTests(unittest.TestCase): def test_create_program(self): program = create_program("IT", 69, 15, 9) - assert get_program_by_name("IT") != None \ No newline at end of file + assert get_program_by_name("IT") != None + + def test_create_program_requirement(self): + create_course("MATH1115", "Fundamental Mathematics for the General Sciences 1",1,6,[]) + create_course("MATH2250", "Industrial Statistics",4,3,[]) + create_course("INFO2606", "Internship",1,6,[]) + + create_programCourse("IT","MATH1115",1) + program_courses=get_all_programCourses("IT") + assert any(course.code == "MATH1115" for course in program_courses) + + def test_programCourses_sorted_by_credits(self): + create_programCourse("IT","INFO2606",2) + program=get_program_by_name("IT") + credits_sorted=programCourses_SortedbyHighestCredits(program.id) + self.assertListEqual(credits_sorted,['INFO2606', 'MATH1115']) + + def test_programCourses_sorted_by_rating(self): + create_programCourse("IT","MATH2250",1) + program=get_program_by_name("IT") + rating_list=programCourses_SortedbyRating(program.id) + self.assertListEqual(rating_list,['MATH1115', 'INFO2606', 'MATH2250']) \ No newline at end of file diff --git a/App/tests/test_programCourses.py b/App/tests/test_programCourses.py deleted file mode 100644 index 10b7e615a..000000000 --- a/App/tests/test_programCourses.py +++ /dev/null @@ -1,73 +0,0 @@ -import pytest, unittest - -from App.main import create_app -from App.database import db, create_db -from App.models import Prerequisites, ProgramCourses, StudentCourseHistory, Course -from App.controllers import ( - create_course, - create_prereq, - getPrereqCodes, - create_program, - create_programCourse, - get_all_programCourses, - get_program_by_name, - programCourses_SortedbyRating, - programCourses_SortedbyHighestCredits, -) - - -class ProgramCoursesUnitTests(unittest.TestCase): - def test_new_prerequisite(self): - prereq=Prerequisites("INFO2605","Introduction to Information Technology Concepts") - assert prereq.prereq_courseCode=="INFO2605" - - def test_prerequisite_toJSON(self): - prereq=Prerequisites("INFO2605","Introduction to Information Technology Concepts") - prereq_json=prereq.get_json() - self.assertDictEqual(prereq_json,{'prereq_id': None, 'prerequisite_courseCode': 'INFO2605', 'prerequisite_course': 'Introduction to Information Technology Concepts'}) - - def test_new_program_course(self): - programcourse=ProgramCourses("1","INFO2605","2") - assert programcourse.code=="INFO2605" - - def test_program_course_toJSON(self): - programcourse=ProgramCourses("1","INFO2605","2") - programcourse_json=programcourse.get_json() - self.assertDictEqual(programcourse_json,{'Program Course ID:':None, 'Program ID:':'1','Course Code: ':'INFO2605','Course Type: ':'2'}) - - -@pytest.fixture(autouse=True, scope="module") -def empty_db(): - app = create_app({'TESTING': True, 'SQLALCHEMY_DATABASE_URI': 'sqlite:///test.db'}) - create_db() - yield app.test_client() - db.drop_all() - -class ProgramCoursesIntegrationTests(unittest.TestCase): - - def test_create_prerequisite(self): - create_course("MATH1115", "Fundamental Mathematics for the General Sciences 1",1,6,[]) - create_course("MATH2250", "Industrial Statistics",4,3,[]) - create_course("INFO2606", "Internship",1,6,[]) - - create_prereq("MATH1115","Industrial Statistics") - prereqs=getPrereqCodes("Industrial Statistics") - self.assertEqual(['MATH1115'],prereqs) - - def test_create_program_requirement(self): - program=create_program("Computer Science and Statistics",51,30,9) - create_programCourse("Computer Science and Statistics","MATH1115",1) - program_courses=get_all_programCourses("Computer Science and Statistics") - assert any(course.code == "MATH1115" for course in program_courses) - - def test_programCourses_sorted_by_credits(self): - create_programCourse("Computer Science and Statistics","INFO2606",2) - program=get_program_by_name("Computer Science and Statistics") - credits_sorted=programCourses_SortedbyHighestCredits(program.id) - self.assertListEqual(credits_sorted,['INFO2606', 'MATH1115']) - - def test_programCourses_sorted_by_rating(self): - create_programCourse("Computer Science and Statistics","MATH2250",1) - program=get_program_by_name("Computer Science and Statistics") - rating_list=programCourses_SortedbyRating(program.id) - self.assertListEqual(rating_list,['MATH1115', 'INFO2606', 'MATH2250']) \ No newline at end of file diff --git a/wsgi.py b/wsgi.py index c369c2fa6..76f5c8fac 100644 --- a/wsgi.py +++ b/wsgi.py @@ -196,21 +196,18 @@ def add_offered_course(code): ''' Test Commands ''' -usercode=programCoursescode=0 + test = AppGroup('test', help='Testing commands') @test.command("user", help="Run User tests") @click.argument("type", default="all") def user_tests_command(type): if type == "unit": - usercode=pytest.main(["-k", "UserUnitTests"]) - programCoursescode=(pytest.main(["App/tests/test_programCourses.py::ProgramCoursesUnitTests"])) + sys.exit(pytest.main(["-k", "UserUnitTests"])) elif type == "int": - usercode=pytest.main(["-k", "UserIntegrationTests"]) - programCoursescode=(pytest.main(["App/tests/test_programCourses.py::ProgramCoursesIntegrationTests"])) + sys.exit(pytest.main(["-k", "UserIntegrationTests"])) else: - usercode=pytest.main(["-k", "App"]) - programCoursescode=(pytest.main(["App/tests/test_programCourses.py"])) + sys.exit(pytest.main(["-k", "App"])) @test.command("course", help="Run Course tests") @click.argument("type", default="all") @@ -268,9 +265,6 @@ def courses_tests_command(type): sys.exit(pytest.main(["App/tests/studentCourseHistory.py"])) -status=usercode + programCoursescode -if(status==1): - sys.exit(status) app.cli.add_command(test) ################################################################# From 4a16730cd232e4d4138f702e7fd3b5634b46f936 Mon Sep 17 00:00:00 2001 From: ashleyjacob Date: Fri, 20 Oct 2023 19:20:19 +0000 Subject: [PATCH 89/90] updated login view --- App/views/auth.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/App/views/auth.py b/App/views/auth.py index f4c14a162..f1fb9eb73 100644 --- a/App/views/auth.py +++ b/App/views/auth.py @@ -35,8 +35,8 @@ def login_action(): user = login(data['username'], data['password']) if user: login_user(user) - return 'user logged in!' - return 'bad username or password given', 401 + return jsonify({"token":jwt_authenticate(data['username'],data['password'])}) + return jsonify({"error":"invalid credentials"}), 401 @auth_views.route('/logout', methods=['GET']) def logout_action(): From 010a931a1c050a1aa1a183e22613f52759c68061 Mon Sep 17 00:00:00 2001 From: Kyle-McIntosh Date: Mon, 23 Oct 2023 22:17:42 -0400 Subject: [PATCH 90/90] Courses and CoursesOffered unit and int test --- App/tests/__init__.py | 4 +- App/tests/coursePlan.py | 170 ++++++++++++++++++++++++++++++ App/tests/coursesOfferedPerSem.py | 68 ++++++++++++ App/tests/test_app.py | 2 +- wsgi.py | 22 +++- 5 files changed, 263 insertions(+), 3 deletions(-) create mode 100644 App/tests/coursePlan.py create mode 100644 App/tests/coursesOfferedPerSem.py diff --git a/App/tests/__init__.py b/App/tests/__init__.py index c3c0114f6..84c894cbf 100644 --- a/App/tests/__init__.py +++ b/App/tests/__init__.py @@ -1,4 +1,6 @@ from .test_app import * from .courses import * from .program import * -from .staff import * \ No newline at end of file +from .staff import * +from .coursePlan import * +from .coursesOfferedPerSem import * \ No newline at end of file diff --git a/App/tests/coursePlan.py b/App/tests/coursePlan.py new file mode 100644 index 000000000..af16c631c --- /dev/null +++ b/App/tests/coursePlan.py @@ -0,0 +1,170 @@ +import pytest, unittest +from App.models import CoursePlan, CoursePlanCourses +from App.controllers import create_CoursePlan, create_student, create_program, addCourseToPlan, enroll_in_programme, addSemesterCourses, generator, createCoursesfromFile, get_program_by_name, getCoursePlan, get_all_courses_by_planid, get_student, create_programCourse, removeCourse +from App.main import create_app +from App.database import db, create_db + +class CoursePlanUnitTests(unittest.TestCase): + + def test_new_courseplan(self): + student_id = "01234" + course_plan = CoursePlan(student_id) + self.assertEqual(course_plan.studentId, student_id) + + def test_courseplan_toJSON(self): + student_id = "01234" + course_plan = CoursePlan(student_id) + course_plan_json = course_plan.get_json() + self.assertDictEqual(course_plan_json, {"planId": None, "studentId": student_id}) + + + def test_new_courseplan_courses(self): + student_id = "01234" + course_plan = CoursePlan(student_id) + course_code = "INFO2605" + courseplan_courses = CoursePlanCourses("1", course_code) + self.assertEqual(courseplan_courses.code, course_code) + + + +@pytest.fixture(autouse=True, scope="module") +def empty_db(): + app = create_app({'TESTING': True, 'SQLALCHEMY_DATABASE_URI': 'sqlite:///test.db'}) + create_db() + yield app.test_client() + db.drop_all() + + +# Integration Tests +class CoursePlanIntegrationTests(unittest.TestCase): + + def test_create_course_plan(self): + # Create a student and program. + program = create_program("Computer Science Major", 69, 15, 9) + student = create_student("1234", "johnpass", "John Doe", program.name) + + #Create courses, semester courses and program coursess + createCoursesfromFile('testData/courseData.csv') + + file_path = "testData/test.txt" + with open(file_path, 'r') as file: + for i, line in enumerate(file): + line = line.strip() + if i ==0: + programName = line + else: + course = line.split(',') + create_programCourse(programName, course[0],int(course[1])) + + file_path1='testData/test2.txt' + with open(file_path1, 'r') as file: + for i, line in enumerate(file): + line = line.strip() + addSemesterCourses(line) + + + plan = create_CoursePlan(student.id) + self.assertIsNotNone(plan) + assert getCoursePlan(student.id) != None + + course_code = "INFO1601" + added_plan = addCourseToPlan(student, course_code) + courseplan_courses = get_all_courses_by_planid("1") + + self.assertIsNotNone(added_plan) + self.assertIn('INFO1601', [course.code for course in courseplan_courses]) + + + def test_remove_course_from_plan(self): + program = get_program_by_name("Computer Science Major") + student = get_student("1234") + plan_id = enroll_in_programme("1234", program.id) + courseplan_courses = get_all_courses_by_planid(plan_id) + self.assertIn('INFO1601', [course.code for course in courseplan_courses]) + removeCourse(student, "INFO1601") + courseplan_courses = get_all_courses_by_planid(plan_id) + self.assertNotIn('INFO1601', [course.code for course in courseplan_courses]) + + + def test_create_fastGraduation_course_plan(self): + program = get_program_by_name("Computer Science Major") + student = get_student("1234") + plan_id = enroll_in_programme("1234", program.id) + + courseplan_courses = get_all_courses_by_planid(plan_id) + course_codes = [course.code for course in courseplan_courses] + for course_code in course_codes: + removeCourse(student, course_code) + + generator(student, "fastest") + courseplan_courses = get_all_courses_by_planid(plan_id) + + print("Courses in Course Plan:") + for course in courseplan_courses: + print(course.code) + + self.assertIsNotNone(courseplan_courses) + self.assertIn('COMP1601', [course.code for course in courseplan_courses]) + + + def test_create_easy_course_plan(self): + program = get_program_by_name("Computer Science Major") + student = get_student("1234") + plan_id = enroll_in_programme("1234", program.id) + + courseplan_courses = get_all_courses_by_planid(plan_id) + course_codes = [course.code for course in courseplan_courses] + for course_code in course_codes: + removeCourse(student, course_code) + + # Create a easy graduation course plan + generator(student, "easy") + courseplan_courses = get_all_courses_by_planid(plan_id) + + self.assertIsNotNone(courseplan_courses) + self.assertIn('COMP1601', [course.code for course in courseplan_courses]) + + def test_create_electives_course_plan(self): + program = get_program_by_name("Computer Science Major") + student = get_student("1234") + plan_id = enroll_in_programme("1234", program.id) + + courseplan_courses = get_all_courses_by_planid(plan_id) + course_codes = [course.code for course in courseplan_courses] + for course_code in course_codes: + removeCourse(student, course_code) + + # Create an electives graduation course plan + generator(student, "electives") + courseplan_courses = get_all_courses_by_planid(plan_id) + + self.assertIsNotNone(courseplan_courses) + self.assertIn('COMP1601', [course.code for course in courseplan_courses]) + + def test_get_course_plan_json(self): + + program = get_program_by_name("Computer Science Major") + student = get_student("1234") + plan_id = enroll_in_programme("1234", program.id) + + courseplan_courses = get_all_courses_by_planid(plan_id) + course_codes = [course.code for course in courseplan_courses] + for course_code in course_codes: + removeCourse(student, course_code) + + course_code = "INFO1601" + added_plan = addCourseToPlan(student, course_code) + courseplan_courses = get_all_courses_by_planid(plan_id) + courseplan = getCoursePlan("1234") + self.assertIsNotNone(added_plan) + self.assertIn('INFO1601', [course.code for course in courseplan_courses]) + + course_plan_json = courseplan.get_json() + + expected_json = { + 'planId': 1, + 'studentId': 1234 + } + self.assertEqual(course_plan_json, expected_json) + + diff --git a/App/tests/coursesOfferedPerSem.py b/App/tests/coursesOfferedPerSem.py new file mode 100644 index 000000000..3ed964b17 --- /dev/null +++ b/App/tests/coursesOfferedPerSem.py @@ -0,0 +1,68 @@ +import pytest, unittest +from App.models import CoursesOfferedPerSem +from App.controllers import addSemesterCourses, create_course, isCourseOffered, get_all_OfferedCodes, delete_all_records +from App.main import create_app +from App.database import db, create_db + + +class CoursesOfferedPerSemUnitTests(unittest.TestCase): + + def test_new_offered_course(self): + course_code = "INFO2605" + offered_course = CoursesOfferedPerSem(course_code) + self.assertEqual(offered_course.code, course_code) + + def test_offered_course_toJSON(self): + course_code = "INFO2605" + offered_course = CoursesOfferedPerSem(course_code) + offered_course_json = offered_course.get_json() + self.assertDictEqual(offered_course_json, {"ID:": None, "Course Code:": course_code}) + +@pytest.fixture(autouse=True, scope="module") +def empty_db(): + app = create_app({'TESTING': True, 'SQLALCHEMY_DATABASE_URI': 'sqlite:///test.db'}) + create_db() + yield app.test_client() + db.drop_all() + +class CoursesOfferedPerSemIntegrationTests(unittest.TestCase): + def test_add_offered_course(self): + prereqs=[] + course_code = "INFO2605" + create_course(course_code, "Professional Ethics and Law", 3, 4, prereqs) + addSemesterCourses(course_code) + self.assertTrue(isCourseOffered(course_code)) + + def test_get_all_offered_courses_json(self): + create_course("MATH2250", "Industrial Statistics",4,3,[]) + create_course("INFO2605", "Professional Ethics and Law", 3, 4, []) + addSemesterCourses("MATH2250") + addSemesterCourses("INFO2605") + offered_courses = get_all_OfferedCodes() + + assert "MATH2250" in offered_courses + assert "INFO2605" in offered_courses + + def test_remove_all_offered(self): + + create_course("MATH2250", "Industrial Statistics", 4, 3, []) + create_course("INFO2605", "Professional Ethics and Law", 3, 4, []) + addSemesterCourses("MATH2250") + addSemesterCourses("INFO2605") + + # Check that courses are offered + assert isCourseOffered("MATH2250") + assert isCourseOffered("INFO2605") + + # Remove all offered courses + delete_all_records() + + # Check that courses are no longer offered + assert not isCourseOffered("MATH2250") + assert not isCourseOffered("INFO2605") + + + + + + diff --git a/App/tests/test_app.py b/App/tests/test_app.py index 154d04b48..f90573b0b 100644 --- a/App/tests/test_app.py +++ b/App/tests/test_app.py @@ -7,7 +7,7 @@ from App.main import create_app from App.database import db, create_db -from App.models import User, Student, Program, StudentCourseHistory +from App.models import User, Student, Program, StudentCourseHistory, CoursePlan from App.controllers import ( create_user, get_all_users_json, diff --git a/wsgi.py b/wsgi.py index 76f5c8fac..be2229779 100644 --- a/wsgi.py +++ b/wsgi.py @@ -220,8 +220,28 @@ def courses_tests_command(type): else: sys.exit(pytest.main(["App/tests/courses.py"])) - +@test.command("coursePlan", help="Run Course Plan tests") +@click.argument("type", default="all") +def courses_tests_command(type): + if type == "unit": + sys.exit(pytest.main(["App/tests/coursePlan.py::CoursePlanUnitTests"])) + elif type == "int": + sys.exit(pytest.main(["App/tests/coursePlan.py::CoursePlanIntegrationTests"])) + else: + sys.exit(pytest.main(["App/tests/coursePlan.py"])) + +#CoursesOfferedPerSemUnitTests +@test.command("coursesOffered", help="Run Courses Offered Per Sem tests") +@click.argument("type", default="all") +def courses_tests_command(type): + if type == "unit": + sys.exit(pytest.main(["App/tests/coursesOfferedPerSem.py::CoursesOfferedPerSemUnitTests"])) + elif type == "int": + sys.exit(pytest.main(["App/tests/coursesOfferedPerSem.py::CoursesOfferedPerSemIntegrationTests"])) + else: + sys.exit(pytest.main(["App/tests/coursesOfferedPerSem.py"])) + @test.command("program", help="Run Program tests") @click.argument("type", default="all")