From c962db628e567d1f54d942b451ef08382cf23c07 Mon Sep 17 00:00:00 2001 From: Andrews3002 Date: Thu, 26 Mar 2026 08:37:38 -0400 Subject: [PATCH 01/37] admin class created --- App/models/admin.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 App/models/admin.py diff --git a/App/models/admin.py b/App/models/admin.py new file mode 100644 index 0000000..28061b1 --- /dev/null +++ b/App/models/admin.py @@ -0,0 +1,15 @@ +from App.database import db +from .user import User + +class Admin(User): + id = db.Column(db.Integer, db.ForeignKey('user.id'), primary_key=True) + + __mapper_args__ = { + 'polymorphic_identity': 'admin' + } + + def __init__(self, username, password): + super().__init__(username, password) + + def get_json(self): + return {**super().get_json(), 'role': 'admin'} \ No newline at end of file From 55a19597e4b8cc30888da7f26751773e7e293511 Mon Sep 17 00:00:00 2001 From: Andrews3002 Date: Thu, 26 Mar 2026 08:39:08 -0400 Subject: [PATCH 02/37] student class created --- App/models/student.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 App/models/student.py diff --git a/App/models/student.py b/App/models/student.py new file mode 100644 index 0000000..3bf6857 --- /dev/null +++ b/App/models/student.py @@ -0,0 +1,15 @@ +from App.database import db +from .user import User + +class Student(User): + id = db.Column(db.Integer, db.ForeignKey('user.id'), primary_key=True) + + __mapper_args__ = { + 'polymorphic_identity': 'student' + } + + def __init__(self, username, password): + super().__init__(username, password) + + def get_json(self): + return {**super().get_json(), 'role': 'student'} \ No newline at end of file From a0a6242ee6ff3a5072458a5bf996178c20125988 Mon Sep 17 00:00:00 2001 From: Andrews3002 Date: Thu, 26 Mar 2026 08:48:59 -0400 Subject: [PATCH 03/37] groupRequest class created --- App/models/groupRequest.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 App/models/groupRequest.py diff --git a/App/models/groupRequest.py b/App/models/groupRequest.py new file mode 100644 index 0000000..c2585cc --- /dev/null +++ b/App/models/groupRequest.py @@ -0,0 +1,18 @@ +from App.database import db +from sqlalchemy.dialects.postgresql import ARRAY + +class GroupRequest(db.Model): + id = db.Column(db.Integer, primary_key=True) + groupName = db.Column(db.String(30), nullable=False, unique=True) + members = db.Column(ARRAY(db.Integer), nullable=False, default=[]) + + def __init__(self, groupName, members: list[int]): + self.groupName = groupName + self.members = members + + def get_json(self): + return { + 'id': self.id, + 'groupName': self.groupName, + 'members': self.members + } \ No newline at end of file From 55ca91ce32e30171cba7e541e551b701377ab65f Mon Sep 17 00:00:00 2001 From: Andrews3002 Date: Thu, 26 Mar 2026 08:50:23 -0400 Subject: [PATCH 04/37] groupRequest class modified --- App/models/groupRequest.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/App/models/groupRequest.py b/App/models/groupRequest.py index c2585cc..41150b4 100644 --- a/App/models/groupRequest.py +++ b/App/models/groupRequest.py @@ -1,10 +1,11 @@ from App.database import db -from sqlalchemy.dialects.postgresql import ARRAY class GroupRequest(db.Model): + __tablename__ = 'group_request' + id = db.Column(db.Integer, primary_key=True) groupName = db.Column(db.String(30), nullable=False, unique=True) - members = db.Column(ARRAY(db.Integer), nullable=False, default=[]) + members = db.Column(db.JSON, nullable=False, default=list) def __init__(self, groupName, members: list[int]): self.groupName = groupName From e9c6b6c64c86991fdee17fb961f15eb2dc50f179 Mon Sep 17 00:00:00 2001 From: Andrews3002 Date: Thu, 26 Mar 2026 09:05:21 -0400 Subject: [PATCH 05/37] group class created --- App/models/group.py | 17 +++++++++++++++++ App/models/groupRequest.py | 2 +- 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 App/models/group.py diff --git a/App/models/group.py b/App/models/group.py new file mode 100644 index 0000000..21a9bf3 --- /dev/null +++ b/App/models/group.py @@ -0,0 +1,17 @@ +from App.database import db + +class Group(db.Model): + id = db.Column(db.Integer, primary_key=True) + groupName = db.Column(db.String(30), nullable=False, unique=True) + + def __init__(self, groupName): + self.groupName = groupName + + def set_generated_name(self): + self.groupName = f"Group{self.id} {self.groupName}" + + def get_json(self): + return { + 'id': self.id, + 'groupName': self.groupName + } \ No newline at end of file diff --git a/App/models/groupRequest.py b/App/models/groupRequest.py index 41150b4..74037a8 100644 --- a/App/models/groupRequest.py +++ b/App/models/groupRequest.py @@ -4,7 +4,7 @@ class GroupRequest(db.Model): __tablename__ = 'group_request' id = db.Column(db.Integer, primary_key=True) - groupName = db.Column(db.String(30), nullable=False, unique=True) + groupName = db.Column(db.String(30), nullable=False) members = db.Column(db.JSON, nullable=False, default=list) def __init__(self, groupName, members: list[int]): From 6f96c7fed85ec586c4bb08cf949b2c576c19cfd9 Mon Sep 17 00:00:00 2001 From: Andrews3002 Date: Thu, 26 Mar 2026 09:15:11 -0400 Subject: [PATCH 06/37] studentGroup class created --- App/models/studentGroup.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 App/models/studentGroup.py diff --git a/App/models/studentGroup.py b/App/models/studentGroup.py new file mode 100644 index 0000000..47493a7 --- /dev/null +++ b/App/models/studentGroup.py @@ -0,0 +1,15 @@ +from App.database import db + +class StudentGroup(db.Model): + studentID = db.Column(db.Integer, db.ForeignKey('student.id'), primary_key=True) + groupID = db.Column(db.Integer, db.ForeignKey('group.id'), primary_key=True) + + def __init__(self, studentID, groupID): + self.studentID = studentID + self.groupID = groupID + + def get_json(self): + return { + 'studentID': self.studentID, + 'groupID': self.groupID + } \ No newline at end of file From 777aaa87977e357a03d31bbe17d3c29d135976f0 Mon Sep 17 00:00:00 2001 From: Andrews3002 Date: Thu, 26 Mar 2026 09:30:06 -0400 Subject: [PATCH 07/37] lot class created --- App/models/groupRequest.py | 2 -- App/models/lot.py | 20 ++++++++++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 App/models/lot.py diff --git a/App/models/groupRequest.py b/App/models/groupRequest.py index 74037a8..bd5533c 100644 --- a/App/models/groupRequest.py +++ b/App/models/groupRequest.py @@ -1,8 +1,6 @@ from App.database import db class GroupRequest(db.Model): - __tablename__ = 'group_request' - id = db.Column(db.Integer, primary_key=True) groupName = db.Column(db.String(30), nullable=False) members = db.Column(db.JSON, nullable=False, default=list) diff --git a/App/models/lot.py b/App/models/lot.py new file mode 100644 index 0000000..21c0a32 --- /dev/null +++ b/App/models/lot.py @@ -0,0 +1,20 @@ +from App.database import db + +class Lot(db.Model): + id = db.Column(db.Integer, primary_key=True) + labType = db.Column(db.String(30), nullable=False) + labSize = db.Column(db.Integer, nullable=False) + budget = db.Column(db.Float, nullable=False) + + def __init__(self, labType, labSize, budget): + self.labType = labType + self.labSize = labSize + self.budget = budget + + def get_json(self): + return { + 'id': self.id, + 'labType': self.labType, + 'labSize': self.labSize, + 'budget': self.budget + } \ No newline at end of file From 327337c3c2539dca59e2dbe0fbdaf67002fc65d4 Mon Sep 17 00:00:00 2001 From: Andrews3002 Date: Thu, 26 Mar 2026 09:32:15 -0400 Subject: [PATCH 08/37] lotGroup class created --- App/models/lotGroup.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 App/models/lotGroup.py diff --git a/App/models/lotGroup.py b/App/models/lotGroup.py new file mode 100644 index 0000000..85cf21a --- /dev/null +++ b/App/models/lotGroup.py @@ -0,0 +1,15 @@ +from App.database import db + +class LotGroup(db.Model): + lotID = db.Column(db.Integer, db.ForeignKey('lot.id'), primary_key=True) + groupID = db.Column(db.Integer, db.ForeignKey('group.id'), primary_key=True) + + def __init__(self, lotID, groupID): + self.lotID = lotID + self.groupID = groupID + + def get_json(self): + return { + 'lotID': self.lotID, + 'groupID': self.groupID + } \ No newline at end of file From bd96ddde3c57585ab815b155089f715a047df1ed Mon Sep 17 00:00:00 2001 From: Andrews3002 Date: Thu, 26 Mar 2026 09:52:40 -0400 Subject: [PATCH 09/37] rfpRequest class created --- App/models/rfpRequest.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 App/models/rfpRequest.py diff --git a/App/models/rfpRequest.py b/App/models/rfpRequest.py new file mode 100644 index 0000000..0ec5566 --- /dev/null +++ b/App/models/rfpRequest.py @@ -0,0 +1,20 @@ +from App.database import db + +class RFPRequest(db.Model): + id = db.Column(db.Integer, primary_key=True) + groupID = db.Column(db.Integer, db.ForeignKey('group.id'), nullable=False) + lotID = db.Column(db.Integer, db.ForeignKey('lot.id'), nullable=False) + specs = db.Column(db.JSON) + + def __init__(self, groupID, lotID, specs): + self.groupID = groupID + self.lotID = lotID + self.specs = specs + + def get_json(self): + return { + 'id': self.id, + 'groupID': self.groupID, + 'lotID': self.lotID, + 'specs': self.specs + } \ No newline at end of file From d320047252b9d2a7facd9475605ce91b4c4d8d57 Mon Sep 17 00:00:00 2001 From: Andrews3002 Date: Thu, 26 Mar 2026 09:54:14 -0400 Subject: [PATCH 10/37] rfp class created --- App/models/RFP.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 App/models/RFP.py diff --git a/App/models/RFP.py b/App/models/RFP.py new file mode 100644 index 0000000..44a25dd --- /dev/null +++ b/App/models/RFP.py @@ -0,0 +1,20 @@ +from App.database import db + +class RFP(db.Model): + id = db.Column(db.Integer, primary_key=True) + groupID = db.Column(db.Integer, db.ForeignKey('group.id'), nullable=False) + lotID = db.Column(db.Integer, db.ForeignKey('lot.id'), nullable=False) + specs = db.Column(db.JSON) + + def __init__(self, groupID, lotID, specs): + self.groupID = groupID + self.lotID = lotID + self.specs = specs + + def get_json(self): + return { + 'id': self.id, + 'groupID': self.groupID, + 'lotID': self.lotID, + 'specs': self.specs + } \ No newline at end of file From 7a39953e5284c534e9e66ac64e4ac9e98f5d7fe3 Mon Sep 17 00:00:00 2001 From: Andrews3002 Date: Thu, 26 Mar 2026 10:03:49 -0400 Subject: [PATCH 11/37] bid class created --- App/models/bid.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 App/models/bid.py diff --git a/App/models/bid.py b/App/models/bid.py new file mode 100644 index 0000000..065ecfa --- /dev/null +++ b/App/models/bid.py @@ -0,0 +1,26 @@ +from App.database import db +from datetime import datetime + +class Bid(db.Model): + id = db.Column(db.Integer, primary_key=True) + lotID = db.Column(db.Integer, db.ForeignKey('lot.id'), nullable=False) + sourceGroupID = db.Column(db.Integer, db.ForeignKey('group.id'), nullable=False) + receipientGroupID = db.Column(db.Integer, db.ForeignKey('group.id'), nullable=False) + timestamp = db.Column(db.DateTime, nullable=False, default=datetime.utcnow) + bidDocumentlink = db.Column(db.String(100), nullable=False) + + def __init__(self, lotID, sourceGroupID, receipientGroupID, bidDocumentlink): + self.lotID = lotID + self.sourceGroupID = sourceGroupID + self.receipientGroupID = receipientGroupID + self.bidDocumentlink = bidDocumentlink + + def get_json(self): + return { + 'id': self.id, + 'lotID': self.lotID, + 'sourceGroupID': self.sourceGroupID, + 'receipientGroupID': self.receipientGroupID, + 'timestamp': self.timestamp.isoformat(), + 'bidDocumentlink': self.bidDocumentlink + } \ No newline at end of file From cbda7094ce1dcb605b22b901ecacbd7aed94e011 Mon Sep 17 00:00:00 2001 From: Andrews3002 Date: Thu, 26 Mar 2026 10:07:46 -0400 Subject: [PATCH 12/37] evaluation class created --- App/models/evaluation.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 App/models/evaluation.py diff --git a/App/models/evaluation.py b/App/models/evaluation.py new file mode 100644 index 0000000..ccd22a9 --- /dev/null +++ b/App/models/evaluation.py @@ -0,0 +1,20 @@ +from App.database import db + +class Evaluation(db.Model): + id = db.Column(db.Integer, primary_key=True) + sourceGroupID = db.Column(db.Integer, db.ForeignKey('group.id'), nullable=False) + receipientGroupID = db.Column(db.Integer, db.ForeignKey('group.id'), nullable=False) + evaluationDetails = db.Column(db.JSON) + + def __init__(self, sourceGroupID, receipientGroupID, evaluationDetails): + self.sourceGroupID = sourceGroupID + self.receipientGroupID = receipientGroupID + self.evaluationDetails = evaluationDetails + + def get_json(self): + return { + 'id': self.id, + 'sourceGroupID': self.sourceGroupID, + 'receipientGroupID': self.receipientGroupID, + 'evaluationDetails': self.evaluationDetails + } \ No newline at end of file From 3380c93f8a28d3ac7bb0228224020fc9f8066698 Mon Sep 17 00:00:00 2001 From: Andrews3002 Date: Thu, 26 Mar 2026 10:16:27 -0400 Subject: [PATCH 13/37] models created --- App/models/bid.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/App/models/bid.py b/App/models/bid.py index 065ecfa..36af2e8 100644 --- a/App/models/bid.py +++ b/App/models/bid.py @@ -7,7 +7,7 @@ class Bid(db.Model): sourceGroupID = db.Column(db.Integer, db.ForeignKey('group.id'), nullable=False) receipientGroupID = db.Column(db.Integer, db.ForeignKey('group.id'), nullable=False) timestamp = db.Column(db.DateTime, nullable=False, default=datetime.utcnow) - bidDocumentlink = db.Column(db.String(100), nullable=False) + bidDocumentlink = db.Column(db.String(1000), nullable=False) def __init__(self, lotID, sourceGroupID, receipientGroupID, bidDocumentlink): self.lotID = lotID From 784cef91973343dfaa9e4e74f33e329d4d1d3228 Mon Sep 17 00:00:00 2001 From: Andrews3002 Date: Thu, 26 Mar 2026 10:30:01 -0400 Subject: [PATCH 14/37] models__init__.py file updated --- App/models/__init__.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/App/models/__init__.py b/App/models/__init__.py index 82da278..bb31897 100644 --- a/App/models/__init__.py +++ b/App/models/__init__.py @@ -1 +1,12 @@ -from .user import * \ No newline at end of file +from .user import * +from .admin import * +from .student import * +from .lot import * +from .group import * +from .groupRequest import * +from .lotGroup import * +from .studentGroup import * +from .rfpRequest import * +from .rfp import * +from .bid import * +from .evaluation import * \ No newline at end of file From 152718cfc5859ca9981bb55581537575c4158524 Mon Sep 17 00:00:00 2001 From: Andrews3002 Date: Thu, 26 Mar 2026 13:37:54 -0400 Subject: [PATCH 15/37] classes have been unit tested --- App/models/admin.py | 6 + App/models/bid.py | 11 +- App/models/rfpRequest.py | 6 +- App/models/student.py | 6 + App/tests/test_app.py | 301 +++++++++++++++++++++++++++++++-------- test.bat | 1 + 6 files changed, 263 insertions(+), 68 deletions(-) create mode 100644 test.bat diff --git a/App/models/admin.py b/App/models/admin.py index 28061b1..2e7777a 100644 --- a/App/models/admin.py +++ b/App/models/admin.py @@ -11,5 +11,11 @@ class Admin(User): def __init__(self, username, password): super().__init__(username, password) + def is_admin(self): + return True + + def is_student(self): + return False + def get_json(self): return {**super().get_json(), 'role': 'admin'} \ No newline at end of file diff --git a/App/models/bid.py b/App/models/bid.py index 36af2e8..0082e26 100644 --- a/App/models/bid.py +++ b/App/models/bid.py @@ -6,14 +6,15 @@ class Bid(db.Model): lotID = db.Column(db.Integer, db.ForeignKey('lot.id'), nullable=False) sourceGroupID = db.Column(db.Integer, db.ForeignKey('group.id'), nullable=False) receipientGroupID = db.Column(db.Integer, db.ForeignKey('group.id'), nullable=False) - timestamp = db.Column(db.DateTime, nullable=False, default=datetime.utcnow) - bidDocumentlink = db.Column(db.String(1000), nullable=False) + timestamp = db.Column(db.DateTime, nullable=False, default=datetime.utcnow()) + bidDocumentLink = db.Column(db.String(1000), nullable=False) - def __init__(self, lotID, sourceGroupID, receipientGroupID, bidDocumentlink): + def __init__(self, lotID, sourceGroupID, receipientGroupID, bidDocumentLink): self.lotID = lotID self.sourceGroupID = sourceGroupID self.receipientGroupID = receipientGroupID - self.bidDocumentlink = bidDocumentlink + self.bidDocumentLink = bidDocumentLink + self.timestamp = datetime.utcnow() def get_json(self): return { @@ -22,5 +23,5 @@ def get_json(self): 'sourceGroupID': self.sourceGroupID, 'receipientGroupID': self.receipientGroupID, 'timestamp': self.timestamp.isoformat(), - 'bidDocumentlink': self.bidDocumentlink + 'bidDocumentLink': self.bidDocumentLink } \ No newline at end of file diff --git a/App/models/rfpRequest.py b/App/models/rfpRequest.py index 0ec5566..91c0cca 100644 --- a/App/models/rfpRequest.py +++ b/App/models/rfpRequest.py @@ -1,9 +1,8 @@ from App.database import db class RFPRequest(db.Model): - id = db.Column(db.Integer, primary_key=True) - groupID = db.Column(db.Integer, db.ForeignKey('group.id'), nullable=False) - lotID = db.Column(db.Integer, db.ForeignKey('lot.id'), nullable=False) + groupID = db.Column(db.Integer, db.ForeignKey('group.id'), primary_key=True) + lotID = db.Column(db.Integer, db.ForeignKey('lot.id'), primary_key=True) specs = db.Column(db.JSON) def __init__(self, groupID, lotID, specs): @@ -13,7 +12,6 @@ def __init__(self, groupID, lotID, specs): def get_json(self): return { - 'id': self.id, 'groupID': self.groupID, 'lotID': self.lotID, 'specs': self.specs diff --git a/App/models/student.py b/App/models/student.py index 3bf6857..1c7d8dd 100644 --- a/App/models/student.py +++ b/App/models/student.py @@ -11,5 +11,11 @@ class Student(User): def __init__(self, username, password): super().__init__(username, password) + def is_admin(self): + return False + + def is_student(self): + return True + def get_json(self): return {**super().get_json(), 'role': 'student'} \ No newline at end of file diff --git a/App/tests/test_app.py b/App/tests/test_app.py index cca1277..4bce843 100644 --- a/App/tests/test_app.py +++ b/App/tests/test_app.py @@ -1,46 +1,231 @@ -import os, tempfile, pytest, logging, unittest -from werkzeug.security import check_password_hash, generate_password_hash +import pytest +import unittest +from datetime import datetime +from werkzeug.security import generate_password_hash from App.main import create_app from App.database import db, create_db -from App.models import User -from App.controllers import ( - create_user, - get_all_users_json, - login, - get_user, - get_user_by_username, - update_user -) +from App.models import User, Admin, Student, Group, GroupRequest, StudentGroup, Lot, LotGroup, RFPRequest, Bid, Evaluation -LOGGER = logging.getLogger(__name__) - ''' - Unit Tests + Unit Tests ''' -class UserUnitTests(unittest.TestCase): - - def test_new_user(self): - user = User("bob", "bobpass") - assert user.username == "bob" - - # pure function no side effects or integrations called - def test_get_json(self): - user = User("bob", "bobpass") - user_json = user.get_json() - self.assertDictEqual(user_json, {"id":None, "username":"bob"}) - - def test_hashed_password(self): - password = "mypass" - hashed = generate_password_hash(password) - user = User("bob", password) - assert user.password != password - - def test_check_password(self): - password = "mypass" - user = User("bob", password) - assert user.check_password(password) + +class AdminUnitTests(unittest.TestCase): + + def test_new_admin(self): + admin = Admin("alice", "alicepass") + assert admin.username == "alice" + + def test_admin_get_json(self): + admin = Admin("alice", "alicepass") + admin_json = admin.get_json() + assert admin_json["username"] == "alice" + assert admin_json["role"] == "admin" + + def test_admin_hashed_password(self): + admin = Admin("alice", "alicepass") + assert admin.password != "alicepass" + + def test_admin_check_password(self): + admin = Admin("alice", "alicepass") + assert admin.check_password("alicepass") + + def test_admin_is_admin(self): + admin = Admin("alice", "alicepass") + assert admin.is_admin() + + def test_admin_is_not_student(self): + admin = Admin("alice", "alicepass") + assert not admin.is_student() + + +class StudentUnitTests(unittest.TestCase): + + def test_new_student(self): + student = Student("bob", "bobpass") + assert student.username == "bob" + + def test_student_get_json(self): + student = Student("bob", "bobpass") + student_json = student.get_json() + assert student_json["username"] == "bob" + assert student_json["role"] == "student" + + def test_student_hashed_password(self): + student = Student("bob", "bobpass") + assert student.password != "bobpass" + + def test_student_check_password(self): + student = Student("bob", "bobpass") + assert student.check_password("bobpass") + + def test_student_is_student(self): + student = Student("bob", "bobpass") + assert student.is_student() + + def test_student_is_not_admin(self): + student = Student("bob", "bobpass") + assert not student.is_admin() + + +class GroupUnitTests(unittest.TestCase): + + def test_new_group(self): + group = Group("Algorithms") + assert group.groupName == "Algorithms" + + def test_group_get_json(self): + group = Group("Algorithms") + group_json = group.get_json() + assert group_json["groupName"] == "Algorithms" + + +class GroupRequestUnitTests(unittest.TestCase): + + def test_new_group_request(self): + group_request = GroupRequest("Algorithms", [1, 2, 3]) + assert group_request.groupName == "Algorithms" + + def test_group_request_members(self): + group_request = GroupRequest("Algorithms", [1, 2, 3]) + assert group_request.members == [1, 2, 3] + + def test_group_request_get_json(self): + group_request = GroupRequest("Algorithms", [1, 2, 3]) + group_json = group_request.get_json() + assert group_json["groupName"] == "Algorithms" + assert group_json["members"] == [1, 2, 3] + + +class StudentGroupUnitTests(unittest.TestCase): + + def test_new_student_group(self): + student_group = StudentGroup(1, 2) + assert student_group.studentID == 1 + assert student_group.groupID == 2 + + def test_student_group_get_json(self): + student_group = StudentGroup(1, 2) + sg_json = student_group.get_json() + self.assertDictEqual(sg_json, {"studentID": 1, "groupID": 2}) + + +class LotUnitTests(unittest.TestCase): + + def test_new_lot(self): + lot = Lot("Biology", 30, 5000.00) + assert lot.labType == "Biology" + + def test_lot_lab_size(self): + lot = Lot("Biology", 30, 5000.00) + assert lot.labSize == 30 + + def test_lot_budget(self): + lot = Lot("Biology", 30, 5000.00) + assert lot.budget == 5000.00 + + def test_lot_get_json(self): + lot = Lot("Biology", 30, 5000.00) + lot_json = lot.get_json() + self.assertDictEqual(lot_json, { + "id": None, + "labType": "Biology", + "labSize": 30, + "budget": 5000.00 + }) + + def test_lot_budget_comparison(self): + lot = Lot("Biology", 30, 5000.00) + assert 4999.99 < lot.budget + assert 5000.01 > lot.budget + + +class LotGroupUnitTests(unittest.TestCase): + + def test_new_lot_group(self): + lot_group = LotGroup(1, 2) + assert lot_group.lotID == 1 + assert lot_group.groupID == 2 + + def test_lot_group_get_json(self): + lot_group = LotGroup(1, 2) + lg_json = lot_group.get_json() + self.assertDictEqual(lg_json, {"lotID": 1, "groupID": 2}) + + +class RFPRequestUnitTests(unittest.TestCase): + + def test_new_rfp_request(self): + rfp = RFPRequest(1, 2, {"detail": "some spec"}) + assert rfp.groupID == 1 + assert rfp.lotID == 2 + + def test_rfp_request_specs(self): + specs = {"detail": "some spec", "budget": 1000} + rfp = RFPRequest(1, 2, specs) + assert rfp.specs == specs + + def test_rfp_request_get_json(self): + specs = {"detail": "some spec"} + rfp = RFPRequest(1, 2, specs) + rfp_json = rfp.get_json() + assert rfp_json["groupID"] == 1 + assert rfp_json["lotID"] == 2 + assert rfp_json["specs"] == specs + + +class BidUnitTests(unittest.TestCase): + + def test_new_bid(self): + bid = Bid(1, 2, 3, "http://example.com/doc") + assert bid.lotID == 1 + assert bid.sourceGroupID == 2 + assert bid.receipientGroupID == 3 + + def test_bid_document_link(self): + bid = Bid(1, 2, 3, "http://example.com/doc") + assert bid.bidDocumentLink == "http://example.com/doc" + + def test_bid_timestamp_auto_set(self): + bid = Bid(1, 2, 3, "http://example.com/doc") + assert isinstance(bid.timestamp, datetime) + + def test_bid_timestamp_is_recent(self): + bid = Bid(1, 2, 3, "http://example.com/doc") + delta = datetime.utcnow() - bid.timestamp + assert delta.seconds < 5 + + def test_bid_get_json(self): + bid = Bid(1, 2, 3, "http://example.com/doc") + bid_json = bid.get_json() + assert bid_json["lotID"] == 1 + assert bid_json["sourceGroupID"] == 2 + assert bid_json["receipientGroupID"] == 3 + assert bid_json["bidDocumentLink"] == "http://example.com/doc" + assert "timestamp" in bid_json + + +class EvaluationUnitTests(unittest.TestCase): + + def test_new_evaluation(self): + evaluation = Evaluation(1, 2, {"score": 85}) + assert evaluation.sourceGroupID == 1 + assert evaluation.receipientGroupID == 2 + + def test_evaluation_details(self): + details = {"score": 85, "comments": "Good work"} + evaluation = Evaluation(1, 2, details) + assert evaluation.evaluationDetails == details + + def test_evaluation_get_json(self): + details = {"score": 85} + evaluation = Evaluation(1, 2, details) + eval_json = evaluation.get_json() + assert eval_json["sourceGroupID"] == 1 + assert eval_json["receipientGroupID"] == 2 + assert eval_json["evaluationDetails"] == details ''' Integration Tests @@ -48,32 +233,30 @@ def test_check_password(self): # 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'}) - create_db() - yield app.test_client() - db.drop_all() - +# @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_authenticate(): - user = create_user("bob", "bobpass") - assert login("bob", "bobpass") != None -class UsersIntegrationTests(unittest.TestCase): +# def test_authenticate(): +# user = create_user("bob", "bobpass") +# assert login("bob", "bobpass") != None - def test_create_user(self): - user = create_user("rick", "bobpass") - assert user.username == "rick" +# class UsersIntegrationTests(unittest.TestCase): - 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) +# def test_create_user(self): +# user = create_user("rick", "bobpass") +# assert user.username == "rick" - # Tests data changes in the database - def test_update_user(self): - update_user(1, "ronnie") - user = get_user(1) - assert user.username == "ronnie" - +# 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) +# # Tests data changes in the database +# def test_update_user(self): +# update_user(1, "ronnie") +# user = get_user(1) +# assert user.username == "ronnie" \ No newline at end of file diff --git a/test.bat b/test.bat new file mode 100644 index 0000000..372caf0 --- /dev/null +++ b/test.bat @@ -0,0 +1 @@ +python -m pytest \ No newline at end of file From e51f3d74bf814f5fafd9b37206c5485d2ffb7172 Mon Sep 17 00:00:00 2001 From: Andrews3002 Date: Thu, 26 Mar 2026 22:09:46 -0400 Subject: [PATCH 16/37] unit tests for models complete and integration tests are ready to be implemented with controllers --- App/tests/{test_app.py => A_unit_test.py} | 40 +------------------- App/tests/B_integration_test.py | 45 +++++++++++++++++++++++ App/tests/__init__.py | 3 +- test.bat | 1 + 4 files changed, 49 insertions(+), 40 deletions(-) rename App/tests/{test_app.py => A_unit_test.py} (85%) create mode 100644 App/tests/B_integration_test.py diff --git a/App/tests/test_app.py b/App/tests/A_unit_test.py similarity index 85% rename from App/tests/test_app.py rename to App/tests/A_unit_test.py index 4bce843..b087461 100644 --- a/App/tests/test_app.py +++ b/App/tests/A_unit_test.py @@ -8,10 +8,6 @@ from App.models import User, Admin, Student, Group, GroupRequest, StudentGroup, Lot, LotGroup, RFPRequest, Bid, Evaluation -''' - Unit Tests -''' - class AdminUnitTests(unittest.TestCase): def test_new_admin(self): @@ -225,38 +221,4 @@ def test_evaluation_get_json(self): eval_json = evaluation.get_json() assert eval_json["sourceGroupID"] == 1 assert eval_json["receipientGroupID"] == 2 - assert eval_json["evaluationDetails"] == details - -''' - 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'}) -# create_db() -# yield app.test_client() -# db.drop_all() - - -# def test_authenticate(): -# user = create_user("bob", "bobpass") -# assert login("bob", "bobpass") != None - -# class UsersIntegrationTests(unittest.TestCase): - -# def test_create_user(self): -# user = create_user("rick", "bobpass") -# assert user.username == "rick" - -# 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) - -# # Tests data changes in the database -# def test_update_user(self): -# update_user(1, "ronnie") -# user = get_user(1) -# assert user.username == "ronnie" \ No newline at end of file + assert eval_json["evaluationDetails"] == details \ No newline at end of file diff --git a/App/tests/B_integration_test.py b/App/tests/B_integration_test.py new file mode 100644 index 0000000..96a8384 --- /dev/null +++ b/App/tests/B_integration_test.py @@ -0,0 +1,45 @@ +import pytest +import unittest +from datetime import datetime +from werkzeug.security import generate_password_hash + +from App.main import create_app +from App.database import db, create_db +from App.models import User, Admin, Student, Group, GroupRequest, StudentGroup, Lot, LotGroup, RFPRequest, Bid, Evaluation +from App.controllers import * + +@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_authenticate(): + user = create_user("bob", "bobpass") + assert login("bob", "bobpass") != None + +class UsersIntegrationTests(unittest.TestCase): + def test_user_children_are_users(self): + admin = Admin("jack", "jackpass") + db.session.add(admin) + student = Student("cooper", "cooperpass") + db.session.add(student) + db.session.commit() + users_json = get_all_users_json() + self.assertListEqual([{"id":1, "username":"bob"}, {"id":2, "username":"jack", "role":"admin"}, {"id":3, "username":"cooper", "role":"student"}], users_json) + + def test_create_user(self): + user = create_user("rick", "bobpass") + assert user.username == "rick" + + 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) + + # Tests data changes in the database + def test_update_user(self): + update_user(1, "ronnie") + user = get_user(1) + assert user.username == "ronnie" + diff --git a/App/tests/__init__.py b/App/tests/__init__.py index f5c872f..f0c4cd1 100644 --- a/App/tests/__init__.py +++ b/App/tests/__init__.py @@ -1 +1,2 @@ -from .test_app import * \ No newline at end of file +from .A_unit_test import * +from .B_integration_test import * \ No newline at end of file diff --git a/test.bat b/test.bat index 372caf0..315fe02 100644 --- a/test.bat +++ b/test.bat @@ -1 +1,2 @@ +cls python -m pytest \ No newline at end of file From 7d9f5813a0cb13da509825884d796aee9e955088 Mon Sep 17 00:00:00 2001 From: Andrews3002 Date: Thu, 26 Mar 2026 22:12:25 -0400 Subject: [PATCH 17/37] ready for controllers --- App/tests/B_integration_test.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/App/tests/B_integration_test.py b/App/tests/B_integration_test.py index 96a8384..a33e8f5 100644 --- a/App/tests/B_integration_test.py +++ b/App/tests/B_integration_test.py @@ -41,5 +41,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" - + assert user.username == "ronnie" \ No newline at end of file From 7361803e3818925268de81613b4a19a9dcde9dbc Mon Sep 17 00:00:00 2001 From: Andrews3002 Date: Fri, 27 Mar 2026 00:14:19 -0400 Subject: [PATCH 18/37] workflow1 complete --- App/controllers/__init__.py | 1 + App/controllers/admin.py | 20 ++ App/controllers/lot.py | 40 ++++ App/controllers/student.py | 20 ++ App/models/user.py | 6 + App/tests/A_unit_test.py | 224 ------------------ App/tests/__init__.py | 4 +- ...ntegration_test.py => integration_test.py} | 54 ++++- App/tests/unit_test.py | 224 ++++++++++++++++++ 9 files changed, 358 insertions(+), 235 deletions(-) create mode 100644 App/controllers/admin.py create mode 100644 App/controllers/lot.py create mode 100644 App/controllers/student.py delete mode 100644 App/tests/A_unit_test.py rename App/tests/{B_integration_test.py => integration_test.py} (51%) create mode 100644 App/tests/unit_test.py diff --git a/App/controllers/__init__.py b/App/controllers/__init__.py index 98fb3b9..f188b14 100644 --- a/App/controllers/__init__.py +++ b/App/controllers/__init__.py @@ -1,3 +1,4 @@ from .user import * from .auth import * from .initialize import * +from .lot import * diff --git a/App/controllers/admin.py b/App/controllers/admin.py new file mode 100644 index 0000000..a85cac9 --- /dev/null +++ b/App/controllers/admin.py @@ -0,0 +1,20 @@ +from App.models import Admin +from App.database import db + +def create_admin(username, password): + newadmin = Admin(username=username, password=password) + db.session.add(newuser) + db.session.commit() + +def get_admin(id): + return db.session.get(Admin, id) + +def get_all_admins(): + return db.session.scalars(db.select(Admin)).all() + +def get_all_admins_json(): + admins = get_all_admins() + if not admins: + return [] + admins = [admin.get_json() for admin in admins] + return admins \ No newline at end of file diff --git a/App/controllers/lot.py b/App/controllers/lot.py new file mode 100644 index 0000000..ab9da2f --- /dev/null +++ b/App/controllers/lot.py @@ -0,0 +1,40 @@ +from App.models import Lot +from App.database import db + +def create_lot(labType, labSize, budget): + newlot = Lot(labType, labSize, budget) + db.session.add(newlot) + db.session.commit() + +def get_lot(id): + return db.session.get(Lot, id) + +def get_all_lots(): + return db.session.scalars(db.select(Lot)).all() + +def get_all_lots_json(): + lots = get_all_lots() + if not lots: + return [] + lots = [lot.get_json() for lot in lots] + return lots + +def edit_lot(id, labType=None, labSize=None, budget=None): + lot = get_lot(id) + if lot: + if labType: + lot.labType = labType + + if labSize: + lot.labSize = labSize + + if budget: + lot.budget = budget + + db.session.commit() + +def remove_lot(id): + lot = get_lot(id) + if lot: + db.session.delete(lot) + db.session.commit() \ No newline at end of file diff --git a/App/controllers/student.py b/App/controllers/student.py new file mode 100644 index 0000000..e99dc9c --- /dev/null +++ b/App/controllers/student.py @@ -0,0 +1,20 @@ +from App.models import Student +from App.database import db + +def create_student(username, password): + newstudent = Student(username=username, password=password) + db.session.add(newstudent) + db.session.commit() + +def get_student(id): + return db.session.get(Student, id) + +def get_all_students(): + return db.session.scalars(db.select(Student)).all() + +def get_all_students_json(): + students = get_all_students() + if not students: + return [] + students = [student.get_json() for student in students] + return students \ No newline at end of file diff --git a/App/models/user.py b/App/models/user.py index 9ed25ad..31cdc8f 100644 --- a/App/models/user.py +++ b/App/models/user.py @@ -5,6 +5,12 @@ class User(db.Model): id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(20), nullable=False, unique=True) password = db.Column(db.String(256), nullable=False) + type = db.Column(db.String(50)) + + __mapper_args__ = { + 'polymorphic_on': type, + 'polymorphic_identity': 'user' + } def __init__(self, username, password): self.username = username diff --git a/App/tests/A_unit_test.py b/App/tests/A_unit_test.py deleted file mode 100644 index b087461..0000000 --- a/App/tests/A_unit_test.py +++ /dev/null @@ -1,224 +0,0 @@ -import pytest -import unittest -from datetime import datetime -from werkzeug.security import generate_password_hash - -from App.main import create_app -from App.database import db, create_db -from App.models import User, Admin, Student, Group, GroupRequest, StudentGroup, Lot, LotGroup, RFPRequest, Bid, Evaluation - - -class AdminUnitTests(unittest.TestCase): - - def test_new_admin(self): - admin = Admin("alice", "alicepass") - assert admin.username == "alice" - - def test_admin_get_json(self): - admin = Admin("alice", "alicepass") - admin_json = admin.get_json() - assert admin_json["username"] == "alice" - assert admin_json["role"] == "admin" - - def test_admin_hashed_password(self): - admin = Admin("alice", "alicepass") - assert admin.password != "alicepass" - - def test_admin_check_password(self): - admin = Admin("alice", "alicepass") - assert admin.check_password("alicepass") - - def test_admin_is_admin(self): - admin = Admin("alice", "alicepass") - assert admin.is_admin() - - def test_admin_is_not_student(self): - admin = Admin("alice", "alicepass") - assert not admin.is_student() - - -class StudentUnitTests(unittest.TestCase): - - def test_new_student(self): - student = Student("bob", "bobpass") - assert student.username == "bob" - - def test_student_get_json(self): - student = Student("bob", "bobpass") - student_json = student.get_json() - assert student_json["username"] == "bob" - assert student_json["role"] == "student" - - def test_student_hashed_password(self): - student = Student("bob", "bobpass") - assert student.password != "bobpass" - - def test_student_check_password(self): - student = Student("bob", "bobpass") - assert student.check_password("bobpass") - - def test_student_is_student(self): - student = Student("bob", "bobpass") - assert student.is_student() - - def test_student_is_not_admin(self): - student = Student("bob", "bobpass") - assert not student.is_admin() - - -class GroupUnitTests(unittest.TestCase): - - def test_new_group(self): - group = Group("Algorithms") - assert group.groupName == "Algorithms" - - def test_group_get_json(self): - group = Group("Algorithms") - group_json = group.get_json() - assert group_json["groupName"] == "Algorithms" - - -class GroupRequestUnitTests(unittest.TestCase): - - def test_new_group_request(self): - group_request = GroupRequest("Algorithms", [1, 2, 3]) - assert group_request.groupName == "Algorithms" - - def test_group_request_members(self): - group_request = GroupRequest("Algorithms", [1, 2, 3]) - assert group_request.members == [1, 2, 3] - - def test_group_request_get_json(self): - group_request = GroupRequest("Algorithms", [1, 2, 3]) - group_json = group_request.get_json() - assert group_json["groupName"] == "Algorithms" - assert group_json["members"] == [1, 2, 3] - - -class StudentGroupUnitTests(unittest.TestCase): - - def test_new_student_group(self): - student_group = StudentGroup(1, 2) - assert student_group.studentID == 1 - assert student_group.groupID == 2 - - def test_student_group_get_json(self): - student_group = StudentGroup(1, 2) - sg_json = student_group.get_json() - self.assertDictEqual(sg_json, {"studentID": 1, "groupID": 2}) - - -class LotUnitTests(unittest.TestCase): - - def test_new_lot(self): - lot = Lot("Biology", 30, 5000.00) - assert lot.labType == "Biology" - - def test_lot_lab_size(self): - lot = Lot("Biology", 30, 5000.00) - assert lot.labSize == 30 - - def test_lot_budget(self): - lot = Lot("Biology", 30, 5000.00) - assert lot.budget == 5000.00 - - def test_lot_get_json(self): - lot = Lot("Biology", 30, 5000.00) - lot_json = lot.get_json() - self.assertDictEqual(lot_json, { - "id": None, - "labType": "Biology", - "labSize": 30, - "budget": 5000.00 - }) - - def test_lot_budget_comparison(self): - lot = Lot("Biology", 30, 5000.00) - assert 4999.99 < lot.budget - assert 5000.01 > lot.budget - - -class LotGroupUnitTests(unittest.TestCase): - - def test_new_lot_group(self): - lot_group = LotGroup(1, 2) - assert lot_group.lotID == 1 - assert lot_group.groupID == 2 - - def test_lot_group_get_json(self): - lot_group = LotGroup(1, 2) - lg_json = lot_group.get_json() - self.assertDictEqual(lg_json, {"lotID": 1, "groupID": 2}) - - -class RFPRequestUnitTests(unittest.TestCase): - - def test_new_rfp_request(self): - rfp = RFPRequest(1, 2, {"detail": "some spec"}) - assert rfp.groupID == 1 - assert rfp.lotID == 2 - - def test_rfp_request_specs(self): - specs = {"detail": "some spec", "budget": 1000} - rfp = RFPRequest(1, 2, specs) - assert rfp.specs == specs - - def test_rfp_request_get_json(self): - specs = {"detail": "some spec"} - rfp = RFPRequest(1, 2, specs) - rfp_json = rfp.get_json() - assert rfp_json["groupID"] == 1 - assert rfp_json["lotID"] == 2 - assert rfp_json["specs"] == specs - - -class BidUnitTests(unittest.TestCase): - - def test_new_bid(self): - bid = Bid(1, 2, 3, "http://example.com/doc") - assert bid.lotID == 1 - assert bid.sourceGroupID == 2 - assert bid.receipientGroupID == 3 - - def test_bid_document_link(self): - bid = Bid(1, 2, 3, "http://example.com/doc") - assert bid.bidDocumentLink == "http://example.com/doc" - - def test_bid_timestamp_auto_set(self): - bid = Bid(1, 2, 3, "http://example.com/doc") - assert isinstance(bid.timestamp, datetime) - - def test_bid_timestamp_is_recent(self): - bid = Bid(1, 2, 3, "http://example.com/doc") - delta = datetime.utcnow() - bid.timestamp - assert delta.seconds < 5 - - def test_bid_get_json(self): - bid = Bid(1, 2, 3, "http://example.com/doc") - bid_json = bid.get_json() - assert bid_json["lotID"] == 1 - assert bid_json["sourceGroupID"] == 2 - assert bid_json["receipientGroupID"] == 3 - assert bid_json["bidDocumentLink"] == "http://example.com/doc" - assert "timestamp" in bid_json - - -class EvaluationUnitTests(unittest.TestCase): - - def test_new_evaluation(self): - evaluation = Evaluation(1, 2, {"score": 85}) - assert evaluation.sourceGroupID == 1 - assert evaluation.receipientGroupID == 2 - - def test_evaluation_details(self): - details = {"score": 85, "comments": "Good work"} - evaluation = Evaluation(1, 2, details) - assert evaluation.evaluationDetails == details - - def test_evaluation_get_json(self): - details = {"score": 85} - evaluation = Evaluation(1, 2, details) - eval_json = evaluation.get_json() - assert eval_json["sourceGroupID"] == 1 - assert eval_json["receipientGroupID"] == 2 - assert eval_json["evaluationDetails"] == details \ No newline at end of file diff --git a/App/tests/__init__.py b/App/tests/__init__.py index f0c4cd1..c2e5876 100644 --- a/App/tests/__init__.py +++ b/App/tests/__init__.py @@ -1,2 +1,2 @@ -from .A_unit_test import * -from .B_integration_test import * \ No newline at end of file +from .unit_test import * +from .integration_test import * \ No newline at end of file diff --git a/App/tests/B_integration_test.py b/App/tests/integration_test.py similarity index 51% rename from App/tests/B_integration_test.py rename to App/tests/integration_test.py index a33e8f5..db94c33 100644 --- a/App/tests/B_integration_test.py +++ b/App/tests/integration_test.py @@ -15,11 +15,13 @@ def empty_db(): yield app.test_client() db.drop_all() +@pytest.mark.run(order=1) def test_authenticate(): user = create_user("bob", "bobpass") assert login("bob", "bobpass") != None class UsersIntegrationTests(unittest.TestCase): + @pytest.mark.run(order=2) def test_user_children_are_users(self): admin = Admin("jack", "jackpass") db.session.add(admin) @@ -29,16 +31,50 @@ def test_user_children_are_users(self): users_json = get_all_users_json() self.assertListEqual([{"id":1, "username":"bob"}, {"id":2, "username":"jack", "role":"admin"}, {"id":3, "username":"cooper", "role":"student"}], users_json) - def test_create_user(self): - user = create_user("rick", "bobpass") - assert user.username == "rick" - - 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) - # Tests data changes in the database + @pytest.mark.run(order=3) def test_update_user(self): update_user(1, "ronnie") user = get_user(1) - assert user.username == "ronnie" \ No newline at end of file + assert user.username == "ronnie" + +class Workflow1IntegrationTests(unittest.TestCase): + @pytest.mark.run(order=4) + def test_creating_lots(self): + db.drop_all() + create_db() + create_lot("GIS Lab", 20, 160000.00) + create_lot("Government Office Lab", 12, 110000.00) + lots_json = get_all_lots_json() + self.assertListEqual([ + { + 'id': 1, + 'labType': "GIS Lab", + 'labSize': 20, + 'budget': 160000.00 + }, + { + 'id': 2, + 'labType': "Government Office Lab", + 'labSize': 12, + 'budget': 110000.00 + } + ], lots_json) + + @pytest.mark.run(order=5) + def test_edit_lots(self): + lot = get_lot(1) + assert lot.budget == 160000.00 + edit_lot(1, budget=170000.00) + lot = get_lot(1) + assert lot.budget == 170000.00 + + @pytest.mark.run(order=6) + def test_remove_lot(self): + lot = get_lot(1) + assert not lot == None + remove_lot(1) + lot = get_lot(1) + assert lot == None + + diff --git a/App/tests/unit_test.py b/App/tests/unit_test.py new file mode 100644 index 0000000..62a2381 --- /dev/null +++ b/App/tests/unit_test.py @@ -0,0 +1,224 @@ +# import pytest +# import unittest +# from datetime import datetime +# from werkzeug.security import generate_password_hash + +# from App.main import create_app +# from App.database import db, create_db +# from App.models import User, Admin, Student, Group, GroupRequest, StudentGroup, Lot, LotGroup, RFPRequest, Bid, Evaluation + + +# class AdminUnitTests(unittest.TestCase): + +# def test_new_admin(self): +# admin = Admin("alice", "alicepass") +# assert admin.username == "alice" + +# def test_admin_get_json(self): +# admin = Admin("alice", "alicepass") +# admin_json = admin.get_json() +# assert admin_json["username"] == "alice" +# assert admin_json["role"] == "admin" + +# def test_admin_hashed_password(self): +# admin = Admin("alice", "alicepass") +# assert admin.password != "alicepass" + +# def test_admin_check_password(self): +# admin = Admin("alice", "alicepass") +# assert admin.check_password("alicepass") + +# def test_admin_is_admin(self): +# admin = Admin("alice", "alicepass") +# assert admin.is_admin() + +# def test_admin_is_not_student(self): +# admin = Admin("alice", "alicepass") +# assert not admin.is_student() + + +# class StudentUnitTests(unittest.TestCase): + +# def test_new_student(self): +# student = Student("bob", "bobpass") +# assert student.username == "bob" + +# def test_student_get_json(self): +# student = Student("bob", "bobpass") +# student_json = student.get_json() +# assert student_json["username"] == "bob" +# assert student_json["role"] == "student" + +# def test_student_hashed_password(self): +# student = Student("bob", "bobpass") +# assert student.password != "bobpass" + +# def test_student_check_password(self): +# student = Student("bob", "bobpass") +# assert student.check_password("bobpass") + +# def test_student_is_student(self): +# student = Student("bob", "bobpass") +# assert student.is_student() + +# def test_student_is_not_admin(self): +# student = Student("bob", "bobpass") +# assert not student.is_admin() + + +# class GroupUnitTests(unittest.TestCase): + +# def test_new_group(self): +# group = Group("Algorithms") +# assert group.groupName == "Algorithms" + +# def test_group_get_json(self): +# group = Group("Algorithms") +# group_json = group.get_json() +# assert group_json["groupName"] == "Algorithms" + + +# class GroupRequestUnitTests(unittest.TestCase): + +# def test_new_group_request(self): +# group_request = GroupRequest("Algorithms", [1, 2, 3]) +# assert group_request.groupName == "Algorithms" + +# def test_group_request_members(self): +# group_request = GroupRequest("Algorithms", [1, 2, 3]) +# assert group_request.members == [1, 2, 3] + +# def test_group_request_get_json(self): +# group_request = GroupRequest("Algorithms", [1, 2, 3]) +# group_json = group_request.get_json() +# assert group_json["groupName"] == "Algorithms" +# assert group_json["members"] == [1, 2, 3] + + +# class StudentGroupUnitTests(unittest.TestCase): + +# def test_new_student_group(self): +# student_group = StudentGroup(1, 2) +# assert student_group.studentID == 1 +# assert student_group.groupID == 2 + +# def test_student_group_get_json(self): +# student_group = StudentGroup(1, 2) +# sg_json = student_group.get_json() +# self.assertDictEqual(sg_json, {"studentID": 1, "groupID": 2}) + + +# class LotUnitTests(unittest.TestCase): + +# def test_new_lot(self): +# lot = Lot("Biology", 30, 5000.00) +# assert lot.labType == "Biology" + +# def test_lot_lab_size(self): +# lot = Lot("Biology", 30, 5000.00) +# assert lot.labSize == 30 + +# def test_lot_budget(self): +# lot = Lot("Biology", 30, 5000.00) +# assert lot.budget == 5000.00 + +# def test_lot_get_json(self): +# lot = Lot("Biology", 30, 5000.00) +# lot_json = lot.get_json() +# self.assertDictEqual(lot_json, { +# "id": None, +# "labType": "Biology", +# "labSize": 30, +# "budget": 5000.00 +# }) + +# def test_lot_budget_comparison(self): +# lot = Lot("Biology", 30, 5000.00) +# assert 4999.99 < lot.budget +# assert 5000.01 > lot.budget + + +# class LotGroupUnitTests(unittest.TestCase): + +# def test_new_lot_group(self): +# lot_group = LotGroup(1, 2) +# assert lot_group.lotID == 1 +# assert lot_group.groupID == 2 + +# def test_lot_group_get_json(self): +# lot_group = LotGroup(1, 2) +# lg_json = lot_group.get_json() +# self.assertDictEqual(lg_json, {"lotID": 1, "groupID": 2}) + + +# class RFPRequestUnitTests(unittest.TestCase): + +# def test_new_rfp_request(self): +# rfp = RFPRequest(1, 2, {"detail": "some spec"}) +# assert rfp.groupID == 1 +# assert rfp.lotID == 2 + +# def test_rfp_request_specs(self): +# specs = {"detail": "some spec", "budget": 1000} +# rfp = RFPRequest(1, 2, specs) +# assert rfp.specs == specs + +# def test_rfp_request_get_json(self): +# specs = {"detail": "some spec"} +# rfp = RFPRequest(1, 2, specs) +# rfp_json = rfp.get_json() +# assert rfp_json["groupID"] == 1 +# assert rfp_json["lotID"] == 2 +# assert rfp_json["specs"] == specs + + +# class BidUnitTests(unittest.TestCase): + +# def test_new_bid(self): +# bid = Bid(1, 2, 3, "http://example.com/doc") +# assert bid.lotID == 1 +# assert bid.sourceGroupID == 2 +# assert bid.receipientGroupID == 3 + +# def test_bid_document_link(self): +# bid = Bid(1, 2, 3, "http://example.com/doc") +# assert bid.bidDocumentLink == "http://example.com/doc" + +# def test_bid_timestamp_auto_set(self): +# bid = Bid(1, 2, 3, "http://example.com/doc") +# assert isinstance(bid.timestamp, datetime) + +# def test_bid_timestamp_is_recent(self): +# bid = Bid(1, 2, 3, "http://example.com/doc") +# delta = datetime.utcnow() - bid.timestamp +# assert delta.seconds < 5 + +# def test_bid_get_json(self): +# bid = Bid(1, 2, 3, "http://example.com/doc") +# bid_json = bid.get_json() +# assert bid_json["lotID"] == 1 +# assert bid_json["sourceGroupID"] == 2 +# assert bid_json["receipientGroupID"] == 3 +# assert bid_json["bidDocumentLink"] == "http://example.com/doc" +# assert "timestamp" in bid_json + + +# class EvaluationUnitTests(unittest.TestCase): + +# def test_new_evaluation(self): +# evaluation = Evaluation(1, 2, {"score": 85}) +# assert evaluation.sourceGroupID == 1 +# assert evaluation.receipientGroupID == 2 + +# def test_evaluation_details(self): +# details = {"score": 85, "comments": "Good work"} +# evaluation = Evaluation(1, 2, details) +# assert evaluation.evaluationDetails == details + +# def test_evaluation_get_json(self): +# details = {"score": 85} +# evaluation = Evaluation(1, 2, details) +# eval_json = evaluation.get_json() +# assert eval_json["sourceGroupID"] == 1 +# assert eval_json["receipientGroupID"] == 2 +# assert eval_json["evaluationDetails"] == details \ No newline at end of file From 32bd4eab086865e138dd66920716320bf105c7c1 Mon Sep 17 00:00:00 2001 From: Andrews3002 Date: Fri, 27 Mar 2026 00:44:45 -0400 Subject: [PATCH 19/37] workflow2 complete --- App/controllers/__init__.py | 3 +++ App/controllers/admin.py | 2 +- App/controllers/groupRequest.py | 26 ++++++++++++++++++++++++++ App/tests/integration_test.py | 19 +++++++++++++++++++ 4 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 App/controllers/groupRequest.py diff --git a/App/controllers/__init__.py b/App/controllers/__init__.py index f188b14..c0243a1 100644 --- a/App/controllers/__init__.py +++ b/App/controllers/__init__.py @@ -2,3 +2,6 @@ from .auth import * from .initialize import * from .lot import * +from .groupRequest import * +from .admin import * +from .student import * diff --git a/App/controllers/admin.py b/App/controllers/admin.py index a85cac9..d6ef3b2 100644 --- a/App/controllers/admin.py +++ b/App/controllers/admin.py @@ -3,7 +3,7 @@ def create_admin(username, password): newadmin = Admin(username=username, password=password) - db.session.add(newuser) + db.session.add(newadmin) db.session.commit() def get_admin(id): diff --git a/App/controllers/groupRequest.py b/App/controllers/groupRequest.py new file mode 100644 index 0000000..5402224 --- /dev/null +++ b/App/controllers/groupRequest.py @@ -0,0 +1,26 @@ +from App.models import GroupRequest +from App.database import db + +def create_groupRequest(groupName, members): + newreq = GroupRequest(groupName, members) + db.session.add(newreq) + db.session.commit() + +def get_groupRequest(id): + return db.session.get(GroupRequest, id) + +def get_all_groupRequest(): + return db.session.scalars(db.select(GroupRequest)).all() + +def get_all_groupRequest_json(): + reqs = get_all_groupRequest() + if not reqs: + return [] + reqs = [req.get_json() for req in reqs] + return reqs + +def remove_groupRequest(id): + req = get_groupRequest(id) + if req: + db.session.delete(req) + db.session.commit() \ No newline at end of file diff --git a/App/tests/integration_test.py b/App/tests/integration_test.py index db94c33..ada88fc 100644 --- a/App/tests/integration_test.py +++ b/App/tests/integration_test.py @@ -43,6 +43,7 @@ class Workflow1IntegrationTests(unittest.TestCase): def test_creating_lots(self): db.drop_all() create_db() + create_admin("bob", "bobpass") create_lot("GIS Lab", 20, 160000.00) create_lot("Government Office Lab", 12, 110000.00) lots_json = get_all_lots_json() @@ -77,4 +78,22 @@ def test_remove_lot(self): lot = get_lot(1) assert lot == None +class Workflow2IntegrationTests(unittest.TestCase): + @pytest.mark.run(order=7) + def test_create_groupRequest(self): + remove_lot(2) + create_lot("GIS Lab", 20, 160000.00) + create_lot("Government Office Lab", 12, 110000.00) + create_student("jack", "jackpass") + create_student("cooper", "cooperpass") + create_student("john", "johnpass") + create_student("tony", "tonypass") + + create_groupRequest("TechNova Solution", [1,2,3,4]) + groupReq = get_groupRequest(1) + self.assertDictEqual({ + 'id': 1, + 'groupName': "TechNova Solution", + 'members': [1,2,3,4] + }, groupReq.get_json()) From 6b22b062312624c4c725bd6cafce48b9c92c7e24 Mon Sep 17 00:00:00 2001 From: Andrews3002 Date: Fri, 27 Mar 2026 10:07:11 -0400 Subject: [PATCH 20/37] workflow3 complete --- App/controllers/__init__.py | 3 + App/controllers/group.py | 29 ++++++++++ App/controllers/groupRequest.py | 32 +++++++++-- App/controllers/lot.py | 2 + App/controllers/lotGroup.py | 26 +++++++++ App/controllers/studentGroup.py | 26 +++++++++ App/models/group.py | 2 +- App/models/lot.py | 5 ++ App/tests/integration_test.py | 98 ++++++++++++++++++++++++++++++++- 9 files changed, 216 insertions(+), 7 deletions(-) create mode 100644 App/controllers/group.py create mode 100644 App/controllers/lotGroup.py create mode 100644 App/controllers/studentGroup.py diff --git a/App/controllers/__init__.py b/App/controllers/__init__.py index c0243a1..e920ac7 100644 --- a/App/controllers/__init__.py +++ b/App/controllers/__init__.py @@ -5,3 +5,6 @@ from .groupRequest import * from .admin import * from .student import * +from .group import * +from .studentGroup import * +from .lotGroup import * \ No newline at end of file diff --git a/App/controllers/group.py b/App/controllers/group.py new file mode 100644 index 0000000..53f6096 --- /dev/null +++ b/App/controllers/group.py @@ -0,0 +1,29 @@ +from App.models import Group +from App.database import db + +def create_group(groupName): + group = Group(groupName) + db.session.add(group) + db.session.flush() + group.set_generated_name() + db.session.commit() + return group + +def get_group(id): + return db.session.get(Group, id) + +def get_all_groups(): + return db.session.scalars(db.select(Group)).all() + +def get_all_groups_json(): + groups = get_all_groups() + if not groups: + return [] + groups = [group.get_json() for group in groups] + return groups + +def remove_group(id): + group = get_group(id) + if group: + db.session.delete(group) + db.session.commit() \ No newline at end of file diff --git a/App/controllers/groupRequest.py b/App/controllers/groupRequest.py index 5402224..73f3a1b 100644 --- a/App/controllers/groupRequest.py +++ b/App/controllers/groupRequest.py @@ -2,9 +2,31 @@ from App.database import db def create_groupRequest(groupName, members): - newreq = GroupRequest(groupName, members) - db.session.add(newreq) - db.session.commit() + duplicates = [] + + for member in members: + existing = db.session.scalars(db.select(GroupRequest).filter(GroupRequest.members.contains(member))).first() + if existing: + duplicates.append(member) + + if not duplicates: + newreq = GroupRequest(groupName, members) + db.session.add(newreq) + db.session.commit() + return { + "id": newreq.id, + "status": "good", + "message": "GroupRequest was sent successfully", + "duplicates": duplicates + } + else: + return { + "id": 0, + "status": "bad", + "message": "You or a member you are trying to add is already in a group request", + "duplicates": duplicates + } + def get_groupRequest(id): return db.session.get(GroupRequest, id) @@ -23,4 +45,6 @@ def remove_groupRequest(id): req = get_groupRequest(id) if req: db.session.delete(req) - db.session.commit() \ No newline at end of file + db.session.commit() + return True + return False \ No newline at end of file diff --git a/App/controllers/lot.py b/App/controllers/lot.py index ab9da2f..511ffd5 100644 --- a/App/controllers/lot.py +++ b/App/controllers/lot.py @@ -4,6 +4,8 @@ def create_lot(labType, labSize, budget): newlot = Lot(labType, labSize, budget) db.session.add(newlot) + db.session.flush() + newlot.set_generated_name() db.session.commit() def get_lot(id): diff --git a/App/controllers/lotGroup.py b/App/controllers/lotGroup.py new file mode 100644 index 0000000..cc42baf --- /dev/null +++ b/App/controllers/lotGroup.py @@ -0,0 +1,26 @@ +from App.models import LotGroup +from App.database import db + +def add_lotGroup(lotID, groupID): + newentry = LotGroup(lotID, groupID) + db.session.add(newentry) + db.session.commit() + +def get_lotGroup(lotID, groupID): + return db.session.get(LotGroup, lotID, groupID) + +def get_all_lotGroups(): + return db.session.scalars(db.select(LotGroup)).all() + +def get_all_lotGroups_json(): + entries = get_all_lotGroups() + if not entries: + return [] + entries = [entry.get_json() for entry in entries] + return entries + +def remove_lotGroup(lotID, groupID): + entry = get_lotGroup(lotID, groupID) + if entry: + db.session.delete(entry) + db.session.commit() \ No newline at end of file diff --git a/App/controllers/studentGroup.py b/App/controllers/studentGroup.py new file mode 100644 index 0000000..50f78ad --- /dev/null +++ b/App/controllers/studentGroup.py @@ -0,0 +1,26 @@ +from App.models import StudentGroup +from App.database import db + +def add_studentGroup(studentID, groupID): + newentry = StudentGroup(studentID, groupID) + db.session.add(newentry) + db.session.commit() + +def get_studentGroup(studentID, groupID): + return db.session.get(StudentGroup, studentID, groupID) + +def get_all_studentGroups(): + return db.session.scalars(db.select(StudentGroup)).all() + +def get_all_studentGroups_json(): + entries = get_all_studentGroups() + if not entries: + return [] + entries = [entry.get_json() for entry in entries] + return entries + +def remove_studentGroup(studentID, groupID): + entry = get_studentGroup(studentID, groupID) + if entry: + db.session.delete(entry) + db.session.commit() \ No newline at end of file diff --git a/App/models/group.py b/App/models/group.py index 21a9bf3..ee1daa8 100644 --- a/App/models/group.py +++ b/App/models/group.py @@ -8,7 +8,7 @@ def __init__(self, groupName): self.groupName = groupName def set_generated_name(self): - self.groupName = f"Group{self.id} {self.groupName}" + self.groupName = f"G{self.id} {self.groupName}" def get_json(self): return { diff --git a/App/models/lot.py b/App/models/lot.py index 21c0a32..b779a6c 100644 --- a/App/models/lot.py +++ b/App/models/lot.py @@ -2,6 +2,7 @@ class Lot(db.Model): id = db.Column(db.Integer, primary_key=True) + name = db.Column(db.String(10)) labType = db.Column(db.String(30), nullable=False) labSize = db.Column(db.Integer, nullable=False) budget = db.Column(db.Float, nullable=False) @@ -11,9 +12,13 @@ def __init__(self, labType, labSize, budget): self.labSize = labSize self.budget = budget + def set_generated_name(self): + self.name = f"Lot {self.id}" + def get_json(self): return { 'id': self.id, + 'name': self.name, 'labType': self.labType, 'labSize': self.labSize, 'budget': self.budget diff --git a/App/tests/integration_test.py b/App/tests/integration_test.py index ada88fc..33ff683 100644 --- a/App/tests/integration_test.py +++ b/App/tests/integration_test.py @@ -50,12 +50,14 @@ def test_creating_lots(self): self.assertListEqual([ { 'id': 1, + 'name': "Lot 1", 'labType': "GIS Lab", 'labSize': 20, 'budget': 160000.00 }, { 'id': 2, + 'name': "Lot 2", 'labType': "Government Office Lab", 'labSize': 12, 'budget': 110000.00 @@ -84,16 +86,108 @@ def test_create_groupRequest(self): remove_lot(2) create_lot("GIS Lab", 20, 160000.00) create_lot("Government Office Lab", 12, 110000.00) + create_lot("University Computer Lab", 40, 250000.00) + create_lot("Data Center", 1000, 25000000.00) create_student("jack", "jackpass") create_student("cooper", "cooperpass") create_student("john", "johnpass") create_student("tony", "tonypass") - create_groupRequest("TechNova Solution", [1,2,3,4]) - groupReq = get_groupRequest(1) + create_student("peper", "peperpass") + create_student("steve", "stevepass") + create_student("clint", "clintpass") + create_student("bruce", "brucepass") + + attempt = create_groupRequest("TechNova Solution", [1,2,3,4]) + assert attempt["status"] == "good" + + groupReq = get_groupRequest(attempt["id"]) self.assertDictEqual({ 'id': 1, 'groupName': "TechNova Solution", 'members': [1,2,3,4] }, groupReq.get_json()) + + @pytest.mark.run(order=8) + def test_trying_to_create_group_request_with_a_duplicate_member(self): + attempt = create_groupRequest("ANK Productions", [1,2,3,4]) + assert attempt["status"] == "bad" + assert attempt["duplicates"] == [1,2,3,4] + + attempt = create_groupRequest("ANK Productions", [1,5,6,7]) + assert attempt["status"] == "bad" + assert attempt["duplicates"] == [1] + + attempt = create_groupRequest("ANK Productions", [1,5,2,7]) + assert attempt["status"] == "bad" + assert attempt["duplicates"] == [1,2] + + attempt = create_groupRequest("ANK Productions", [1,3,2,7]) + assert attempt["status"] == "bad" + assert attempt["duplicates"] == [1,3,2] + +class Workflow3IntegrationTests(unittest.TestCase): + @pytest.mark.run(order=9) + def test_approving_groupReuests(self): + attempt = create_groupRequest("ANK Productions", [5,6,7,8]) + assert attempt["status"] == "good" + + groupReq = get_groupRequest(attempt["id"]) + self.assertDictEqual({ + 'id': 2, + 'groupName': "ANK Productions", + 'members': [5,6,7,8] + }, groupReq.get_json()) + + groupReq = get_groupRequest(1) + + group = create_group(groupReq.groupName) + assert group.groupName == "G1 TechNova Solution" + + for member in groupReq.members: + add_studentGroup(member, group.id) + + self.assertListEqual([ + { + 'studentID': 1, + 'groupID': 1 + }, + { + 'studentID': 2, + 'groupID': 1 + }, + { + 'studentID': 3, + 'groupID': 1 + }, + { + 'studentID': 4, + 'groupID': 1 + } + ], get_all_studentGroups_json()) + + add_lotGroup(1, group.id) + add_lotGroup(2, group.id) + + self.assertListEqual([ + { + 'lotID': 1, + 'groupID': 1 + }, + { + 'lotID': 2, + 'groupID': 1 + } + ], get_all_lotGroups_json()) + + removed = remove_groupRequest(1) + assert removed == True + + groupReq = get_groupRequest(1) + assert not groupReq + + @pytest.mark.run(order=10) + def test_rejecting_a_group_request(self): + rejected = remove_groupRequest(2) + assert rejected \ No newline at end of file From dbde84fe152de365e25a3d9b7254270a90262875 Mon Sep 17 00:00:00 2001 From: Andrews3002 Date: Fri, 27 Mar 2026 11:00:37 -0400 Subject: [PATCH 21/37] workflow4 complete --- App/controllers/group.py | 4 +++- App/controllers/lotGroup.py | 6 ++++-- App/controllers/studentGroup.py | 6 ++++-- App/tests/integration_test.py | 21 ++++++++++++++++++++- 4 files changed, 31 insertions(+), 6 deletions(-) diff --git a/App/controllers/group.py b/App/controllers/group.py index 53f6096..32215cd 100644 --- a/App/controllers/group.py +++ b/App/controllers/group.py @@ -26,4 +26,6 @@ def remove_group(id): group = get_group(id) if group: db.session.delete(group) - db.session.commit() \ No newline at end of file + db.session.commit() + return True + return False \ No newline at end of file diff --git a/App/controllers/lotGroup.py b/App/controllers/lotGroup.py index cc42baf..c506ef9 100644 --- a/App/controllers/lotGroup.py +++ b/App/controllers/lotGroup.py @@ -7,7 +7,7 @@ def add_lotGroup(lotID, groupID): db.session.commit() def get_lotGroup(lotID, groupID): - return db.session.get(LotGroup, lotID, groupID) + return db.session.get(LotGroup, (lotID, groupID)) def get_all_lotGroups(): return db.session.scalars(db.select(LotGroup)).all() @@ -23,4 +23,6 @@ def remove_lotGroup(lotID, groupID): entry = get_lotGroup(lotID, groupID) if entry: db.session.delete(entry) - db.session.commit() \ No newline at end of file + db.session.commit() + return True + return False \ No newline at end of file diff --git a/App/controllers/studentGroup.py b/App/controllers/studentGroup.py index 50f78ad..f75a060 100644 --- a/App/controllers/studentGroup.py +++ b/App/controllers/studentGroup.py @@ -7,7 +7,7 @@ def add_studentGroup(studentID, groupID): db.session.commit() def get_studentGroup(studentID, groupID): - return db.session.get(StudentGroup, studentID, groupID) + return db.session.get(StudentGroup, (studentID, groupID)) def get_all_studentGroups(): return db.session.scalars(db.select(StudentGroup)).all() @@ -23,4 +23,6 @@ def remove_studentGroup(studentID, groupID): entry = get_studentGroup(studentID, groupID) if entry: db.session.delete(entry) - db.session.commit() \ No newline at end of file + db.session.commit() + return True + return False \ No newline at end of file diff --git a/App/tests/integration_test.py b/App/tests/integration_test.py index 33ff683..68d7efe 100644 --- a/App/tests/integration_test.py +++ b/App/tests/integration_test.py @@ -190,4 +190,23 @@ def test_approving_groupReuests(self): @pytest.mark.run(order=10) def test_rejecting_a_group_request(self): rejected = remove_groupRequest(2) - assert rejected \ No newline at end of file + assert rejected + +class Workflow4IntegrationTests(unittest.TestCase): + @pytest.mark.run(order=11) + def test_remove_group(self): + group = get_group(1) + entries = db.session.scalars(db.select(StudentGroup).filter_by(groupID = group.id)).all() + + for entry in entries: + removed = remove_studentGroup(entry.studentID, entry.groupID) + assert removed + + entries = db.session.scalars(db.select(LotGroup).filter_by(groupID = group.id)).all() + + for entry in entries: + removed = remove_lotGroup(entry.lotID, entry.groupID) + assert removed + + removed = remove_group(group.id) + assert removed \ No newline at end of file From 85f3efdaf39115a2787904d850148f93d73198d5 Mon Sep 17 00:00:00 2001 From: Andrews3002 Date: Fri, 27 Mar 2026 12:42:39 -0400 Subject: [PATCH 22/37] workflow5 complete --- App/controllers/__init__.py | 3 +- App/controllers/groupRequest.py | 7 ++- App/controllers/lot.py | 17 +++++++ App/controllers/rfpRequest.py | 46 +++++++++++++++++ App/models/lot.py | 13 +++++ App/tests/integration_test.py | 89 ++++++++++++++++++++++++++++++++- 6 files changed, 169 insertions(+), 6 deletions(-) create mode 100644 App/controllers/rfpRequest.py diff --git a/App/controllers/__init__.py b/App/controllers/__init__.py index e920ac7..47d441d 100644 --- a/App/controllers/__init__.py +++ b/App/controllers/__init__.py @@ -7,4 +7,5 @@ from .student import * from .group import * from .studentGroup import * -from .lotGroup import * \ No newline at end of file +from .lotGroup import * +from .rfpRequest import * \ No newline at end of file diff --git a/App/controllers/groupRequest.py b/App/controllers/groupRequest.py index 73f3a1b..a585dc2 100644 --- a/App/controllers/groupRequest.py +++ b/App/controllers/groupRequest.py @@ -27,15 +27,14 @@ def create_groupRequest(groupName, members): "duplicates": duplicates } - def get_groupRequest(id): return db.session.get(GroupRequest, id) -def get_all_groupRequest(): +def get_all_groupRequests(): return db.session.scalars(db.select(GroupRequest)).all() -def get_all_groupRequest_json(): - reqs = get_all_groupRequest() +def get_all_groupRequests_json(): + reqs = get_all_groupRequests() if not reqs: return [] reqs = [req.get_json() for req in reqs] diff --git a/App/controllers/lot.py b/App/controllers/lot.py index 511ffd5..b82f63a 100644 --- a/App/controllers/lot.py +++ b/App/controllers/lot.py @@ -1,5 +1,6 @@ from App.models import Lot from App.database import db +from sqlalchemy.orm.attributes import flag_modified def create_lot(labType, labSize, budget): newlot = Lot(labType, labSize, budget) @@ -35,6 +36,22 @@ def edit_lot(id, labType=None, labSize=None, budget=None): db.session.commit() +def edit_lotRFP_details(id, rfpDetails): + lot = get_lot(id) + if lot: + for spec, details in lot.specs.items(): + lot.specs[spec] = rfpDetails[spec] + flag_modified(lot, "specs") + db.session.commit() + return lot + return None + +def get_lotRFP_details_json(id): + lot = get_lot(id) + if lot: + return lot.specs + return None + def remove_lot(id): lot = get_lot(id) if lot: diff --git a/App/controllers/rfpRequest.py b/App/controllers/rfpRequest.py new file mode 100644 index 0000000..9e4e444 --- /dev/null +++ b/App/controllers/rfpRequest.py @@ -0,0 +1,46 @@ +from App.models import RFPRequest +from App.database import db + +def create_rfpRequest(groupID, lotID, specs): + duplicate = False + + existing = db.session.scalars(db.select(RFPRequest).filter_by(lotID = lotID)).first() + if existing: + duplicate = True + + if not duplicate: + newreq = RFPRequest(groupID, lotID, specs) + db.session.add(newreq) + db.session.commit() + return { + "id": (groupID, lotID), + "status": "good", + "message": "RFP Request was sent successfully" + } + else: + return { + "id": (0, 0), + "status": "bad", + "message": f"You already submitted a group request for Lot{lotID}" + } + +def get_rfpRequest(id): + return db.session.get(RFPRequest, id) + +def get_all_rfpRequests(): + return db.session.scalars(db.select(GroupRequest)).all() + +def get_all_rfpRequests_json(): + reqs = get_all_rfpRequests() + if not reqs: + return [] + reqs = [req.get_json() for req in reqs] + return reqs + +def remove_rfpRequest(id): + req = get_rfpRequest(id) + if req: + db.session.delete(req) + db.session.commit() + return True + return False \ No newline at end of file diff --git a/App/models/lot.py b/App/models/lot.py index b779a6c..80f2d6d 100644 --- a/App/models/lot.py +++ b/App/models/lot.py @@ -6,11 +6,24 @@ class Lot(db.Model): labType = db.Column(db.String(30), nullable=False) labSize = db.Column(db.Integer, nullable=False) budget = db.Column(db.Float, nullable=False) + specs = db.Column(db.JSON) def __init__(self, labType, labSize, budget): self.labType = labType self.labSize = labSize self.budget = budget + self.specs = { + "deviceType": "", + "resolution": "", + "os": "", + "cpu": "", + "ram": "", + "drive": "", + "gpu": "", + "peripherals": "", + "features": "", + "io": "" + } def set_generated_name(self): self.name = f"Lot {self.id}" diff --git a/App/tests/integration_test.py b/App/tests/integration_test.py index 68d7efe..29288ba 100644 --- a/App/tests/integration_test.py +++ b/App/tests/integration_test.py @@ -209,4 +209,91 @@ def test_remove_group(self): assert removed removed = remove_group(group.id) - assert removed \ No newline at end of file + assert removed + +class Workflow5IntegrationTests(unittest.TestCase): + @pytest.mark.run(order=12) + def test_save_rfp_details(self): + attempt = create_groupRequest("TechNova Solution", [1,2,3,4]) + assert attempt["status"] == "good" + + attempt = create_groupRequest("ANK Productions", [5,6,7,8]) + assert attempt["status"] == "good" + + for i in range(1, 3): + groupReq = get_groupRequest(i) + + group = create_group(groupReq.groupName) + + for member in groupReq.members: + add_studentGroup(member, group.id) + + if i == 1: + add_lotGroup(1, group.id) + add_lotGroup(2, group.id) + else: + add_lotGroup(3, group.id) + add_lotGroup(4, group.id) + + removed = remove_groupRequest(i) + + self.assertDictEqual({ + "deviceType": "", + "resolution": "", + "os": "", + "cpu": "", + "ram": "", + "drive": "", + "gpu": "", + "peripherals": "", + "features": "", + "io": "" + }, get_lotRFP_details_json(1)) + + details = { + "deviceType": "Workstation/Laptop/Tablet", + "resolution": "", + "os": "Mac/Windows/Android/IOS/Linux/Chromium", + "cpu": "Core and frequency range eg (quad-core @ 2.2 - 3.0 GHz)", + "ram": "", + "drive": "", + "gpu": "", + "peripherals": "", + "features": "", + "io": "" + } + + lot = edit_lotRFP_details(1, details) + + self.assertDictEqual({ + "deviceType": "Workstation/Laptop/Tablet", + "resolution": "", + "os": "Mac/Windows/Android/IOS/Linux/Chromium", + "cpu": "Core and frequency range eg (quad-core @ 2.2 - 3.0 GHz)", + "ram": "", + "drive": "", + "gpu": "", + "peripherals": "", + "features": "", + "io": "" + }, get_lotRFP_details_json(lot.id)) + + @pytest.mark.run(order=13) + def test_submit_rfp_details(self): + lot = get_lot(1) + attempt = create_rfpRequest(1, lot.id, lot.specs) + self.assertDictEqual({ + "id": (1, 1), + "status": "good", + "message": "RFP Request was sent successfully" + }, attempt) + + @pytest.mark.run(order=14) + def test_submit_duplicate_rfp_details(self): + lot = get_lot(1) + attempt = create_rfpRequest(1, lot.id, lot.specs) + self.assertDictEqual({ + "id": (0, 0), + "status": "bad", + "message": "You already submitted a group request for Lot1" + }, attempt) \ No newline at end of file From 8e7a6ae5f26ea2038bc9e6ef879010d753d2e643 Mon Sep 17 00:00:00 2001 From: Andrews3002 Date: Fri, 27 Mar 2026 13:33:32 -0400 Subject: [PATCH 23/37] workflow6 complete --- App/controllers/__init__.py | 3 +- App/controllers/rfp.py | 28 ++++++++++++ App/controllers/rfpRequest.py | 31 +++++++++---- App/models/RFP.py | 6 +-- App/tests/integration_test.py | 84 +++++++++++++++++++++++++++++++++-- 5 files changed, 134 insertions(+), 18 deletions(-) create mode 100644 App/controllers/rfp.py diff --git a/App/controllers/__init__.py b/App/controllers/__init__.py index 47d441d..dbbe46e 100644 --- a/App/controllers/__init__.py +++ b/App/controllers/__init__.py @@ -8,4 +8,5 @@ from .group import * from .studentGroup import * from .lotGroup import * -from .rfpRequest import * \ No newline at end of file +from .rfpRequest import * +from .rfp import * \ No newline at end of file diff --git a/App/controllers/rfp.py b/App/controllers/rfp.py new file mode 100644 index 0000000..7479775 --- /dev/null +++ b/App/controllers/rfp.py @@ -0,0 +1,28 @@ +from App.models import RFP +from App.database import db + +def create_rfp(groupID, lotID, specs): + rfp = RFP(groupID, lotID, specs) + db.session.add(rfp) + db.session.commit() + +def get_rfp(groupID, lotID): + return db.session.get(RFP, (groupID, lotID)) + +def get_all_rfps(): + return db.session.scalars(db.select(RFP)).all() + +def get_all_rfps_json(): + rfps = get_all_rfps() + if not rfps: + return [] + rfps = [rfp.get_json() for rfp in rfps] + return rfps + +def remove_rfp(groupID, lotID): + rfp = get_rfp(groupID, lotID) + if rfp: + db.session.delete(rfp) + db.session.commit() + return True + return False \ No newline at end of file diff --git a/App/controllers/rfpRequest.py b/App/controllers/rfpRequest.py index 9e4e444..60a9b23 100644 --- a/App/controllers/rfpRequest.py +++ b/App/controllers/rfpRequest.py @@ -1,14 +1,19 @@ -from App.models import RFPRequest +from App.models import RFPRequest, RFP from App.database import db def create_rfpRequest(groupID, lotID, specs): duplicate = False + approved = False existing = db.session.scalars(db.select(RFPRequest).filter_by(lotID = lotID)).first() if existing: duplicate = True - if not duplicate: + appr = db.session.scalars(db.select(RFP).filter_by(lotID = lotID)).first() + if appr: + approved = True + + if not duplicate and not approved: newreq = RFPRequest(groupID, lotID, specs) db.session.add(newreq) db.session.commit() @@ -17,18 +22,26 @@ def create_rfpRequest(groupID, lotID, specs): "status": "good", "message": "RFP Request was sent successfully" } - else: + elif duplicate: return { "id": (0, 0), "status": "bad", - "message": f"You already submitted a group request for Lot{lotID}" + "message": f"You already submitted an rfp request for Lot{lotID}" } + elif approved: + return { + "id": (0, 0), + "status": "bad", + "message": f"You already have an approved RFP in the gallery for Lot{lotID}" + } + else: + return None -def get_rfpRequest(id): - return db.session.get(RFPRequest, id) +def get_rfpRequest(groupID, lotID): + return db.session.get(RFPRequest, (groupID, lotID)) def get_all_rfpRequests(): - return db.session.scalars(db.select(GroupRequest)).all() + return db.session.scalars(db.select(RFPRequest)).all() def get_all_rfpRequests_json(): reqs = get_all_rfpRequests() @@ -37,8 +50,8 @@ def get_all_rfpRequests_json(): reqs = [req.get_json() for req in reqs] return reqs -def remove_rfpRequest(id): - req = get_rfpRequest(id) +def remove_rfpRequest(groupID, lotID): + req = get_rfpRequest(groupID, lotID) if req: db.session.delete(req) db.session.commit() diff --git a/App/models/RFP.py b/App/models/RFP.py index 44a25dd..6b221f8 100644 --- a/App/models/RFP.py +++ b/App/models/RFP.py @@ -1,9 +1,8 @@ from App.database import db class RFP(db.Model): - id = db.Column(db.Integer, primary_key=True) - groupID = db.Column(db.Integer, db.ForeignKey('group.id'), nullable=False) - lotID = db.Column(db.Integer, db.ForeignKey('lot.id'), nullable=False) + groupID = db.Column(db.Integer, db.ForeignKey('group.id'), primary_key=True) + lotID = db.Column(db.Integer, db.ForeignKey('lot.id'), primary_key=True) specs = db.Column(db.JSON) def __init__(self, groupID, lotID, specs): @@ -13,7 +12,6 @@ def __init__(self, groupID, lotID, specs): def get_json(self): return { - 'id': self.id, 'groupID': self.groupID, 'lotID': self.lotID, 'specs': self.specs diff --git a/App/tests/integration_test.py b/App/tests/integration_test.py index 29288ba..507d2c2 100644 --- a/App/tests/integration_test.py +++ b/App/tests/integration_test.py @@ -250,7 +250,7 @@ def test_save_rfp_details(self): "io": "" }, get_lotRFP_details_json(1)) - details = { + details1 = { "deviceType": "Workstation/Laptop/Tablet", "resolution": "", "os": "Mac/Windows/Android/IOS/Linux/Chromium", @@ -263,7 +263,7 @@ def test_save_rfp_details(self): "io": "" } - lot = edit_lotRFP_details(1, details) + lot = edit_lotRFP_details(1, details1) self.assertDictEqual({ "deviceType": "Workstation/Laptop/Tablet", @@ -278,6 +278,34 @@ def test_save_rfp_details(self): "io": "" }, get_lotRFP_details_json(lot.id)) + details2 = { + "deviceType": "", + "resolution": "", + "os": "", + "cpu": "", + "ram": "", + "drive": "HDD/SSD, speed and capacity range, (list if secondary storage)", + "gpu": "", + "peripherals": "Mouse keyboard, touchpad, gamepad, headset, speakers, webcam, adapters, hubs, eGPU, drawing tablet", + "features": "Touch screen, WIFI version, bluetooth, Capture Card, Integrated Speakers, Integrated Webcam, Fingerprint reader, LTE", + "io": "Optical Drive, USB Type-C, USB 3, USB 4, HDMI input, HDMI out, ethernet, Display port, thunderbolt, SD card reader, audio ports" + } + + lot = edit_lotRFP_details(2, details2) + + self.assertDictEqual({ + "deviceType": "", + "resolution": "", + "os": "", + "cpu": "", + "ram": "", + "drive": "HDD/SSD, speed and capacity range, (list if secondary storage)", + "gpu": "", + "peripherals": "Mouse keyboard, touchpad, gamepad, headset, speakers, webcam, adapters, hubs, eGPU, drawing tablet", + "features": "Touch screen, WIFI version, bluetooth, Capture Card, Integrated Speakers, Integrated Webcam, Fingerprint reader, LTE", + "io": "Optical Drive, USB Type-C, USB 3, USB 4, HDMI input, HDMI out, ethernet, Display port, thunderbolt, SD card reader, audio ports" + }, get_lotRFP_details_json(lot.id)) + @pytest.mark.run(order=13) def test_submit_rfp_details(self): lot = get_lot(1) @@ -287,6 +315,14 @@ def test_submit_rfp_details(self): "status": "good", "message": "RFP Request was sent successfully" }, attempt) + + lot = get_lot(2) + attempt = create_rfpRequest(1, lot.id, lot.specs) + self.assertDictEqual({ + "id": (1, 2), + "status": "good", + "message": "RFP Request was sent successfully" + }, attempt) @pytest.mark.run(order=14) def test_submit_duplicate_rfp_details(self): @@ -295,5 +331,45 @@ def test_submit_duplicate_rfp_details(self): self.assertDictEqual({ "id": (0, 0), "status": "bad", - "message": "You already submitted a group request for Lot1" - }, attempt) \ No newline at end of file + "message": "You already submitted an rfp request for Lot1" + }, attempt) + +class Workflow6IntegrationTests(unittest.TestCase): + @pytest.mark.run(order=15) + def test_approve_rfp_Request(self): + rfpRequest = get_rfpRequest(1, 1) + + create_rfp(rfpRequest.groupID, rfpRequest.lotID, rfpRequest.specs) + + rfp = get_rfp(1, 1) + + self.assertDictEqual({ + 'groupID': 1, + 'lotID': 1, + 'specs': { + "deviceType": "Workstation/Laptop/Tablet", + "resolution": "", + "os": "Mac/Windows/Android/IOS/Linux/Chromium", + "cpu": "Core and frequency range eg (quad-core @ 2.2 - 3.0 GHz)", + "ram": "", + "drive": "", + "gpu": "", + "peripherals": "", + "features": "", + "io": "" + } + }, rfp.get_json()) + + removed = remove_rfpRequest(1, 1) + assert removed + + @pytest.mark.run(order=16) + def test_reject_rfp_Request(self): + removed = remove_rfpRequest(1, 2) + assert removed + + reqs = get_all_rfpRequests() + assert not reqs + + rfps = get_all_rfps() + assert len(rfps) == 1 \ No newline at end of file From a50ca85a667e69fefe0f7dab4bac133cc37899d5 Mon Sep 17 00:00:00 2001 From: Andrews3002 Date: Fri, 27 Mar 2026 17:23:23 -0400 Subject: [PATCH 24/37] workflow7 complete --- App/controllers/__init__.py | 4 +- App/controllers/bid.py | 40 ++++ App/controllers/groupRequest.py | 49 ---- App/controllers/lot.py | 26 ++- App/controllers/rfp.py | 5 +- App/controllers/rfpRequest.py | 59 ----- App/models/RFP.py | 27 ++- App/models/__init__.py | 4 +- App/models/group.py | 4 +- App/models/groupRequest.py | 17 -- App/models/lot.py | 23 +- App/models/rfpRequest.py | 18 -- App/tests/integration_test.py | 395 ++++++++++++++++---------------- App/tests/unit_test.py | 2 +- 14 files changed, 304 insertions(+), 369 deletions(-) create mode 100644 App/controllers/bid.py delete mode 100644 App/controllers/groupRequest.py delete mode 100644 App/controllers/rfpRequest.py delete mode 100644 App/models/groupRequest.py delete mode 100644 App/models/rfpRequest.py diff --git a/App/controllers/__init__.py b/App/controllers/__init__.py index dbbe46e..bab5e9f 100644 --- a/App/controllers/__init__.py +++ b/App/controllers/__init__.py @@ -2,11 +2,9 @@ from .auth import * from .initialize import * from .lot import * -from .groupRequest import * from .admin import * from .student import * from .group import * from .studentGroup import * from .lotGroup import * -from .rfpRequest import * -from .rfp import * \ No newline at end of file +from .RFP import * \ No newline at end of file diff --git a/App/controllers/bid.py b/App/controllers/bid.py new file mode 100644 index 0000000..eded35a --- /dev/null +++ b/App/controllers/bid.py @@ -0,0 +1,40 @@ +from App.models import Bid +from App.database import db + +def create_bid(lotID, sourceGroupID, receipientGroupID, bidDocumentLink): + newlot = Lot(labType, labSize, budget) + db.session.add(newlot) + db.session.commit() + +def get_lot(id): + return db.session.get(Lot, id) + +def get_all_lots(): + return db.session.scalars(db.select(Lot)).all() + +def get_all_lots_json(): + lots = get_all_lots() + if not lots: + return [] + lots = [lot.get_json() for lot in lots] + return lots + +def edit_lot(id, labType=None, labSize=None, budget=None): + lot = get_lot(id) + if lot: + if labType: + lot.labType = labType + + if labSize: + lot.labSize = labSize + + if budget: + lot.budget = budget + + db.session.commit() + +def remove_lot(id): + lot = get_lot(id) + if lot: + db.session.delete(lot) + db.session.commit() \ No newline at end of file diff --git a/App/controllers/groupRequest.py b/App/controllers/groupRequest.py deleted file mode 100644 index a585dc2..0000000 --- a/App/controllers/groupRequest.py +++ /dev/null @@ -1,49 +0,0 @@ -from App.models import GroupRequest -from App.database import db - -def create_groupRequest(groupName, members): - duplicates = [] - - for member in members: - existing = db.session.scalars(db.select(GroupRequest).filter(GroupRequest.members.contains(member))).first() - if existing: - duplicates.append(member) - - if not duplicates: - newreq = GroupRequest(groupName, members) - db.session.add(newreq) - db.session.commit() - return { - "id": newreq.id, - "status": "good", - "message": "GroupRequest was sent successfully", - "duplicates": duplicates - } - else: - return { - "id": 0, - "status": "bad", - "message": "You or a member you are trying to add is already in a group request", - "duplicates": duplicates - } - -def get_groupRequest(id): - return db.session.get(GroupRequest, id) - -def get_all_groupRequests(): - return db.session.scalars(db.select(GroupRequest)).all() - -def get_all_groupRequests_json(): - reqs = get_all_groupRequests() - if not reqs: - return [] - reqs = [req.get_json() for req in reqs] - return reqs - -def remove_groupRequest(id): - req = get_groupRequest(id) - if req: - db.session.delete(req) - db.session.commit() - return True - return False \ No newline at end of file diff --git a/App/controllers/lot.py b/App/controllers/lot.py index b82f63a..b182e18 100644 --- a/App/controllers/lot.py +++ b/App/controllers/lot.py @@ -36,12 +36,30 @@ def edit_lot(id, labType=None, labSize=None, budget=None): db.session.commit() -def edit_lotRFP_details(id, rfpDetails): +def edit_lotRFP_details(id, deviceType=None, resolution=None, os=None, cpu=None, ram=None, drive=None, gpu=None, peripherals=None, features=None, io=None): lot = get_lot(id) if lot: - for spec, details in lot.specs.items(): - lot.specs[spec] = rfpDetails[spec] - flag_modified(lot, "specs") + if deviceType: + lot.deviceType = deviceType + if resolution: + lot.resolution = resolution + if os: + lot.os = os + if cpu: + lot.cpu = cpu + if ram: + lot.ram = ram + if drive: + lot.drive = drive + if gpu: + lot.gpu = gpu + if peripherals: + lot.peripherals = peripherals + if features: + lot.features = features + if io: + lot.io = io + db.session.commit() return lot return None diff --git a/App/controllers/rfp.py b/App/controllers/rfp.py index 7479775..4bbba87 100644 --- a/App/controllers/rfp.py +++ b/App/controllers/rfp.py @@ -1,10 +1,11 @@ from App.models import RFP from App.database import db -def create_rfp(groupID, lotID, specs): - rfp = RFP(groupID, lotID, specs) +def create_rfp(groupID, lotID): + rfp = RFP(groupID, lotID) db.session.add(rfp) db.session.commit() + return rfp def get_rfp(groupID, lotID): return db.session.get(RFP, (groupID, lotID)) diff --git a/App/controllers/rfpRequest.py b/App/controllers/rfpRequest.py deleted file mode 100644 index 60a9b23..0000000 --- a/App/controllers/rfpRequest.py +++ /dev/null @@ -1,59 +0,0 @@ -from App.models import RFPRequest, RFP -from App.database import db - -def create_rfpRequest(groupID, lotID, specs): - duplicate = False - approved = False - - existing = db.session.scalars(db.select(RFPRequest).filter_by(lotID = lotID)).first() - if existing: - duplicate = True - - appr = db.session.scalars(db.select(RFP).filter_by(lotID = lotID)).first() - if appr: - approved = True - - if not duplicate and not approved: - newreq = RFPRequest(groupID, lotID, specs) - db.session.add(newreq) - db.session.commit() - return { - "id": (groupID, lotID), - "status": "good", - "message": "RFP Request was sent successfully" - } - elif duplicate: - return { - "id": (0, 0), - "status": "bad", - "message": f"You already submitted an rfp request for Lot{lotID}" - } - elif approved: - return { - "id": (0, 0), - "status": "bad", - "message": f"You already have an approved RFP in the gallery for Lot{lotID}" - } - else: - return None - -def get_rfpRequest(groupID, lotID): - return db.session.get(RFPRequest, (groupID, lotID)) - -def get_all_rfpRequests(): - return db.session.scalars(db.select(RFPRequest)).all() - -def get_all_rfpRequests_json(): - reqs = get_all_rfpRequests() - if not reqs: - return [] - reqs = [req.get_json() for req in reqs] - return reqs - -def remove_rfpRequest(groupID, lotID): - req = get_rfpRequest(groupID, lotID) - if req: - db.session.delete(req) - db.session.commit() - return True - return False \ No newline at end of file diff --git a/App/models/RFP.py b/App/models/RFP.py index 6b221f8..d150ca8 100644 --- a/App/models/RFP.py +++ b/App/models/RFP.py @@ -3,16 +3,35 @@ class RFP(db.Model): groupID = db.Column(db.Integer, db.ForeignKey('group.id'), primary_key=True) lotID = db.Column(db.Integer, db.ForeignKey('lot.id'), primary_key=True) - specs = db.Column(db.JSON) + status = db.Column(db.String(30), default="requested") + deviceType = db.Column(db.String(1000), default="") + resolution = db.Column(db.String(1000), default="") + os = db.Column(db.String(1000), default="") + cpu = db.Column(db.String(1000), default="") + ram = db.Column(db.String(1000), default="") + drive = db.Column(db.String(1000), default="") + gpu = db.Column(db.String(1000), default="") + peripherals = db.Column(db.String(1000), default="") + features = db.Column(db.String(1000), default="") + io = db.Column(db.String(1000), default="") - def __init__(self, groupID, lotID, specs): + def __init__(self, groupID, lotID): self.groupID = groupID self.lotID = lotID - self.specs = specs def get_json(self): return { 'groupID': self.groupID, 'lotID': self.lotID, - 'specs': self.specs + 'status': self.status, + 'Type': self.deviceType, + 'Screen Size & Resolution': self.resolution, + 'Operating System(s)': self.os, + 'CPU': self.cpu, + 'Memory (RAM)': self.ram, + 'Hard Drive': self.drive, + 'Graphics': self.gpu, + 'External Peripherals': self.peripherals, + 'Features': self.features, + 'I/O': self.io } \ No newline at end of file diff --git a/App/models/__init__.py b/App/models/__init__.py index bb31897..12a5df4 100644 --- a/App/models/__init__.py +++ b/App/models/__init__.py @@ -3,10 +3,8 @@ from .student import * from .lot import * from .group import * -from .groupRequest import * from .lotGroup import * from .studentGroup import * -from .rfpRequest import * -from .rfp import * +from .RFP import * from .bid import * from .evaluation import * \ No newline at end of file diff --git a/App/models/group.py b/App/models/group.py index ee1daa8..4061b85 100644 --- a/App/models/group.py +++ b/App/models/group.py @@ -3,6 +3,7 @@ class Group(db.Model): id = db.Column(db.Integer, primary_key=True) groupName = db.Column(db.String(30), nullable=False, unique=True) + status = db.Column(db.String(30), nullable=False, default="requested") def __init__(self, groupName): self.groupName = groupName @@ -13,5 +14,6 @@ def set_generated_name(self): def get_json(self): return { 'id': self.id, - 'groupName': self.groupName + 'groupName': self.groupName, + 'status': self.status } \ No newline at end of file diff --git a/App/models/groupRequest.py b/App/models/groupRequest.py deleted file mode 100644 index bd5533c..0000000 --- a/App/models/groupRequest.py +++ /dev/null @@ -1,17 +0,0 @@ -from App.database import db - -class GroupRequest(db.Model): - id = db.Column(db.Integer, primary_key=True) - groupName = db.Column(db.String(30), nullable=False) - members = db.Column(db.JSON, nullable=False, default=list) - - def __init__(self, groupName, members: list[int]): - self.groupName = groupName - self.members = members - - def get_json(self): - return { - 'id': self.id, - 'groupName': self.groupName, - 'members': self.members - } \ No newline at end of file diff --git a/App/models/lot.py b/App/models/lot.py index 80f2d6d..5f56dd1 100644 --- a/App/models/lot.py +++ b/App/models/lot.py @@ -6,24 +6,21 @@ class Lot(db.Model): labType = db.Column(db.String(30), nullable=False) labSize = db.Column(db.Integer, nullable=False) budget = db.Column(db.Float, nullable=False) - specs = db.Column(db.JSON) + deviceType = db.Column(db.String(1000), default="") + resolution = db.Column(db.String(1000), default="") + os = db.Column(db.String(1000), default="") + cpu = db.Column(db.String(1000), default="") + ram = db.Column(db.String(1000), default="") + drive = db.Column(db.String(1000), default="") + gpu = db.Column(db.String(1000), default="") + peripherals = db.Column(db.String(1000), default="") + features = db.Column(db.String(1000), default="") + io = db.Column(db.String(1000), default="") def __init__(self, labType, labSize, budget): self.labType = labType self.labSize = labSize self.budget = budget - self.specs = { - "deviceType": "", - "resolution": "", - "os": "", - "cpu": "", - "ram": "", - "drive": "", - "gpu": "", - "peripherals": "", - "features": "", - "io": "" - } def set_generated_name(self): self.name = f"Lot {self.id}" diff --git a/App/models/rfpRequest.py b/App/models/rfpRequest.py deleted file mode 100644 index 91c0cca..0000000 --- a/App/models/rfpRequest.py +++ /dev/null @@ -1,18 +0,0 @@ -from App.database import db - -class RFPRequest(db.Model): - groupID = db.Column(db.Integer, db.ForeignKey('group.id'), primary_key=True) - lotID = db.Column(db.Integer, db.ForeignKey('lot.id'), primary_key=True) - specs = db.Column(db.JSON) - - def __init__(self, groupID, lotID, specs): - self.groupID = groupID - self.lotID = lotID - self.specs = specs - - def get_json(self): - return { - 'groupID': self.groupID, - 'lotID': self.lotID, - 'specs': self.specs - } \ No newline at end of file diff --git a/App/tests/integration_test.py b/App/tests/integration_test.py index 507d2c2..98de246 100644 --- a/App/tests/integration_test.py +++ b/App/tests/integration_test.py @@ -5,7 +5,7 @@ from App.main import create_app from App.database import db, create_db -from App.models import User, Admin, Student, Group, GroupRequest, StudentGroup, Lot, LotGroup, RFPRequest, Bid, Evaluation +from App.models import User, Admin, Student, Group, StudentGroup, Lot, LotGroup, Bid, Evaluation, RFP from App.controllers import * @pytest.fixture(autouse=True, scope="module") @@ -99,55 +99,20 @@ def test_create_groupRequest(self): create_student("clint", "clintpass") create_student("bruce", "brucepass") - attempt = create_groupRequest("TechNova Solution", [1,2,3,4]) - assert attempt["status"] == "good" + groupName = "TechNova Solution" + members = [1,2,3,4] - groupReq = get_groupRequest(attempt["id"]) + group = create_group(groupName) + group = get_group(1) self.assertDictEqual({ 'id': 1, - 'groupName': "TechNova Solution", - 'members': [1,2,3,4] - }, groupReq.get_json()) - - @pytest.mark.run(order=8) - def test_trying_to_create_group_request_with_a_duplicate_member(self): - attempt = create_groupRequest("ANK Productions", [1,2,3,4]) - assert attempt["status"] == "bad" - assert attempt["duplicates"] == [1,2,3,4] - - attempt = create_groupRequest("ANK Productions", [1,5,6,7]) - assert attempt["status"] == "bad" - assert attempt["duplicates"] == [1] - - attempt = create_groupRequest("ANK Productions", [1,5,2,7]) - assert attempt["status"] == "bad" - assert attempt["duplicates"] == [1,2] - - attempt = create_groupRequest("ANK Productions", [1,3,2,7]) - assert attempt["status"] == "bad" - assert attempt["duplicates"] == [1,3,2] - -class Workflow3IntegrationTests(unittest.TestCase): - @pytest.mark.run(order=9) - def test_approving_groupReuests(self): - attempt = create_groupRequest("ANK Productions", [5,6,7,8]) - assert attempt["status"] == "good" - - groupReq = get_groupRequest(attempt["id"]) - self.assertDictEqual({ - 'id': 2, - 'groupName': "ANK Productions", - 'members': [5,6,7,8] - }, groupReq.get_json()) - - groupReq = get_groupRequest(1) + 'groupName': "G1 TechNova Solution", + 'status': "requested" + }, group.get_json()) - group = create_group(groupReq.groupName) - assert group.groupName == "G1 TechNova Solution" - - for member in groupReq.members: + for member in members: add_studentGroup(member, group.id) - + self.assertListEqual([ { 'studentID': 1, @@ -164,11 +129,41 @@ def test_approving_groupReuests(self): { 'studentID': 4, 'groupID': 1 - } + }, ], get_all_studentGroups_json()) - add_lotGroup(1, group.id) - add_lotGroup(2, group.id) + @pytest.mark.run(order=8) + def test_trying_to_create_group_request_with_a_duplicate_member(self): + groupName = "ANK Productions" + members = [1,2,3,4] + + duplicates = [] + + for member in members: + existing = db.session.scalars(db.select(StudentGroup).filter_by(studentID = member)).first() + if existing: + duplicates.append(member) + + assert duplicates == [1,2,3,4] + + members = [5,6,7,8] + group = create_group(groupName) + + for member in members: + add_studentGroup(member, group.id) + +class Workflow3IntegrationTests(unittest.TestCase): + @pytest.mark.run(order=9) + def test_approving_groupReuests(self): + groupID = 1 + Lot1ID = 1 + Lot2ID = 2 + group = get_group(groupID) + add_lotGroup(Lot1ID, group.id) + add_lotGroup(Lot2ID, group.id) + + group.status = "approved" + db.session.commit() self.assertListEqual([ { @@ -181,195 +176,205 @@ def test_approving_groupReuests(self): } ], get_all_lotGroups_json()) - removed = remove_groupRequest(1) - assert removed == True - - groupReq = get_groupRequest(1) - assert not groupReq + group = get_group(1) + assert group.status == "approved" @pytest.mark.run(order=10) def test_rejecting_a_group_request(self): - rejected = remove_groupRequest(2) - assert rejected + groupID = 2 + + entries = db.session.scalars(db.select(StudentGroup).filter_by(groupID = groupID)).all() + + for entry in entries: + removed = remove_studentGroup(entry.studentID, groupID) + assert removed + + entries = db.session.scalars(db.select(LotGroup).filter_by(groupID = groupID)).all() + + for entry in entries: + removed = remove_lotGroup(entry.lotID, groupID) + assert removed + + removed = remove_group(groupID) + assert removed class Workflow4IntegrationTests(unittest.TestCase): @pytest.mark.run(order=11) def test_remove_group(self): - group = get_group(1) - entries = db.session.scalars(db.select(StudentGroup).filter_by(groupID = group.id)).all() + groupID = 1 + + entries = db.session.scalars(db.select(StudentGroup).filter_by(groupID = groupID)).all() for entry in entries: - removed = remove_studentGroup(entry.studentID, entry.groupID) + removed = remove_studentGroup(entry.studentID, groupID) assert removed - - entries = db.session.scalars(db.select(LotGroup).filter_by(groupID = group.id)).all() + + entries = db.session.scalars(db.select(LotGroup).filter_by(groupID = groupID)).all() for entry in entries: - removed = remove_lotGroup(entry.lotID, entry.groupID) + removed = remove_lotGroup(entry.lotID, groupID) assert removed - removed = remove_group(group.id) + removed = remove_group(groupID) assert removed + class Workflow5IntegrationTests(unittest.TestCase): @pytest.mark.run(order=12) def test_save_rfp_details(self): - attempt = create_groupRequest("TechNova Solution", [1,2,3,4]) - assert attempt["status"] == "good" + lotID = 1 + deviceType = "Workstation/Laptop/Tablet" + resolution = "" + os = "Mac/Windows/Android/IOS/Linux/Chromium" + cpu = "Core and frequency range eg (quad-core @ 2.2 - 3.0 GHz)" + ram = "" + drive = "" + gpu = "" + peripherals = "" + features = "" + io = "" + + lot = edit_lotRFP_details(lotID, deviceType=deviceType, os=os, cpu=cpu) + assert lot.deviceType == "Workstation/Laptop/Tablet" + assert lot.resolution == "" + assert lot.os == "Mac/Windows/Android/IOS/Linux/Chromium" + assert lot.cpu == "Core and frequency range eg (quad-core @ 2.2 - 3.0 GHz)" + assert lot.ram == "" + assert lot.drive == "" + assert lot.gpu == "" + assert lot.peripherals == "" + assert lot.features == "" + assert lot.io == "" + + lotID = 2 + deviceType = "" + resolution = "" + os = "" + cpu = "" + ram = "" + drive = "HDD/SSD, speed and capacity range, (list if secondary storage)" + gpu = "Integrated/Dedicated with memory range" + peripherals = "" + features = "Touch screen, WIFI version, bluetooth, Capture Card, Integrated Speakers, Integrated Webcam, Fingerprint reader, LTE" + io = "" + + lot = edit_lotRFP_details(lotID, drive=drive, gpu=gpu, features=features) + assert lot.deviceType == "" + assert lot.resolution == "" + assert lot.os == "" + assert lot.cpu == "" + assert lot.ram == "" + assert lot.drive == "HDD/SSD, speed and capacity range, (list if secondary storage)" + assert lot.gpu == "Integrated/Dedicated with memory range" + assert lot.peripherals == "" + assert lot.features == "Touch screen, WIFI version, bluetooth, Capture Card, Integrated Speakers, Integrated Webcam, Fingerprint reader, LTE" + assert lot.io == "" - attempt = create_groupRequest("ANK Productions", [5,6,7,8]) - assert attempt["status"] == "good" - for i in range(1, 3): - groupReq = get_groupRequest(i) + @pytest.mark.run(order=13) + def test_submit_rfp_details(self): + lotID = 1 + groupID = 1 - group = create_group(groupReq.groupName) + rfp = create_rfp(lotID, groupID) - for member in groupReq.members: - add_studentGroup(member, group.id) + lot = get_lot(lotID) - if i == 1: - add_lotGroup(1, group.id) - add_lotGroup(2, group.id) - else: - add_lotGroup(3, group.id) - add_lotGroup(4, group.id) + rfp.deviceType = lot.deviceType + rfp.resolution = lot.resolution + rfp.os = lot.os + rfp.cpu = lot.cpu + rfp.ram = lot.ram + rfp.drive = lot.drive + rfp.gpu = lot.gpu + rfp.peripherals = lot.peripherals + rfp.features = lot.features + rfp.io = lot.io - removed = remove_groupRequest(i) + db.session.commit() + + rfp = get_rfp(groupID, lotID) + assert rfp.deviceType == "Workstation/Laptop/Tablet" + assert rfp.resolution == "" + assert rfp.os == "Mac/Windows/Android/IOS/Linux/Chromium" + assert rfp.cpu == "Core and frequency range eg (quad-core @ 2.2 - 3.0 GHz)" + assert rfp.ram == "" + assert rfp.drive == "" + assert rfp.gpu == "" + assert rfp.peripherals == "" + assert rfp.features == "" + assert rfp.io == "" + assert rfp.status == "requested" - self.assertDictEqual({ - "deviceType": "", - "resolution": "", - "os": "", - "cpu": "", - "ram": "", - "drive": "", - "gpu": "", - "peripherals": "", - "features": "", - "io": "" - }, get_lotRFP_details_json(1)) - details1 = { - "deviceType": "Workstation/Laptop/Tablet", - "resolution": "", - "os": "Mac/Windows/Android/IOS/Linux/Chromium", - "cpu": "Core and frequency range eg (quad-core @ 2.2 - 3.0 GHz)", - "ram": "", - "drive": "", - "gpu": "", - "peripherals": "", - "features": "", - "io": "" - } + @pytest.mark.run(order=14) + def test_submit_duplicate_rfp_details(self): + lotID = 1 + groupID = 1 - lot = edit_lotRFP_details(1, details1) + rfp = db.session.scalars(db.select(RFP).filter_by(groupID=groupID, lotID=lotID)).first() + assert rfp + assert rfp.status == "requested" - self.assertDictEqual({ - "deviceType": "Workstation/Laptop/Tablet", - "resolution": "", - "os": "Mac/Windows/Android/IOS/Linux/Chromium", - "cpu": "Core and frequency range eg (quad-core @ 2.2 - 3.0 GHz)", - "ram": "", - "drive": "", - "gpu": "", - "peripherals": "", - "features": "", - "io": "" - }, get_lotRFP_details_json(lot.id)) - - details2 = { - "deviceType": "", - "resolution": "", - "os": "", - "cpu": "", - "ram": "", - "drive": "HDD/SSD, speed and capacity range, (list if secondary storage)", - "gpu": "", - "peripherals": "Mouse keyboard, touchpad, gamepad, headset, speakers, webcam, adapters, hubs, eGPU, drawing tablet", - "features": "Touch screen, WIFI version, bluetooth, Capture Card, Integrated Speakers, Integrated Webcam, Fingerprint reader, LTE", - "io": "Optical Drive, USB Type-C, USB 3, USB 4, HDMI input, HDMI out, ethernet, Display port, thunderbolt, SD card reader, audio ports" - } + lotID = 2 - lot = edit_lotRFP_details(2, details2) + rfp = create_rfp(groupID, lotID) + assert rfp - self.assertDictEqual({ - "deviceType": "", - "resolution": "", - "os": "", - "cpu": "", - "ram": "", - "drive": "HDD/SSD, speed and capacity range, (list if secondary storage)", - "gpu": "", - "peripherals": "Mouse keyboard, touchpad, gamepad, headset, speakers, webcam, adapters, hubs, eGPU, drawing tablet", - "features": "Touch screen, WIFI version, bluetooth, Capture Card, Integrated Speakers, Integrated Webcam, Fingerprint reader, LTE", - "io": "Optical Drive, USB Type-C, USB 3, USB 4, HDMI input, HDMI out, ethernet, Display port, thunderbolt, SD card reader, audio ports" - }, get_lotRFP_details_json(lot.id)) + lot = get_lot(lotID) - @pytest.mark.run(order=13) - def test_submit_rfp_details(self): - lot = get_lot(1) - attempt = create_rfpRequest(1, lot.id, lot.specs) - self.assertDictEqual({ - "id": (1, 1), - "status": "good", - "message": "RFP Request was sent successfully" - }, attempt) + rfp.deviceType = lot.deviceType + rfp.resolution = lot.resolution + rfp.os = lot.os + rfp.cpu = lot.cpu + rfp.ram = lot.ram + rfp.drive = lot.drive + rfp.gpu = lot.gpu + rfp.peripherals = lot.peripherals + rfp.features = lot.features + rfp.io = lot.io - lot = get_lot(2) - attempt = create_rfpRequest(1, lot.id, lot.specs) - self.assertDictEqual({ - "id": (1, 2), - "status": "good", - "message": "RFP Request was sent successfully" - }, attempt) - - @pytest.mark.run(order=14) - def test_submit_duplicate_rfp_details(self): - lot = get_lot(1) - attempt = create_rfpRequest(1, lot.id, lot.specs) - self.assertDictEqual({ - "id": (0, 0), - "status": "bad", - "message": "You already submitted an rfp request for Lot1" - }, attempt) + db.session.commit() + + rfp = get_rfp(groupID, lotID) + assert rfp.deviceType == "" + assert rfp.resolution == "" + assert rfp.os == "" + assert rfp.cpu == "" + assert rfp.ram == "" + assert rfp.drive == "HDD/SSD, speed and capacity range, (list if secondary storage)" + assert rfp.gpu == "Integrated/Dedicated with memory range" + assert rfp.peripherals == "" + assert rfp.features == "Touch screen, WIFI version, bluetooth, Capture Card, Integrated Speakers, Integrated Webcam, Fingerprint reader, LTE" + assert rfp.io == "" + assert rfp.status == "requested" class Workflow6IntegrationTests(unittest.TestCase): @pytest.mark.run(order=15) def test_approve_rfp_Request(self): - rfpRequest = get_rfpRequest(1, 1) - - create_rfp(rfpRequest.groupID, rfpRequest.lotID, rfpRequest.specs) - - rfp = get_rfp(1, 1) + lotID = 1 + groupID = 1 - self.assertDictEqual({ - 'groupID': 1, - 'lotID': 1, - 'specs': { - "deviceType": "Workstation/Laptop/Tablet", - "resolution": "", - "os": "Mac/Windows/Android/IOS/Linux/Chromium", - "cpu": "Core and frequency range eg (quad-core @ 2.2 - 3.0 GHz)", - "ram": "", - "drive": "", - "gpu": "", - "peripherals": "", - "features": "", - "io": "" - } - }, rfp.get_json()) + rfp = get_rfp(groupID, lotID) + rfp.status = "approved" + db.session.commit() - removed = remove_rfpRequest(1, 1) - assert removed + rfp = get_rfp(groupID, lotID) + assert rfp.status == "approved" @pytest.mark.run(order=16) def test_reject_rfp_Request(self): - removed = remove_rfpRequest(1, 2) + groupID = 1 + lotID = 2 + + removed = remove_rfp(groupID, lotID) assert removed - reqs = get_all_rfpRequests() - assert not reqs +class Workflow7IntegrationTests(unittest.TestCase): + @pytest.mark.run(order=17) + def test_remove_rfp(self): + groupID = 1 + lotID = 1 - rfps = get_all_rfps() - assert len(rfps) == 1 \ No newline at end of file + removed = remove_rfp(groupID, lotID) + assert removed \ No newline at end of file diff --git a/App/tests/unit_test.py b/App/tests/unit_test.py index 62a2381..99a6a29 100644 --- a/App/tests/unit_test.py +++ b/App/tests/unit_test.py @@ -5,7 +5,7 @@ # from App.main import create_app # from App.database import db, create_db -# from App.models import User, Admin, Student, Group, GroupRequest, StudentGroup, Lot, LotGroup, RFPRequest, Bid, Evaluation +# from App.models import User, Admin, Student, Group, StudentGroup, Lot, LotGroup, Bid, Evaluation, RFP # class AdminUnitTests(unittest.TestCase): From bd2966c6f45dace679a4f8bab277cf699322f7e5 Mon Sep 17 00:00:00 2001 From: Andrews3002 Date: Sat, 28 Mar 2026 12:01:38 -0400 Subject: [PATCH 25/37] workflow8 complete --- .gitignore | 3 +- App/controllers/__init__.py | 3 +- App/controllers/bid.py | 45 +++++--------- App/controllers/group.py | 5 ++ App/controllers/rfp.py | 19 ++++++ App/models/bid.py | 2 +- App/tests/integration_test.py | 108 ++++++++++++++++++++-------------- 7 files changed, 108 insertions(+), 77 deletions(-) diff --git a/.gitignore b/.gitignore index cfa62a9..ef4d255 100644 --- a/.gitignore +++ b/.gitignore @@ -153,4 +153,5 @@ cython_debug/ # option (not recommended) you can uncomment the following to ignore the entire idea folder. #.idea/ -node_modules/ \ No newline at end of file +node_modules/ +instance_tracker.txt \ No newline at end of file diff --git a/App/controllers/__init__.py b/App/controllers/__init__.py index bab5e9f..5a6d57b 100644 --- a/App/controllers/__init__.py +++ b/App/controllers/__init__.py @@ -7,4 +7,5 @@ from .group import * from .studentGroup import * from .lotGroup import * -from .RFP import * \ No newline at end of file +from .RFP import * +from .bid import * \ No newline at end of file diff --git a/App/controllers/bid.py b/App/controllers/bid.py index eded35a..fbcf5f3 100644 --- a/App/controllers/bid.py +++ b/App/controllers/bid.py @@ -2,39 +2,26 @@ from App.database import db def create_bid(lotID, sourceGroupID, receipientGroupID, bidDocumentLink): - newlot = Lot(labType, labSize, budget) - db.session.add(newlot) + newbid = Bid(lotID, sourceGroupID, receipientGroupID, bidDocumentLink) + db.session.add(newbid) db.session.commit() + return newbid -def get_lot(id): - return db.session.get(Lot, id) +def get_bid(id): + return db.session.get(Bid, id) -def get_all_lots(): - return db.session.scalars(db.select(Lot)).all() +def get_all_bids(): + return db.session.scalars(db.select(Bid)).all() -def get_all_lots_json(): - lots = get_all_lots() - if not lots: +def get_all_bids_json(): + bids = get_all_bids() + if not bids: return [] - lots = [lot.get_json() for lot in lots] - return lots + bids = [bid.get_json() for bid in bids] + return bids -def edit_lot(id, labType=None, labSize=None, budget=None): - lot = get_lot(id) - if lot: - if labType: - lot.labType = labType - - if labSize: - lot.labSize = labSize - - if budget: - lot.budget = budget - - db.session.commit() - -def remove_lot(id): - lot = get_lot(id) - if lot: - db.session.delete(lot) +def remove_bid(id): + bid = get_bid(id) + if bid: + db.session.delete(bid) db.session.commit() \ No newline at end of file diff --git a/App/controllers/group.py b/App/controllers/group.py index 32215cd..16e8bc5 100644 --- a/App/controllers/group.py +++ b/App/controllers/group.py @@ -9,6 +9,11 @@ def create_group(groupName): db.session.commit() return group +def approve_group(id): + group = get_group(id) + group.status = "approved" + db.session.commit() + def get_group(id): return db.session.get(Group, id) diff --git a/App/controllers/rfp.py b/App/controllers/rfp.py index 4bbba87..952109d 100644 --- a/App/controllers/rfp.py +++ b/App/controllers/rfp.py @@ -1,12 +1,31 @@ from App.models import RFP from App.database import db +from .lot import get_lot def create_rfp(groupID, lotID): rfp = RFP(groupID, lotID) + lot = get_lot(lotID) + + rfp.deviceType = lot.deviceType + rfp.resolution = lot.resolution + rfp.os = lot.os + rfp.cpu = lot.cpu + rfp.ram = lot.ram + rfp.drive = lot.drive + rfp.gpu = lot.gpu + rfp.peripherals = lot.peripherals + rfp.features = lot.features + rfp.io = lot.io + db.session.add(rfp) db.session.commit() return rfp +def approve_rfp(groupID, lotID): + rfp = get_rfp(groupID, lotID) + rfp.status = "approved" + db.session.commit() + def get_rfp(groupID, lotID): return db.session.get(RFP, (groupID, lotID)) diff --git a/App/models/bid.py b/App/models/bid.py index 0082e26..624831c 100644 --- a/App/models/bid.py +++ b/App/models/bid.py @@ -6,7 +6,7 @@ class Bid(db.Model): lotID = db.Column(db.Integer, db.ForeignKey('lot.id'), nullable=False) sourceGroupID = db.Column(db.Integer, db.ForeignKey('group.id'), nullable=False) receipientGroupID = db.Column(db.Integer, db.ForeignKey('group.id'), nullable=False) - timestamp = db.Column(db.DateTime, nullable=False, default=datetime.utcnow()) + timestamp = db.Column(db.DateTime, nullable=False, default=datetime.utcnow) bidDocumentLink = db.Column(db.String(1000), nullable=False) def __init__(self, lotID, sourceGroupID, receipientGroupID, bidDocumentLink): diff --git a/App/tests/integration_test.py b/App/tests/integration_test.py index 98de246..af658aa 100644 --- a/App/tests/integration_test.py +++ b/App/tests/integration_test.py @@ -43,7 +43,6 @@ class Workflow1IntegrationTests(unittest.TestCase): def test_creating_lots(self): db.drop_all() create_db() - create_admin("bob", "bobpass") create_lot("GIS Lab", 20, 160000.00) create_lot("Government Office Lab", 12, 110000.00) lots_json = get_all_lots_json() @@ -75,10 +74,10 @@ def test_edit_lots(self): @pytest.mark.run(order=6) def test_remove_lot(self): lot = get_lot(1) - assert not lot == None + assert lot remove_lot(1) lot = get_lot(1) - assert lot == None + assert not lot class Workflow2IntegrationTests(unittest.TestCase): @pytest.mark.run(order=7) @@ -103,7 +102,7 @@ def test_create_groupRequest(self): members = [1,2,3,4] group = create_group(groupName) - group = get_group(1) + self.assertDictEqual({ 'id': 1, 'groupName': "G1 TechNova Solution", @@ -158,13 +157,11 @@ def test_approving_groupReuests(self): groupID = 1 Lot1ID = 1 Lot2ID = 2 - group = get_group(groupID) - add_lotGroup(Lot1ID, group.id) - add_lotGroup(Lot2ID, group.id) - - group.status = "approved" - db.session.commit() + add_lotGroup(Lot1ID, groupID) + add_lotGroup(Lot2ID, groupID) + approve_group(groupID) + self.assertListEqual([ { 'lotID': 1, @@ -218,6 +215,35 @@ def test_remove_group(self): removed = remove_group(groupID) assert removed + groupName = "TechNova Solution" + members = [1,2,3,4] + Lot1ID = 1 + Lot2ID = 2 + + group = create_group(groupName) + + for member in members: + add_studentGroup(member, group.id) + + add_lotGroup(Lot1ID, group.id) + add_lotGroup(Lot2ID, group.id) + + approve_group(group.id) + + groupName = "ANK Productions" + members = [5,6,7,8] + Lot1ID = 3 + Lot2ID = 4 + + group = create_group(groupName) + + for member in members: + add_studentGroup(member, group.id) + + add_lotGroup(Lot1ID, group.id) + add_lotGroup(Lot2ID, group.id) + + approve_group(group.id) class Workflow5IntegrationTests(unittest.TestCase): @pytest.mark.run(order=12) @@ -276,22 +302,7 @@ def test_submit_rfp_details(self): lotID = 1 groupID = 1 - rfp = create_rfp(lotID, groupID) - - lot = get_lot(lotID) - - rfp.deviceType = lot.deviceType - rfp.resolution = lot.resolution - rfp.os = lot.os - rfp.cpu = lot.cpu - rfp.ram = lot.ram - rfp.drive = lot.drive - rfp.gpu = lot.gpu - rfp.peripherals = lot.peripherals - rfp.features = lot.features - rfp.io = lot.io - - db.session.commit() + rfp = create_rfp(groupID, lotID) rfp = get_rfp(groupID, lotID) assert rfp.deviceType == "Workstation/Laptop/Tablet" @@ -321,21 +332,6 @@ def test_submit_duplicate_rfp_details(self): rfp = create_rfp(groupID, lotID) assert rfp - lot = get_lot(lotID) - - rfp.deviceType = lot.deviceType - rfp.resolution = lot.resolution - rfp.os = lot.os - rfp.cpu = lot.cpu - rfp.ram = lot.ram - rfp.drive = lot.drive - rfp.gpu = lot.gpu - rfp.peripherals = lot.peripherals - rfp.features = lot.features - rfp.io = lot.io - - db.session.commit() - rfp = get_rfp(groupID, lotID) assert rfp.deviceType == "" assert rfp.resolution == "" @@ -355,9 +351,7 @@ def test_approve_rfp_Request(self): lotID = 1 groupID = 1 - rfp = get_rfp(groupID, lotID) - rfp.status = "approved" - db.session.commit() + approve_rfp(groupID, lotID) rfp = get_rfp(groupID, lotID) assert rfp.status == "approved" @@ -377,4 +371,28 @@ def test_remove_rfp(self): lotID = 1 removed = remove_rfp(groupID, lotID) - assert removed \ No newline at end of file + assert removed + + rfp = create_rfp(groupID, lotID) + approve_rfp(groupID, lotID) + + groupID = 2 + lotID = 3 + rfp = create_rfp(groupID, lotID) + approve_rfp(groupID, lotID) + +class Workflow8IntegrationTests(unittest.TestCase): + @pytest.mark.run(order=18) + def test_place_bid(self): + sourceGroupID = 1 + receipientGroupID = 2 + lotID = 3 + bidDocumentLink = "www.exampleBid.com" + + bid = create_bid(lotID, sourceGroupID, receipientGroupID, bidDocumentLink) + + assert bid + assert bid.sourceGroupID == 1 + assert bidDocumentLink == "www.exampleBid.com" + assert receipientGroupID == 2 + assert lotID == 3 \ No newline at end of file From 40f605f56aeb57e0786874618a2702eea3dd02ba Mon Sep 17 00:00:00 2001 From: Andrews3002 Date: Sat, 28 Mar 2026 13:26:46 -0400 Subject: [PATCH 26/37] workflow9 complete --- App/controllers/__init__.py | 3 +- App/controllers/bid.py | 4 ++- App/controllers/evaluation.py | 59 +++++++++++++++++++++++++++++++++++ App/models/evaluation.py | 25 ++++++++++++--- App/tests/integration_test.py | 42 ++++++++++++++++++++++++- 5 files changed, 126 insertions(+), 7 deletions(-) create mode 100644 App/controllers/evaluation.py diff --git a/App/controllers/__init__.py b/App/controllers/__init__.py index 5a6d57b..5060db1 100644 --- a/App/controllers/__init__.py +++ b/App/controllers/__init__.py @@ -8,4 +8,5 @@ from .studentGroup import * from .lotGroup import * from .RFP import * -from .bid import * \ No newline at end of file +from .bid import * +from .evaluation import * \ No newline at end of file diff --git a/App/controllers/bid.py b/App/controllers/bid.py index fbcf5f3..670b662 100644 --- a/App/controllers/bid.py +++ b/App/controllers/bid.py @@ -24,4 +24,6 @@ def remove_bid(id): bid = get_bid(id) if bid: db.session.delete(bid) - db.session.commit() \ No newline at end of file + db.session.commit() + return True + return False \ No newline at end of file diff --git a/App/controllers/evaluation.py b/App/controllers/evaluation.py new file mode 100644 index 0000000..7a2473b --- /dev/null +++ b/App/controllers/evaluation.py @@ -0,0 +1,59 @@ +from App.models import Evaluation +from App.database import db + +def create_evaluation(sourceGroupID, receipientGroupID, bidID, lotID, specsMet, presentation, professionalism, budget): + neweval = Evaluation(sourceGroupID, receipientGroupID, bidID, lotID, specsMet, presentation, professionalism, budget) + db.session.add(neweval) + db.session.commit() + return neweval + +def edit_evaluation(id, specsMet, presentation, professionalism, budget, deviceType=None, resolution=None, os=None, cpu=None, ram=None, drive=None, gpu=None, peripherals=None, features=None, io=None): + eva = get_evaluation(id) + if eva: + eva.overallScore = round((((specsMet + presentation + professionalism + budget)/25) * 10), 1) + + if deviceType: + eva.deviceType = deviceType + if resolution: + eva.resolution = resolution + if os: + eva.os = os + if cpu: + eva.cpu = cpu + if ram: + eva.ram = ram + if drive: + eva.drive = drive + if gpu: + eva.gpu = gpu + if peripherals: + eva.peripherals = peripherals + if features: + eva.features = features + if io: + eva.io = io + + db.session.commit() + return True + return False + +def get_evaluation(id): + return db.session.get(Evaluation, id) + +def get_all_evaluations(): + return db.session.scalars(db.select(Evaluation)).all() + +def get_all_evaluations_json(): + evals = get_all_evaluations() + if not evals: + return [] + evals = [eva.get_json() for eva in evals] + return evals + +def remove_evaluation(id): + eva = get_bid(id) + if eva: + db.session.delete(eva) + db.session.commit() + return True + return False \ No newline at end of file diff --git a/App/models/evaluation.py b/App/models/evaluation.py index ccd22a9..501ab69 100644 --- a/App/models/evaluation.py +++ b/App/models/evaluation.py @@ -4,17 +4,34 @@ class Evaluation(db.Model): id = db.Column(db.Integer, primary_key=True) sourceGroupID = db.Column(db.Integer, db.ForeignKey('group.id'), nullable=False) receipientGroupID = db.Column(db.Integer, db.ForeignKey('group.id'), nullable=False) - evaluationDetails = db.Column(db.JSON) + bidID = db.Column(db.Integer, db.ForeignKey('bid.id'), nullable=False) + lotID = db.Column(db.Integer, db.ForeignKey('lot.id'), nullable=False) + status = db.Column(db.String(30), default="draft") + overallScore = db.Column(db.Float, default=0.0) + deviceType = db.Column(db.String(1000), default="") + resolution = db.Column(db.String(1000), default="") + os = db.Column(db.String(1000), default="") + cpu = db.Column(db.String(1000), default="") + ram = db.Column(db.String(1000), default="") + drive = db.Column(db.String(1000), default="") + gpu = db.Column(db.String(1000), default="") + peripherals = db.Column(db.String(1000), default="") + features = db.Column(db.String(1000), default="") + io = db.Column(db.String(1000), default="") - def __init__(self, sourceGroupID, receipientGroupID, evaluationDetails): + def __init__(self, sourceGroupID, receipientGroupID, bidID, lotID, specsMet, presentation, professionalism, budget): + self.bidID = bidID + self.lotID = lotID self.sourceGroupID = sourceGroupID self.receipientGroupID = receipientGroupID - self.evaluationDetails = evaluationDetails + self.overallScore = round((((specsMet + presentation + professionalism + budget)/25) * 10), 1) def get_json(self): return { 'id': self.id, 'sourceGroupID': self.sourceGroupID, 'receipientGroupID': self.receipientGroupID, - 'evaluationDetails': self.evaluationDetails + 'bidID': self.bidID, + 'lotID': self.lotID, + 'overallScore': self.overallScore } \ No newline at end of file diff --git a/App/tests/integration_test.py b/App/tests/integration_test.py index af658aa..7c6e2fe 100644 --- a/App/tests/integration_test.py +++ b/App/tests/integration_test.py @@ -395,4 +395,44 @@ def test_place_bid(self): assert bid.sourceGroupID == 1 assert bidDocumentLink == "www.exampleBid.com" assert receipientGroupID == 2 - assert lotID == 3 \ No newline at end of file + assert lotID == 3 + +class Workflow9IntegrationTests(unittest.TestCase): + @pytest.mark.run(order=19) + def test_remove_bid(self): + bidID = 1 + + removed = remove_bid(bidID) + assert removed + + sourceGroupID = 1 + receipientGroupID = 2 + lotID = 3 + bidDocumentLink = "www.exampleBid.com" + + bid = create_bid(lotID, sourceGroupID, receipientGroupID, bidDocumentLink) + + sourceGroupID = 2 + receipientGroupID = 1 + lotID = 1 + bidDocumentLink = "www.exampleBid.com" + + bid = create_bid(lotID, sourceGroupID, receipientGroupID, bidDocumentLink) + +# class Workflow10IntegrationTests(unittest.TestCase): +# @pytest.mark.run(order=20) +# def test_create_evaluation(self): +# sourceGroupID = 1 +# receipientGroupID = 2 +# bidID = 2 +# lotID = 1 +# specsMet = 5 +# presentation = 3 +# professionalism = 2 +# budget = 4 + +# evaluation = create_evaluation(sourceGroupID, receipientGroupID, bidID, lotID, specsMet, presentation, professionalism, budget) + +# assert evaluation +# assert evaluation.status == "draft" +# assert evaluation.overallScore == 5.6 \ No newline at end of file From f7da430fde64c8b0dff310ea52c2d8e171f3eb0a Mon Sep 17 00:00:00 2001 From: Andrews3002 Date: Sat, 28 Mar 2026 13:27:08 -0400 Subject: [PATCH 27/37] workflow10 complete --- App/tests/integration_test.py | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/App/tests/integration_test.py b/App/tests/integration_test.py index 7c6e2fe..c6c3a7f 100644 --- a/App/tests/integration_test.py +++ b/App/tests/integration_test.py @@ -419,20 +419,20 @@ def test_remove_bid(self): bid = create_bid(lotID, sourceGroupID, receipientGroupID, bidDocumentLink) -# class Workflow10IntegrationTests(unittest.TestCase): -# @pytest.mark.run(order=20) -# def test_create_evaluation(self): -# sourceGroupID = 1 -# receipientGroupID = 2 -# bidID = 2 -# lotID = 1 -# specsMet = 5 -# presentation = 3 -# professionalism = 2 -# budget = 4 - -# evaluation = create_evaluation(sourceGroupID, receipientGroupID, bidID, lotID, specsMet, presentation, professionalism, budget) - -# assert evaluation -# assert evaluation.status == "draft" -# assert evaluation.overallScore == 5.6 \ No newline at end of file +class Workflow10IntegrationTests(unittest.TestCase): + @pytest.mark.run(order=20) + def test_create_evaluation(self): + sourceGroupID = 1 + receipientGroupID = 2 + bidID = 2 + lotID = 1 + specsMet = 5 + presentation = 3 + professionalism = 2 + budget = 4 + + evaluation = create_evaluation(sourceGroupID, receipientGroupID, bidID, lotID, specsMet, presentation, professionalism, budget) + + assert evaluation + assert evaluation.status == "draft" + assert evaluation.overallScore == 5.6 \ No newline at end of file From 9e5200185a3ee19f27113867bb317e48bd18917a Mon Sep 17 00:00:00 2001 From: Andrews3002 Date: Sat, 28 Mar 2026 13:50:00 -0400 Subject: [PATCH 28/37] workflow11 complete --- App/controllers/evaluation.py | 5 +++++ App/tests/integration_test.py | 33 ++++++++++++++++++++++++++++++++- 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/App/controllers/evaluation.py b/App/controllers/evaluation.py index 7a2473b..0dc9042 100644 --- a/App/controllers/evaluation.py +++ b/App/controllers/evaluation.py @@ -37,6 +37,11 @@ def edit_evaluation(id, specsMet, presentation, professionalism, budget, deviceT return True return False +def select_evaluation(id): + evaluation = get_evaluation(id) + evaluation.status = "selected" + db.session.commit() + def get_evaluation(id): return db.session.get(Evaluation, id) diff --git a/App/tests/integration_test.py b/App/tests/integration_test.py index c6c3a7f..f1c52a9 100644 --- a/App/tests/integration_test.py +++ b/App/tests/integration_test.py @@ -435,4 +435,35 @@ def test_create_evaluation(self): assert evaluation assert evaluation.status == "draft" - assert evaluation.overallScore == 5.6 \ No newline at end of file + assert evaluation.overallScore == 5.6 + +class Workflow11IntegrationTests(unittest.TestCase): + @pytest.mark.run(order=21) + def test_edit_evaluation(self): + evaluationID = 1 + specsMet = 9 + presentation = 3 + professionalism = 2 + budget = 4 + deviceType = "device type comment" + resolution = "resolution comment" + ram = "ram comment" + + edited = edit_evaluation(evaluationID, specsMet, presentation, professionalism, budget, deviceType=deviceType, resolution=resolution, ram=ram) + assert edited + + evaluation = get_evaluation(evaluationID) + assert evaluation.overallScore == 7.2 + assert evaluation.deviceType == "device type comment" + assert evaluation.resolution == "resolution comment" + assert evaluation.ram == "ram comment" + + @pytest.mark.run(order=22) + def test_select_evaluation(self): + evaluationID = 1 + + select_evaluation(evaluationID) + + evaluation = get_evaluation(evaluationID) + assert evaluation + assert evaluation.status == "selected" \ No newline at end of file From e389edf8483864fd63cf31f12aaa7eea34bcfd47 Mon Sep 17 00:00:00 2001 From: Andrews3002 Date: Sat, 28 Mar 2026 13:54:06 -0400 Subject: [PATCH 29/37] workflow12 complete --- App/controllers/evaluation.py | 2 +- App/tests/integration_test.py | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/App/controllers/evaluation.py b/App/controllers/evaluation.py index 0dc9042..3726519 100644 --- a/App/controllers/evaluation.py +++ b/App/controllers/evaluation.py @@ -56,7 +56,7 @@ def get_all_evaluations_json(): return evals def remove_evaluation(id): - eva = get_bid(id) + eva = get_evaluation(id) if eva: db.session.delete(eva) db.session.commit() diff --git a/App/tests/integration_test.py b/App/tests/integration_test.py index f1c52a9..b310102 100644 --- a/App/tests/integration_test.py +++ b/App/tests/integration_test.py @@ -466,4 +466,12 @@ def test_select_evaluation(self): evaluation = get_evaluation(evaluationID) assert evaluation - assert evaluation.status == "selected" \ No newline at end of file + assert evaluation.status == "selected" + +class Workflow12IntegrationTests(unittest.TestCase): + @pytest.mark.run(order=23) + def test_remove_evaluation(self): + evaluationID = 1 + + removed = remove_evaluation(evaluationID) + assert removed \ No newline at end of file From 4d4cb687e031d5ed5a6e2ab863026ee7fcf22783 Mon Sep 17 00:00:00 2001 From: Andrews3002 Date: Sat, 28 Mar 2026 14:21:44 -0400 Subject: [PATCH 30/37] controllers, integration and unit tests are all complete --- App/tests/unit_test.py | 444 ++++++++++++++++++++--------------------- 1 file changed, 221 insertions(+), 223 deletions(-) diff --git a/App/tests/unit_test.py b/App/tests/unit_test.py index 99a6a29..b1454e2 100644 --- a/App/tests/unit_test.py +++ b/App/tests/unit_test.py @@ -1,224 +1,222 @@ -# import pytest -# import unittest -# from datetime import datetime -# from werkzeug.security import generate_password_hash +import pytest +import unittest +from datetime import datetime +from werkzeug.security import generate_password_hash -# from App.main import create_app -# from App.database import db, create_db -# from App.models import User, Admin, Student, Group, StudentGroup, Lot, LotGroup, Bid, Evaluation, RFP - - -# class AdminUnitTests(unittest.TestCase): - -# def test_new_admin(self): -# admin = Admin("alice", "alicepass") -# assert admin.username == "alice" - -# def test_admin_get_json(self): -# admin = Admin("alice", "alicepass") -# admin_json = admin.get_json() -# assert admin_json["username"] == "alice" -# assert admin_json["role"] == "admin" - -# def test_admin_hashed_password(self): -# admin = Admin("alice", "alicepass") -# assert admin.password != "alicepass" - -# def test_admin_check_password(self): -# admin = Admin("alice", "alicepass") -# assert admin.check_password("alicepass") - -# def test_admin_is_admin(self): -# admin = Admin("alice", "alicepass") -# assert admin.is_admin() - -# def test_admin_is_not_student(self): -# admin = Admin("alice", "alicepass") -# assert not admin.is_student() - - -# class StudentUnitTests(unittest.TestCase): - -# def test_new_student(self): -# student = Student("bob", "bobpass") -# assert student.username == "bob" - -# def test_student_get_json(self): -# student = Student("bob", "bobpass") -# student_json = student.get_json() -# assert student_json["username"] == "bob" -# assert student_json["role"] == "student" - -# def test_student_hashed_password(self): -# student = Student("bob", "bobpass") -# assert student.password != "bobpass" - -# def test_student_check_password(self): -# student = Student("bob", "bobpass") -# assert student.check_password("bobpass") - -# def test_student_is_student(self): -# student = Student("bob", "bobpass") -# assert student.is_student() - -# def test_student_is_not_admin(self): -# student = Student("bob", "bobpass") -# assert not student.is_admin() - - -# class GroupUnitTests(unittest.TestCase): - -# def test_new_group(self): -# group = Group("Algorithms") -# assert group.groupName == "Algorithms" - -# def test_group_get_json(self): -# group = Group("Algorithms") -# group_json = group.get_json() -# assert group_json["groupName"] == "Algorithms" - - -# class GroupRequestUnitTests(unittest.TestCase): - -# def test_new_group_request(self): -# group_request = GroupRequest("Algorithms", [1, 2, 3]) -# assert group_request.groupName == "Algorithms" - -# def test_group_request_members(self): -# group_request = GroupRequest("Algorithms", [1, 2, 3]) -# assert group_request.members == [1, 2, 3] - -# def test_group_request_get_json(self): -# group_request = GroupRequest("Algorithms", [1, 2, 3]) -# group_json = group_request.get_json() -# assert group_json["groupName"] == "Algorithms" -# assert group_json["members"] == [1, 2, 3] - - -# class StudentGroupUnitTests(unittest.TestCase): - -# def test_new_student_group(self): -# student_group = StudentGroup(1, 2) -# assert student_group.studentID == 1 -# assert student_group.groupID == 2 - -# def test_student_group_get_json(self): -# student_group = StudentGroup(1, 2) -# sg_json = student_group.get_json() -# self.assertDictEqual(sg_json, {"studentID": 1, "groupID": 2}) - - -# class LotUnitTests(unittest.TestCase): - -# def test_new_lot(self): -# lot = Lot("Biology", 30, 5000.00) -# assert lot.labType == "Biology" - -# def test_lot_lab_size(self): -# lot = Lot("Biology", 30, 5000.00) -# assert lot.labSize == 30 - -# def test_lot_budget(self): -# lot = Lot("Biology", 30, 5000.00) -# assert lot.budget == 5000.00 - -# def test_lot_get_json(self): -# lot = Lot("Biology", 30, 5000.00) -# lot_json = lot.get_json() -# self.assertDictEqual(lot_json, { -# "id": None, -# "labType": "Biology", -# "labSize": 30, -# "budget": 5000.00 -# }) - -# def test_lot_budget_comparison(self): -# lot = Lot("Biology", 30, 5000.00) -# assert 4999.99 < lot.budget -# assert 5000.01 > lot.budget - - -# class LotGroupUnitTests(unittest.TestCase): - -# def test_new_lot_group(self): -# lot_group = LotGroup(1, 2) -# assert lot_group.lotID == 1 -# assert lot_group.groupID == 2 - -# def test_lot_group_get_json(self): -# lot_group = LotGroup(1, 2) -# lg_json = lot_group.get_json() -# self.assertDictEqual(lg_json, {"lotID": 1, "groupID": 2}) - - -# class RFPRequestUnitTests(unittest.TestCase): - -# def test_new_rfp_request(self): -# rfp = RFPRequest(1, 2, {"detail": "some spec"}) -# assert rfp.groupID == 1 -# assert rfp.lotID == 2 - -# def test_rfp_request_specs(self): -# specs = {"detail": "some spec", "budget": 1000} -# rfp = RFPRequest(1, 2, specs) -# assert rfp.specs == specs - -# def test_rfp_request_get_json(self): -# specs = {"detail": "some spec"} -# rfp = RFPRequest(1, 2, specs) -# rfp_json = rfp.get_json() -# assert rfp_json["groupID"] == 1 -# assert rfp_json["lotID"] == 2 -# assert rfp_json["specs"] == specs - - -# class BidUnitTests(unittest.TestCase): - -# def test_new_bid(self): -# bid = Bid(1, 2, 3, "http://example.com/doc") -# assert bid.lotID == 1 -# assert bid.sourceGroupID == 2 -# assert bid.receipientGroupID == 3 - -# def test_bid_document_link(self): -# bid = Bid(1, 2, 3, "http://example.com/doc") -# assert bid.bidDocumentLink == "http://example.com/doc" - -# def test_bid_timestamp_auto_set(self): -# bid = Bid(1, 2, 3, "http://example.com/doc") -# assert isinstance(bid.timestamp, datetime) - -# def test_bid_timestamp_is_recent(self): -# bid = Bid(1, 2, 3, "http://example.com/doc") -# delta = datetime.utcnow() - bid.timestamp -# assert delta.seconds < 5 - -# def test_bid_get_json(self): -# bid = Bid(1, 2, 3, "http://example.com/doc") -# bid_json = bid.get_json() -# assert bid_json["lotID"] == 1 -# assert bid_json["sourceGroupID"] == 2 -# assert bid_json["receipientGroupID"] == 3 -# assert bid_json["bidDocumentLink"] == "http://example.com/doc" -# assert "timestamp" in bid_json - - -# class EvaluationUnitTests(unittest.TestCase): - -# def test_new_evaluation(self): -# evaluation = Evaluation(1, 2, {"score": 85}) -# assert evaluation.sourceGroupID == 1 -# assert evaluation.receipientGroupID == 2 - -# def test_evaluation_details(self): -# details = {"score": 85, "comments": "Good work"} -# evaluation = Evaluation(1, 2, details) -# assert evaluation.evaluationDetails == details - -# def test_evaluation_get_json(self): -# details = {"score": 85} -# evaluation = Evaluation(1, 2, details) -# eval_json = evaluation.get_json() -# assert eval_json["sourceGroupID"] == 1 -# assert eval_json["receipientGroupID"] == 2 -# assert eval_json["evaluationDetails"] == details \ No newline at end of file +from App.main import create_app +from App.database import db, create_db +from App.models import User, Admin, Student, Group, StudentGroup, Lot, LotGroup, Bid, Evaluation, RFP + + +class AdminUnitTests(unittest.TestCase): + def test_new_admin(self): + admin = Admin("alice", "alicepass") + assert admin.username == "alice" + + def test_admin_get_json(self): + admin = Admin("alice", "alicepass") + admin_json = admin.get_json() + assert admin_json["username"] == "alice" + assert admin_json["role"] == "admin" + + def test_admin_hashed_password(self): + admin = Admin("alice", "alicepass") + assert admin.password != "alicepass" + + def test_admin_check_password(self): + admin = Admin("alice", "alicepass") + assert admin.check_password("alicepass") + + def test_admin_is_admin(self): + admin = Admin("alice", "alicepass") + assert admin.is_admin() + + def test_admin_is_not_student(self): + admin = Admin("alice", "alicepass") + assert not admin.is_student() + + +class StudentUnitTests(unittest.TestCase): + def test_new_student(self): + student = Student("bob", "bobpass") + assert student.username == "bob" + + def test_student_get_json(self): + student = Student("bob", "bobpass") + student_json = student.get_json() + assert student_json["username"] == "bob" + assert student_json["role"] == "student" + + def test_student_hashed_password(self): + student = Student("bob", "bobpass") + assert student.password != "bobpass" + + def test_student_check_password(self): + student = Student("bob", "bobpass") + assert student.check_password("bobpass") + + def test_student_is_student(self): + student = Student("bob", "bobpass") + assert student.is_student() + + def test_student_is_not_admin(self): + student = Student("bob", "bobpass") + assert not student.is_admin() + + +class GroupUnitTests(unittest.TestCase): + def test_new_group(self): + group = Group("Algorithms") + assert group.groupName == "Algorithms" + + def test_group_get_json(self): + group = Group("Algorithms") + group_json = group.get_json() + assert group_json["groupName"] == "Algorithms" + + +class StudentGroupUnitTests(unittest.TestCase): + def test_new_student_group(self): + student_group = StudentGroup(1, 2) + assert student_group.studentID == 1 + assert student_group.groupID == 2 + + def test_student_group_get_json(self): + student_group = StudentGroup(1, 2) + sg_json = student_group.get_json() + self.assertDictEqual(sg_json, {"studentID": 1, "groupID": 2}) + + +class LotUnitTests(unittest.TestCase): + def test_new_lot(self): + lot = Lot("Biology", 30, 5000.00) + assert lot.labType == "Biology" + + def test_lot_lab_size(self): + lot = Lot("Biology", 30, 5000.00) + assert lot.labSize == 30 + + def test_lot_budget(self): + lot = Lot("Biology", 30, 5000.00) + assert lot.budget == 5000.00 + + def test_lot_get_json(self): + lot = Lot("Biology", 30, 5000.00) + lot_json = lot.get_json() + self.assertDictEqual(lot_json, { + "id": None, + "name": None, + "labType": "Biology", + "labSize": 30, + "budget": 5000.00 + }) + + def test_lot_budget_comparison(self): + lot = Lot("Biology", 30, 5000.00) + assert 4999.99 < lot.budget + assert 5000.01 > lot.budget + + +class LotGroupUnitTests(unittest.TestCase): + def test_new_lot_group(self): + lot_group = LotGroup(1, 2) + assert lot_group.lotID == 1 + assert lot_group.groupID == 2 + + def test_lot_group_get_json(self): + lot_group = LotGroup(1, 2) + lg_json = lot_group.get_json() + self.assertDictEqual(lg_json, {"lotID": 1, "groupID": 2}) + +class RFPUnitTests(unittest.TestCase): + def test_new_RFP(self): + rfp = RFP(1, 10) + assert rfp + assert rfp.groupID == 1 + assert rfp.lotID == 10 + + def test_RFP_get_json(self): + rfp = RFP(1, 10) + assert rfp + + self.assertDictEqual({ + 'groupID': 1, + 'lotID': 10, + 'status': None, + 'Type': None, + 'Screen Size & Resolution': None, + 'Operating System(s)': None, + 'CPU': None, + 'Memory (RAM)': None, + 'Hard Drive': None, + 'Graphics': None, + 'External Peripherals': None, + 'Features': None, + 'I/O': None + }, rfp.get_json()) + +class BidUnitTests(unittest.TestCase): + def test_new_bid(self): + bid = Bid(1, 2, 3, "http://example.com/doc") + assert bid.lotID == 1 + assert bid.sourceGroupID == 2 + assert bid.receipientGroupID == 3 + + def test_bid_document_link(self): + bid = Bid(1, 2, 3, "http://example.com/doc") + assert bid.bidDocumentLink == "http://example.com/doc" + + def test_bid_timestamp_auto_set(self): + bid = Bid(1, 2, 3, "http://example.com/doc") + assert isinstance(bid.timestamp, datetime) + + def test_bid_timestamp_is_recent(self): + bid = Bid(1, 2, 3, "http://example.com/doc") + delta = datetime.utcnow() - bid.timestamp + assert delta.seconds < 5 + + def test_bid_get_json(self): + bid = Bid(1, 2, 3, "http://example.com/doc") + bid_json = bid.get_json() + assert bid_json["lotID"] == 1 + assert bid_json["sourceGroupID"] == 2 + assert bid_json["receipientGroupID"] == 3 + assert bid_json["bidDocumentLink"] == "http://example.com/doc" + assert "timestamp" in bid_json + + +class EvaluationUnitTests(unittest.TestCase): + def test_new_evaluation(self): + sourceGroupID = 1 + receipientGroupID = 2 + bidID = 2 + lotID = 1 + specsMet = 5 + presentation = 3 + professionalism = 2 + budget = 4 + + evaluation = Evaluation(sourceGroupID, receipientGroupID, bidID, lotID, specsMet, presentation, professionalism, budget) + assert evaluation + assert evaluation.overallScore == 5.6 + + def test_evaluation_get_json(self): + sourceGroupID = 1 + receipientGroupID = 2 + bidID = 2 + lotID = 1 + specsMet = 5 + presentation = 3 + professionalism = 2 + budget = 4 + + evaluation = Evaluation(sourceGroupID, receipientGroupID, bidID, lotID, specsMet, presentation, professionalism, budget) + + self.assertDictEqual({ + 'id': None, + 'sourceGroupID': 1, + 'receipientGroupID': 2, + 'bidID': 2, + 'lotID': 1, + 'overallScore': 5.6 + }, evaluation.get_json()) \ No newline at end of file From 2b8440c0c170e659791fb7b98ffc892ec9141cb4 Mon Sep 17 00:00:00 2001 From: Andrews3002 Date: Thu, 2 Apr 2026 16:06:59 -0400 Subject: [PATCH 31/37] controllers finalization --- App/controllers/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/App/controllers/__init__.py b/App/controllers/__init__.py index 5060db1..e75ec60 100644 --- a/App/controllers/__init__.py +++ b/App/controllers/__init__.py @@ -7,6 +7,6 @@ from .group import * from .studentGroup import * from .lotGroup import * -from .RFP import * +from .rfp import * from .bid import * from .evaluation import * \ No newline at end of file From a059cbb1274508f7e440a22c312ad851d84e0356 Mon Sep 17 00:00:00 2001 From: Andrews3002 Date: Thu, 2 Apr 2026 18:35:06 -0400 Subject: [PATCH 32/37] ordering tests correctly --- App/tests/integration_test.py | 54 +++++++++++++++++------------------ App/tests/unit_test.py | 38 ++++++++++++++++++++++-- 2 files changed, 61 insertions(+), 31 deletions(-) diff --git a/App/tests/integration_test.py b/App/tests/integration_test.py index b310102..069fec1 100644 --- a/App/tests/integration_test.py +++ b/App/tests/integration_test.py @@ -15,13 +15,13 @@ def empty_db(): yield app.test_client() db.drop_all() -@pytest.mark.run(order=1) +@pytest.mark.run(order=33) def test_authenticate(): user = create_user("bob", "bobpass") assert login("bob", "bobpass") != None class UsersIntegrationTests(unittest.TestCase): - @pytest.mark.run(order=2) + @pytest.mark.run(order=34) def test_user_children_are_users(self): admin = Admin("jack", "jackpass") db.session.add(admin) @@ -32,14 +32,14 @@ def test_user_children_are_users(self): self.assertListEqual([{"id":1, "username":"bob"}, {"id":2, "username":"jack", "role":"admin"}, {"id":3, "username":"cooper", "role":"student"}], users_json) # Tests data changes in the database - @pytest.mark.run(order=3) + @pytest.mark.run(order=35) def test_update_user(self): update_user(1, "ronnie") user = get_user(1) assert user.username == "ronnie" class Workflow1IntegrationTests(unittest.TestCase): - @pytest.mark.run(order=4) + @pytest.mark.run(order=36) def test_creating_lots(self): db.drop_all() create_db() @@ -63,7 +63,7 @@ def test_creating_lots(self): } ], lots_json) - @pytest.mark.run(order=5) + @pytest.mark.run(order=37) def test_edit_lots(self): lot = get_lot(1) assert lot.budget == 160000.00 @@ -71,7 +71,7 @@ def test_edit_lots(self): lot = get_lot(1) assert lot.budget == 170000.00 - @pytest.mark.run(order=6) + @pytest.mark.run(order=38) def test_remove_lot(self): lot = get_lot(1) assert lot @@ -80,7 +80,7 @@ def test_remove_lot(self): assert not lot class Workflow2IntegrationTests(unittest.TestCase): - @pytest.mark.run(order=7) + @pytest.mark.run(order=39) def test_create_groupRequest(self): remove_lot(2) create_lot("GIS Lab", 20, 160000.00) @@ -131,7 +131,7 @@ def test_create_groupRequest(self): }, ], get_all_studentGroups_json()) - @pytest.mark.run(order=8) + @pytest.mark.run(order=40) def test_trying_to_create_group_request_with_a_duplicate_member(self): groupName = "ANK Productions" members = [1,2,3,4] @@ -152,7 +152,7 @@ def test_trying_to_create_group_request_with_a_duplicate_member(self): add_studentGroup(member, group.id) class Workflow3IntegrationTests(unittest.TestCase): - @pytest.mark.run(order=9) + @pytest.mark.run(order=41) def test_approving_groupReuests(self): groupID = 1 Lot1ID = 1 @@ -176,7 +176,7 @@ def test_approving_groupReuests(self): group = get_group(1) assert group.status == "approved" - @pytest.mark.run(order=10) + @pytest.mark.run(order=42) def test_rejecting_a_group_request(self): groupID = 2 @@ -196,7 +196,7 @@ def test_rejecting_a_group_request(self): assert removed class Workflow4IntegrationTests(unittest.TestCase): - @pytest.mark.run(order=11) + @pytest.mark.run(order=43) def test_remove_group(self): groupID = 1 @@ -246,7 +246,7 @@ def test_remove_group(self): approve_group(group.id) class Workflow5IntegrationTests(unittest.TestCase): - @pytest.mark.run(order=12) + @pytest.mark.run(order=44) def test_save_rfp_details(self): lotID = 1 deviceType = "Workstation/Laptop/Tablet" @@ -296,8 +296,7 @@ def test_save_rfp_details(self): assert lot.features == "Touch screen, WIFI version, bluetooth, Capture Card, Integrated Speakers, Integrated Webcam, Fingerprint reader, LTE" assert lot.io == "" - - @pytest.mark.run(order=13) + @pytest.mark.run(order=45) def test_submit_rfp_details(self): lotID = 1 groupID = 1 @@ -316,9 +315,8 @@ def test_submit_rfp_details(self): assert rfp.features == "" assert rfp.io == "" assert rfp.status == "requested" - - - @pytest.mark.run(order=14) + + @pytest.mark.run(order=46) def test_submit_duplicate_rfp_details(self): lotID = 1 groupID = 1 @@ -346,7 +344,7 @@ def test_submit_duplicate_rfp_details(self): assert rfp.status == "requested" class Workflow6IntegrationTests(unittest.TestCase): - @pytest.mark.run(order=15) + @pytest.mark.run(order=47) def test_approve_rfp_Request(self): lotID = 1 groupID = 1 @@ -356,7 +354,7 @@ def test_approve_rfp_Request(self): rfp = get_rfp(groupID, lotID) assert rfp.status == "approved" - @pytest.mark.run(order=16) + @pytest.mark.run(order=48) def test_reject_rfp_Request(self): groupID = 1 lotID = 2 @@ -365,7 +363,7 @@ def test_reject_rfp_Request(self): assert removed class Workflow7IntegrationTests(unittest.TestCase): - @pytest.mark.run(order=17) + @pytest.mark.run(order=49) def test_remove_rfp(self): groupID = 1 lotID = 1 @@ -382,7 +380,7 @@ def test_remove_rfp(self): approve_rfp(groupID, lotID) class Workflow8IntegrationTests(unittest.TestCase): - @pytest.mark.run(order=18) + @pytest.mark.run(order=50) def test_place_bid(self): sourceGroupID = 1 receipientGroupID = 2 @@ -398,7 +396,7 @@ def test_place_bid(self): assert lotID == 3 class Workflow9IntegrationTests(unittest.TestCase): - @pytest.mark.run(order=19) + @pytest.mark.run(order=51) def test_remove_bid(self): bidID = 1 @@ -418,9 +416,9 @@ def test_remove_bid(self): bidDocumentLink = "www.exampleBid.com" bid = create_bid(lotID, sourceGroupID, receipientGroupID, bidDocumentLink) - + class Workflow10IntegrationTests(unittest.TestCase): - @pytest.mark.run(order=20) + @pytest.mark.run(order=52) def test_create_evaluation(self): sourceGroupID = 1 receipientGroupID = 2 @@ -438,7 +436,7 @@ def test_create_evaluation(self): assert evaluation.overallScore == 5.6 class Workflow11IntegrationTests(unittest.TestCase): - @pytest.mark.run(order=21) + @pytest.mark.run(order=53) def test_edit_evaluation(self): evaluationID = 1 specsMet = 9 @@ -457,8 +455,8 @@ def test_edit_evaluation(self): assert evaluation.deviceType == "device type comment" assert evaluation.resolution == "resolution comment" assert evaluation.ram == "ram comment" - - @pytest.mark.run(order=22) + + @pytest.mark.run(order=54) def test_select_evaluation(self): evaluationID = 1 @@ -469,7 +467,7 @@ def test_select_evaluation(self): assert evaluation.status == "selected" class Workflow12IntegrationTests(unittest.TestCase): - @pytest.mark.run(order=23) + @pytest.mark.run(order=55) def test_remove_evaluation(self): evaluationID = 1 diff --git a/App/tests/unit_test.py b/App/tests/unit_test.py index b1454e2..4afd474 100644 --- a/App/tests/unit_test.py +++ b/App/tests/unit_test.py @@ -9,66 +9,80 @@ class AdminUnitTests(unittest.TestCase): + @pytest.mark.run(order=1) def test_new_admin(self): admin = Admin("alice", "alicepass") assert admin.username == "alice" + @pytest.mark.run(order=2) def test_admin_get_json(self): admin = Admin("alice", "alicepass") admin_json = admin.get_json() assert admin_json["username"] == "alice" assert admin_json["role"] == "admin" + @pytest.mark.run(order=3) def test_admin_hashed_password(self): admin = Admin("alice", "alicepass") assert admin.password != "alicepass" + @pytest.mark.run(order=4) def test_admin_check_password(self): admin = Admin("alice", "alicepass") assert admin.check_password("alicepass") + @pytest.mark.run(order=5) def test_admin_is_admin(self): admin = Admin("alice", "alicepass") assert admin.is_admin() + @pytest.mark.run(order=6) def test_admin_is_not_student(self): admin = Admin("alice", "alicepass") assert not admin.is_student() class StudentUnitTests(unittest.TestCase): + @pytest.mark.run(order=7) def test_new_student(self): student = Student("bob", "bobpass") assert student.username == "bob" + @pytest.mark.run(order=8) def test_student_get_json(self): student = Student("bob", "bobpass") student_json = student.get_json() assert student_json["username"] == "bob" assert student_json["role"] == "student" + @pytest.mark.run(order=9) def test_student_hashed_password(self): student = Student("bob", "bobpass") assert student.password != "bobpass" + @pytest.mark.run(order=10) def test_student_check_password(self): student = Student("bob", "bobpass") assert student.check_password("bobpass") + @pytest.mark.run(order=11) def test_student_is_student(self): student = Student("bob", "bobpass") assert student.is_student() + @pytest.mark.run(order=12) def test_student_is_not_admin(self): student = Student("bob", "bobpass") assert not student.is_admin() class GroupUnitTests(unittest.TestCase): + @pytest.mark.run(order=13) def test_new_group(self): group = Group("Algorithms") assert group.groupName == "Algorithms" + @pytest.mark.run(order=14) def test_group_get_json(self): group = Group("Algorithms") group_json = group.get_json() @@ -76,11 +90,13 @@ def test_group_get_json(self): class StudentGroupUnitTests(unittest.TestCase): + @pytest.mark.run(order=15) def test_new_student_group(self): student_group = StudentGroup(1, 2) assert student_group.studentID == 1 assert student_group.groupID == 2 + @pytest.mark.run(order=16) def test_student_group_get_json(self): student_group = StudentGroup(1, 2) sg_json = student_group.get_json() @@ -88,18 +104,22 @@ def test_student_group_get_json(self): class LotUnitTests(unittest.TestCase): + @pytest.mark.run(order=17) def test_new_lot(self): lot = Lot("Biology", 30, 5000.00) assert lot.labType == "Biology" + @pytest.mark.run(order=18) def test_lot_lab_size(self): lot = Lot("Biology", 30, 5000.00) assert lot.labSize == 30 + @pytest.mark.run(order=19) def test_lot_budget(self): lot = Lot("Biology", 30, 5000.00) assert lot.budget == 5000.00 + @pytest.mark.run(order=20) def test_lot_get_json(self): lot = Lot("Biology", 30, 5000.00) lot_json = lot.get_json() @@ -111,6 +131,7 @@ def test_lot_get_json(self): "budget": 5000.00 }) + @pytest.mark.run(order=21) def test_lot_budget_comparison(self): lot = Lot("Biology", 30, 5000.00) assert 4999.99 < lot.budget @@ -118,27 +139,31 @@ def test_lot_budget_comparison(self): class LotGroupUnitTests(unittest.TestCase): + @pytest.mark.run(order=22) def test_new_lot_group(self): lot_group = LotGroup(1, 2) assert lot_group.lotID == 1 assert lot_group.groupID == 2 + @pytest.mark.run(order=23) def test_lot_group_get_json(self): lot_group = LotGroup(1, 2) lg_json = lot_group.get_json() self.assertDictEqual(lg_json, {"lotID": 1, "groupID": 2}) + class RFPUnitTests(unittest.TestCase): + @pytest.mark.run(order=24) def test_new_RFP(self): rfp = RFP(1, 10) assert rfp assert rfp.groupID == 1 assert rfp.lotID == 10 - + + @pytest.mark.run(order=25) def test_RFP_get_json(self): rfp = RFP(1, 10) assert rfp - self.assertDictEqual({ 'groupID': 1, 'lotID': 10, @@ -155,26 +180,32 @@ def test_RFP_get_json(self): 'I/O': None }, rfp.get_json()) + class BidUnitTests(unittest.TestCase): + @pytest.mark.run(order=26) def test_new_bid(self): bid = Bid(1, 2, 3, "http://example.com/doc") assert bid.lotID == 1 assert bid.sourceGroupID == 2 assert bid.receipientGroupID == 3 + @pytest.mark.run(order=27) def test_bid_document_link(self): bid = Bid(1, 2, 3, "http://example.com/doc") assert bid.bidDocumentLink == "http://example.com/doc" + @pytest.mark.run(order=28) def test_bid_timestamp_auto_set(self): bid = Bid(1, 2, 3, "http://example.com/doc") assert isinstance(bid.timestamp, datetime) + @pytest.mark.run(order=29) def test_bid_timestamp_is_recent(self): bid = Bid(1, 2, 3, "http://example.com/doc") delta = datetime.utcnow() - bid.timestamp assert delta.seconds < 5 + @pytest.mark.run(order=30) def test_bid_get_json(self): bid = Bid(1, 2, 3, "http://example.com/doc") bid_json = bid.get_json() @@ -186,6 +217,7 @@ def test_bid_get_json(self): class EvaluationUnitTests(unittest.TestCase): + @pytest.mark.run(order=31) def test_new_evaluation(self): sourceGroupID = 1 receipientGroupID = 2 @@ -200,6 +232,7 @@ def test_new_evaluation(self): assert evaluation assert evaluation.overallScore == 5.6 + @pytest.mark.run(order=32) def test_evaluation_get_json(self): sourceGroupID = 1 receipientGroupID = 2 @@ -211,7 +244,6 @@ def test_evaluation_get_json(self): budget = 4 evaluation = Evaluation(sourceGroupID, receipientGroupID, bidID, lotID, specsMet, presentation, professionalism, budget) - self.assertDictEqual({ 'id': None, 'sourceGroupID': 1, From 2f55f6dc01110220e14114bdbc29fc26ff9a6c66 Mon Sep 17 00:00:00 2001 From: Andrews3002 Date: Thu, 2 Apr 2026 18:41:12 -0400 Subject: [PATCH 33/37] adding pytest ordering to the requirements --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 5bda9f8..dbe01a4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -13,4 +13,4 @@ pytest==7.0.1 psycopg2-binary==2.9.9 python-dotenv==1.0.1 rich==13.4.2 - +pytest-ordering \ No newline at end of file From d65d51a262b508fecd5fd6a3b1e4ac440b621ba7 Mon Sep 17 00:00:00 2001 From: Andrews3002 Date: Thu, 2 Apr 2026 18:45:49 -0400 Subject: [PATCH 34/37] adding pytest ordering to the requirements --- requirements.txt | Bin 294 -> 1676 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/requirements.txt b/requirements.txt index dbe01a47f2a81d465681c01f8eefeb310a133be9..1f7c9089b27801680ba3ae92bfc9fd5bc59d3600 100644 GIT binary patch literal 1676 zcmZ`(O;6iU5ZrU6{uCo@J_?5(5P|~&sgz0_E8~C(v5jRrK>6`4GdtecO;uShj=Zz` zW@qQUKfiOU?A~g-v!xaG6;EnASYPm)*=PG?xefLV1mmyP;XNRu-(dG0AIJd+#WFiU zgwb8EbBCRl*4PT!-6s2Z6EExm&(b5Ae~rw-GYe#r-w|TuxaU<1aI3I7@T{?j*hQ54 z9*&4L7^#N=HOPS-hyyutH}$$eg$|en;=~mAjf&h?ot$IG95uy<*?YdI!4ymE1a+ue z<2A_n5G!?7bKI%(mujp;{^>t^C3a!A_QMi8vo~kgIM0PwXTMt8EUv(ybbZ(nyWt*W zv)xT%-+@?L>x$;H>O^ZM+tqLE+Ah&)1+5;DUE8m}_E5JaA}?4}o(wXt#vVg?GQ4*L z{U{W9a@T!VtOTQ~)sA)E86}?bvAsY8mIqs$jsbBiHM{hZ>y#3svk=*GlDx(} zbVJESyvd{%y*rO4?j)Xd-fE#5v6`^3k3eyP3%pskfs9U5WMGKvb2f#I7AT9gXqBrc&^EkhSsE{tysU_jkfG%XPBLt-Pc81DJ4LH zWcvj8^?cmay2R(8l!P4ekv};biw^%}Hj)?Yn>rK*jZ!%XnD}joZBk~CPt@Ull30*4rCEHT?+6MC0>PT0 x! Date: Thu, 2 Apr 2026 18:51:45 -0400 Subject: [PATCH 35/37] adding pytest ordering to the requirements --- App/tests/__init__.py | 4 ++-- App/tests/{unit_test.py => tests_1_unit_test.py} | 0 .../{integration_test.py => tests_2_integration_test.py} | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename App/tests/{unit_test.py => tests_1_unit_test.py} (100%) rename App/tests/{integration_test.py => tests_2_integration_test.py} (100%) diff --git a/App/tests/__init__.py b/App/tests/__init__.py index c2e5876..8e14424 100644 --- a/App/tests/__init__.py +++ b/App/tests/__init__.py @@ -1,2 +1,2 @@ -from .unit_test import * -from .integration_test import * \ No newline at end of file +from .tests_1_unit_test import * +from .tests_2_integration_test import * \ No newline at end of file diff --git a/App/tests/unit_test.py b/App/tests/tests_1_unit_test.py similarity index 100% rename from App/tests/unit_test.py rename to App/tests/tests_1_unit_test.py diff --git a/App/tests/integration_test.py b/App/tests/tests_2_integration_test.py similarity index 100% rename from App/tests/integration_test.py rename to App/tests/tests_2_integration_test.py From 81de658815e9e6a314b2f381479cf2ba7d273e79 Mon Sep 17 00:00:00 2001 From: Andrews3002 Date: Thu, 2 Apr 2026 18:58:04 -0400 Subject: [PATCH 36/37] adding pytest ordering to the requirements --- requirements.txt | Bin 1676 -> 1660 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/requirements.txt b/requirements.txt index 1f7c9089b27801680ba3ae92bfc9fd5bc59d3600..abe5aad0004ec29defc95c421d45e08e02b57c7a 100644 GIT binary patch delta 24 fcmeC-{lmlm|6d|Q4nrzKE<+MSCPVT@`CK*tZPEw6 delta 40 rcmeyv)59zO|6d|Q4nrzKE<+MSCPOlVEf5+q=mD`gkTlxJpUVaS?0*Sg From e1e64311b0fce9db2917ab25551162d6211f9903 Mon Sep 17 00:00:00 2001 From: Andrews3002 Date: Thu, 2 Apr 2026 19:01:07 -0400 Subject: [PATCH 37/37] adding pytest ordering to the requirements --- requirements.txt | Bin 1660 -> 620 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/requirements.txt b/requirements.txt index abe5aad0004ec29defc95c421d45e08e02b57c7a..fb497bac0684b1abae36cb1cacebf62fba6c2f7b 100644 GIT binary patch delta 80 zcmeyv^M-}#|G&vp&B=3^R3=9-DNR1YqA*#C#b~k+tIOm^EOGzI?rrM5p&gh;_WxQ^hb&w5lC)BZOmhyy~Mz z8NE^FX|yrZ?ryjHOc=+TxYIMuNS$Bz5q37(NzFG|Zy3j!wGp?uRwtedEf7b2-P0bi z6(jesQ4ToJfjPjDYIS1A%FqcjRvb*Dza=Ae&GcLqN6KkF>^{zgTKm`_-YE~dwV4C0 zPPMGnA?|(hw`yd9fAvqTL0rUje2qbTh{t5tCeLwZX9`}=SzL<2B=w;qx}gSao_8~d zFG6f%m5PoIvV-6&ZX78b}!=RUp3tAM3Em_C=Y`=v(aNw9)`Dxz<)-; zld2~w*1P3vB((hFMSl%?KyY0_8ogxoLwU8}c|F!1Vx#v$f)*yn{ZwDDcY zI-^B5`|48PXWGj?^l{WRaH4&*)R}2DGpY`xtkq#s^lmhnK%@MXe&2~znG+~GeId?U z;pQ2$M~ZqY?c#il)DfIZ-?-Z~R{B2Axjyua3+ED_EBi!`84|^HH1x-H?ntKr~0#a(wn)H vxA@zW;I27Og%*7d;xMz$Pl~Oyd#H7Iw)c139sxVF>*Q^mYJZoT-1+_hN0aVb