diff --git a/backend/db/errors/database_errors.py b/backend/db/errors/database_errors.py index 9fa9e114..eb45dc51 100644 --- a/backend/db/errors/database_errors.py +++ b/backend/db/errors/database_errors.py @@ -2,3 +2,8 @@ class ItemNotFoundError(Exception): def __init__(self, message: str) -> None: super().__init__(message) + + +class UniqueConstraintError(Exception): + def __init__(self, message: str) -> None: + super().__init__(message) diff --git a/backend/db/implementation/SqlAdminDAO.py b/backend/db/implementation/SqlAdminDAO.py new file mode 100644 index 00000000..2aff92ec --- /dev/null +++ b/backend/db/implementation/SqlAdminDAO.py @@ -0,0 +1,27 @@ +from sqlalchemy import select + +from db.errors.database_errors import ItemNotFoundError +from db.extensions import db +from db.interface.AdminDAO import AdminDAO +from db.models.models import Admin +from domain.models.AdminDataclass import AdminDataclass + + +class SqlAdminDAO(AdminDAO): + def get_admin(self, ident: int) -> AdminDataclass: + admin: Admin | None = db.session.get(Admin, ident=ident) + if not admin: + msg = f"Admin with id {ident} not found" + raise ItemNotFoundError(msg) + return admin.to_domain_model() + + def get_all_admins(self) -> list[AdminDataclass]: + admins: list[Admin] = list(db.session.scalars(select(Admin)).all()) + return [admin.to_domain_model() for admin in admins] + + def create_admin(self, name: str, email: str) -> AdminDataclass: + new_admin: Admin = Admin(name=name, email=email) + db.session.add(new_admin) + db.session.commit() + return new_admin.to_domain_model() + diff --git a/backend/db/implementation/SqlGroupDAO.py b/backend/db/implementation/SqlGroupDAO.py new file mode 100644 index 00000000..cb426e24 --- /dev/null +++ b/backend/db/implementation/SqlGroupDAO.py @@ -0,0 +1,65 @@ +from db.errors.database_errors import ItemNotFoundError, UniqueConstraintError +from db.extensions import db +from db.interface.GroupDAO import GroupDAO +from db.models.models import Group, Project, Student +from domain.models.GroupDataclass import GroupDataclass +from domain.models.StudentDataclass import StudentDataclass + + +class SqlGroupDAO(GroupDAO): + def create_group(self, project_id: int) -> GroupDataclass: + project: Project | None = db.session.get(Project, ident=project_id) + if not project: + msg = f"Project with id {project} not found" + raise ItemNotFoundError(msg) + new_group: Group = Group(project_id=project_id) + db.session.add(new_group) + db.session.commit() + return new_group.to_domain_model() + + def get_group(self, group_id: int) -> GroupDataclass: + group: Group | None = db.session.get(Group, ident=group_id) + if not group: + msg = f"Group with id {group_id} not found" + raise ItemNotFoundError(msg) + return group.to_domain_model() + + def get_groups_of_project(self, project_id: int) -> list[GroupDataclass]: + project: Project | None = db.session.get(Project, ident=project_id) + if not project: + msg = f"Project with id {project} not found" + raise ItemNotFoundError(msg) + groups: list[Group] = project.groups + return [group.to_domain_model() for group in groups] + + def get_groups_of_student(self, student_id: int) -> list[GroupDataclass]: + student: Student | None = db.session.get(Student, ident=student_id) + if not student: + msg = f"Student with id {student_id} not found" + raise ItemNotFoundError(msg) + groups: list[Group] = student.groups + return [group.to_domain_model() for group in groups] + + def add_student_to_group(self, student_id: int, group_id: int) -> None: + student: Student | None = db.session.get(Student, ident=student_id) + group: Group | None = db.session.get(Group, ident=group_id) + if not student: + msg = f"Student with id {student_id} not found" + raise ItemNotFoundError(msg) + if not group: + msg = f"Group with id {group_id} not found" + raise ItemNotFoundError(msg) + if student in group.students: + msg = f"Student with id {student_id} already in group with id {group_id}" + raise UniqueConstraintError(msg) + + group.students.append(student) + db.session.commit() + + def get_students_of_group(self, group_id: int) -> list[StudentDataclass]: + group: Group | None = db.session.get(Group, ident=group_id) + if not group: + msg = f"Group with id {group_id} not found" + raise ItemNotFoundError(msg) + students: list[Student] = group.students + return [student.to_domain_model() for student in students] diff --git a/backend/db/implementation/SqlProjectDAO.py b/backend/db/implementation/SqlProjectDAO.py new file mode 100644 index 00000000..6f2bd059 --- /dev/null +++ b/backend/db/implementation/SqlProjectDAO.py @@ -0,0 +1,40 @@ +from datetime import datetime + +from db.errors.database_errors import ItemNotFoundError +from db.extensions import db +from db.interface.ProjectDAO import ProjectDAO +from db.models.models import Project, Subject +from domain.models.ProjectDataclass import ProjectDataclass + + +class SqlProjectDAO(ProjectDAO): + def create_project(self, subject_id: int, name: str, deadline: datetime, archived: bool, requirements: str, + visible: bool, max_students: int) -> ProjectDataclass: + subject: Subject | None = db.session.get(Subject, subject_id) + if not subject: + msg = f"Subject with id {subject_id} not found" + raise ItemNotFoundError(msg) + + new_project: Project = Project(subject_id=subject_id, name=name, deadline=deadline, + archived=archived, requirements=requirements, visible=visible, + max_students=max_students) + + db.session.add(new_project) + db.session.commit() + return new_project.to_domain_model() + + + def get_project(self, project_id: int) -> ProjectDataclass: + project: Project | None = db.session.get(Project, ident=project_id) + if not project: + msg = f"Project with id {project_id} not found" + raise ItemNotFoundError(msg) + return project.to_domain_model() + + def get_projects_of_subject(self, subject_id: int) -> list[ProjectDataclass]: + subject: Subject | None = db.session.get(Subject, ident=subject_id) + if not subject: + msg = f"Subject with id {subject_id} not found" + raise ItemNotFoundError(msg) + projects: list[Project] = subject.projects + return [project.to_domain_model() for project in projects] diff --git a/backend/db/implementation/SqlStudentDAO.py b/backend/db/implementation/SqlStudentDAO.py new file mode 100644 index 00000000..580a7670 --- /dev/null +++ b/backend/db/implementation/SqlStudentDAO.py @@ -0,0 +1,26 @@ +from sqlalchemy import select + +from db.errors.database_errors import ItemNotFoundError +from db.extensions import db +from db.interface.StudentDAO import StudentDAO +from db.models.models import Student +from domain.models.StudentDataclass import StudentDataclass + + +class SqlStudentDAO(StudentDAO): + def get_student(self, ident: int) -> StudentDataclass: + student: Student | None = db.session.get(Student, ident=ident) + if not student: + msg = f"Student with id {ident} not found" + raise ItemNotFoundError(msg) + return student.to_domain_model() + + def get_all_students(self) -> list[StudentDataclass]: + students: list[Student] = list(db.session.scalars(select(Student)).all()) + return [student.to_domain_model() for student in students] + + def create_student(self, name: str, email: str) -> StudentDataclass: + new_student: Student = Student(name=name, email=email) + db.session.add(new_student) + db.session.commit() + return new_student.to_domain_model() diff --git a/backend/db/implementation/SqlSubjectDAO.py b/backend/db/implementation/SqlSubjectDAO.py new file mode 100644 index 00000000..40e59f10 --- /dev/null +++ b/backend/db/implementation/SqlSubjectDAO.py @@ -0,0 +1,70 @@ +from db.errors.database_errors import ItemNotFoundError, UniqueConstraintError +from db.extensions import db +from db.interface.SubjectDAO import SubjectDAO +from db.models.models import Student, Subject, Teacher +from domain.models.SubjectDataclass import SubjectDataclass + + +class SqlSubjectDAO(SubjectDAO): + def create_subject(self, name: str) -> SubjectDataclass: + new_subject = Subject(name=name) + db.session.add(new_subject) + db.session.commit() + return new_subject.to_domain_model() + + def get_subject(self, subject_id: int) -> SubjectDataclass: + subject: Subject | None = db.session.get(Subject, ident=subject_id) + if not subject: + msg = f"Subject with id {subject_id} not found" + raise ItemNotFoundError(msg) + return subject.to_domain_model() + + def get_subjects_of_teacher(self, teacher_id: int) -> list[SubjectDataclass]: + teacher: Teacher | None = db.session.get(Teacher, ident=teacher_id) + if not teacher: + msg = f"Teacher with id {teacher_id} not found" + raise ItemNotFoundError(msg) + subjects: list[Subject] = teacher.subjects + return [vak.to_domain_model() for vak in subjects] + + def get_subjects_of_student(self, student_id: int) -> list[SubjectDataclass]: + student: Student | None = db.session.get(Student, ident=student_id) + if not student: + msg = f"Student with id {student_id} not found" + raise ItemNotFoundError(msg) + subjects: list[Subject] = student.subjects + return [vak.to_domain_model() for vak in subjects] + + def add_student_to_subject(self, student_id: int, subject_id: int) -> None: + student: Student | None = db.session.get(Student, ident=student_id) + subject: Subject | None = db.session.get(Subject, ident=subject_id) + + if not student: + msg = f"Student with id {student_id} not found" + raise ItemNotFoundError(msg) + if not subject: + msg = f"Subject with id {subject_id} not found" + raise ItemNotFoundError(msg) + if subject in student.subjects: + msg = f"Student with id {student_id} already has subject with id {subject_id}" + raise UniqueConstraintError(msg) + + student.subjects.append(subject) + db.session.commit() + + def add_teacher_to_subject(self, teacher_id: int, subject_id: int) -> None: + teacher: Teacher | None = db.session.get(Teacher, ident=teacher_id) + subject: Subject | None = db.session.get(Subject, ident=subject_id) + + if not teacher: + msg = f"Teacher with id {teacher_id} not found" + raise ItemNotFoundError(msg) + if not subject: + msg = f"Subject with id {subject_id} not found" + raise ItemNotFoundError(msg) + if subject in teacher.subjects: + msg = f"Teacher with id {teacher_id} already has subject with id {subject_id}" + raise UniqueConstraintError(msg) + + teacher.subjects.append(subject) + db.session.commit() diff --git a/backend/db/implementation/SqlSubmissionDAO.py b/backend/db/implementation/SqlSubmissionDAO.py new file mode 100644 index 00000000..51a101b5 --- /dev/null +++ b/backend/db/implementation/SqlSubmissionDAO.py @@ -0,0 +1,49 @@ +from datetime import datetime + +from db.errors.database_errors import ItemNotFoundError +from db.extensions import db +from db.interface.SubmissionDAO import SubmissionDAO +from db.models.models import Group, Student, Submission +from domain.models.SubmissionDataclass import SubmissionDataclass, SubmissionState + + +class SqlSubmissionDAO(SubmissionDAO): + def create_submission(self, student_id: int, group_id: int, message: str,state: SubmissionState, + date_time: datetime) -> SubmissionDataclass: + + student: Student | None = db.session.get(Student, ident=student_id) + group: Group | None = db.session.get(Group, ident=group_id) + if not student: + msg = f"Student with id {student_id} not found" + raise ItemNotFoundError(msg) + if not group: + msg = f"Group with id {group_id} not found" + raise ItemNotFoundError(msg) + new_submission: Submission = Submission(student_id=student_id, + group_id=group_id, message=message, state=state, date_time=date_time) + db.session.add(new_submission) + db.session.commit() + return new_submission.to_domain_model() + + def get_submission(self, submission_id: int) -> SubmissionDataclass: + submission: Submission | None = db.session.get(Submission, ident=submission_id) + if not submission: + msg = f"Submission with id {submission_id} not found" + raise ItemNotFoundError(msg) + return submission.to_domain_model() + + def get_submissions_of_student(self, student_id: int) -> list[SubmissionDataclass]: + student: Student | None = db.session.get(Student, ident=student_id) + if not student: + msg = f"Student with id {student_id} not found" + raise ItemNotFoundError(msg) + submissions: list[Submission] = student.submissions + return [submission.to_domain_model() for submission in submissions] + + def get_submissions_of_group(self, group_id: int) -> list[SubmissionDataclass]: + group: Group | None = db.session.get(Group, ident=group_id) + if not group: + msg = f"Group with id {group_id} not found" + raise ItemNotFoundError(msg) + submissions: list[Submission] = group.submissions + return [submission.to_domain_model() for submission in submissions] diff --git a/backend/db/implementation/SqlLesgeverDAO.py b/backend/db/implementation/SqlTeacherDAO.py similarity index 54% rename from backend/db/implementation/SqlLesgeverDAO.py rename to backend/db/implementation/SqlTeacherDAO.py index 6bef5470..9623cb3e 100644 --- a/backend/db/implementation/SqlLesgeverDAO.py +++ b/backend/db/implementation/SqlTeacherDAO.py @@ -1,3 +1,5 @@ +from sqlalchemy import select + from db.errors.database_errors import ItemNotFoundError from db.extensions import db from db.interface.TeacherDAO import TeacherDAO @@ -7,22 +9,20 @@ class SqlTeacherDAO(TeacherDAO): def get_teacher(self, ident: int) -> TeacherDataclass: - teacher: Teacher | None = Teacher.query.get(ident=ident) + teacher: Teacher | None = db.session.get(Teacher, ident) if not teacher: - msg = f"Teacher with id {ident} not found" + msg = f"Teacher with id {ident} not found" raise ItemNotFoundError(msg) return teacher.to_domain_model() def get_all_teachers(self) -> list[TeacherDataclass]: - teachers: list[Teacher] = Teacher.query.all() - return [lesgever.to_domain_model() for lesgever in teachers] - - def create_teacher(self, teacher: TeacherDataclass) -> None: - new_teacher = Teacher(name=teacher.name, email=teacher.email) + teachers: list[Teacher] = list(db.session.scalars(select(Teacher)).all()) + return [teacher.to_domain_model() for teacher in teachers] + def create_teacher(self, name: str, email: str) -> TeacherDataclass: + new_teacher = Teacher(name=name, email=email) db.session.add(new_teacher) db.session.commit() - - teacher.id = new_teacher.id + return new_teacher.to_domain_model() diff --git a/backend/db/implementation/SqlUserDAO.py b/backend/db/implementation/SqlUserDAO.py new file mode 100644 index 00000000..7a1b25ac --- /dev/null +++ b/backend/db/implementation/SqlUserDAO.py @@ -0,0 +1,21 @@ +from sqlalchemy import select + +from db.errors.database_errors import ItemNotFoundError +from db.extensions import db +from db.interface.UserDAO import UserDAO +from db.models.models import User +from domain.models.UserDataclass import UserDataclass + + +class SqlUserDAO(UserDAO): + def get_user(self, ident: int) -> UserDataclass: + user: User | None = db.session.get(User, ident=ident) + if not user: + msg = f"User with id {ident} not found" + raise ItemNotFoundError(msg) + return user.to_domain_model() + + def get_all_users(self) -> list[UserDataclass]: + users: list[User] = list(db.session.scalars(select(User)).all()) + return [user.to_domain_model() for user in users] + diff --git a/backend/db/implementation/SqlVakDAO.py b/backend/db/implementation/SqlVakDAO.py deleted file mode 100644 index b841634c..00000000 --- a/backend/db/implementation/SqlVakDAO.py +++ /dev/null @@ -1,34 +0,0 @@ -from db.errors.database_errors import ItemNotFoundError -from db.extensions import db -from db.interface.SubjectDAO import SubjectDAO -from db.models.models import Subject, Teacher -from domain.models.SubjectDataclass import SubjectDataclass - - -class SqlSubjectDAO(SubjectDAO): - def create_subject(self, subject: SubjectDataclass) -> None: - - new_subject = Subject(name=subject.name) - - db.session.add(new_subject) - db.session.commit() - - subject.id = new_subject.id - - def get_subject(self, subject_id: int) -> SubjectDataclass: - subject = Subject.query.get(subject_id) - if not subject: - msg = f"Het vak met id {subject_id} kon niet in de databank gevonden worden" - raise ItemNotFoundError(msg) - - return subject.to_domain_model() - - def get_subjects(self, teacher_id: int) -> list[SubjectDataclass]: - teacher: Teacher | None = Teacher.query.get(ident=teacher_id) - - if not teacher: - msg = f"De teacher met id {teacher_id} kon niet in de databank gevonden worden" - raise ItemNotFoundError(msg) - - subjects: list[Subject] = teacher.subjects - return [vak.to_domain_model() for vak in subjects] diff --git a/backend/db/interface/AdminDAO.py b/backend/db/interface/AdminDAO.py new file mode 100644 index 00000000..f776df7e --- /dev/null +++ b/backend/db/interface/AdminDAO.py @@ -0,0 +1,36 @@ +from abc import ABC, abstractmethod + +from domain.models.AdminDataclass import AdminDataclass + + +class AdminDAO(ABC): + @abstractmethod + def get_admin(self, ident: int) -> AdminDataclass: + """ + Haalt een admin op aan de hand van zijn identificatie. + + :param ident: Het id van de te zoeken admin. + :return: De admin die overeenkomt met de gegeven id. + :raises ItemNotFoundException: Als geen admin met het gegeven id gevonden werd. + """ + raise NotImplementedError + + @abstractmethod + def get_all_admins(self) -> list[AdminDataclass]: + """ + Haalt alle admins op. + + :return: Een lijst van alle admins. + """ + raise NotImplementedError + + @abstractmethod + def create_admin(self, name: str, email: str) -> AdminDataclass: + """ + Maakt een nieuwe admin aan. + + :param name: De naam van de nieuwe admin. + :param email: De email van de nieuwe admin. + :return: De nieuwe admin + """ + raise NotImplementedError diff --git a/backend/db/interface/GroupDAO.py b/backend/db/interface/GroupDAO.py new file mode 100644 index 00000000..c76ccd73 --- /dev/null +++ b/backend/db/interface/GroupDAO.py @@ -0,0 +1,68 @@ +from abc import ABC, abstractmethod + +from domain.models.GroupDataclass import GroupDataclass +from domain.models.StudentDataclass import StudentDataclass + + +class GroupDAO(ABC): + @abstractmethod + def create_group(self, project_id: int) -> GroupDataclass: + """ + Creëert een nieuw GroupDataClass in de database en associeert het met een ProjectDataClass. + + :param project_id: Id van het project dat gelinkt is aan de groep + :raises: ItemNotFoundException: Als er geen ProjectDataClass met de opgegeven `project_id` in de database is. + :returns: De nieuw aangemaakte groep + """ + raise NotImplementedError + + @abstractmethod + def get_group(self, group_id: int) -> GroupDataclass: + """ + Haalt een GroupDataClass op aan de hand van zijn identificatie. + + :param group_id: De identificatie van het op te halen GroupDataClass. + :raises ItemNotFoundException: Als er geen GroupDataClass met de opgegeven `group_id` in de database bestaat. + :returns: De domeinmodel-instantie van het opgehaalde GroupDataClass. + """ + raise NotImplementedError + + @abstractmethod + def get_groups_of_project(self, project_id: int) -> list[GroupDataclass]: + """ + Haalt alle groepen op die bij een bepaald project horen. + + :param project_id: Het subject waarvan de projecten opgehaald moeten worden. + :return: Een lijst van projecten die bij een bepaald project horen. + """ + raise NotImplementedError + + @abstractmethod + def get_groups_of_student(self, student_id: int) -> list[GroupDataclass]: + """ + Haalt alle groepen op die bij een bepaalde student horen. + + :param student_id: De student waarvan de groepen opgehaald moeten worden. + :return: Een lijst van groepen die bij een bepaald student horen. + """ + raise NotImplementedError + + @abstractmethod + def add_student_to_group(self, student_id: int, group_id: int) -> None: + """ + Gaat een student toevoegen aan een groep + + :param student_id: De student die aan de groep moet toegevoegd worden. + :param group_id: De groep waaraan de student moet toegevoegd worden. + :raises ItemNotFoundException: Als er geen group/student met gegeven id in de databank zit. + """ + raise NotImplementedError + + def get_students_of_group(self, group_id: int) -> list[StudentDataclass]: + """ + Gaat alle studenten geven die in een bepaalde groep zitten + + :param group_id: De groep waarvan de studenten worden opgeroepen + :raises ItemNotFoundException: Als er geen group met gegeven id in de databank zit. + """ + raise NotImplementedError diff --git a/backend/db/interface/ProjectDAO.py b/backend/db/interface/ProjectDAO.py new file mode 100644 index 00000000..e1db39dd --- /dev/null +++ b/backend/db/interface/ProjectDAO.py @@ -0,0 +1,45 @@ +from abc import ABC, abstractmethod +from datetime import datetime + +from domain.models.ProjectDataclass import ProjectDataclass + + +class ProjectDAO(ABC): + @abstractmethod + def create_project(self, subject_id: int, name: str, deadline: datetime, archived: bool, requirements: str, + visible: bool, max_students: int) -> ProjectDataclass: + """ + Creëert een nieuw ProjectDataClass in de database en associeert het met een SubjectDataClass. + + :param max_students: maximaal aantal studenten per groep per project + :param visible: of het project zichtbaar is voor de studenten + :param requirements: Uitleg van het project + :param archived: Of het project gearchiveerd is + :param name: De naam van het project + :param deadline: De deadline van het project + :param subject_id: De identificatie van de SubjectDataClass waarmee het ProjectDataClass geassocieerd wordt. + :raises: ItemNotFoundException: Als er geen SubjectDataClass met de opgegeven `teacher_id` in de database is. + :returns: Het nieuw aangemaakte project + """ + raise NotImplementedError + + @abstractmethod + def get_project(self, project_id: int) -> ProjectDataclass: + """ + Haalt een ProjectDataClass op aan de hand van zijn identificatie. + + :param project_id: De identificatie van het op te halen ProjectDataClass. + :raises ItemNotFoundException: Als er geen ProjectDataClass met de opgegeven `project_id` in de database bestaat + :returns: De domeinmodel-instantie van het opgehaalde ProjectDataClass. + """ + raise NotImplementedError + + @abstractmethod + def get_projects_of_subject(self, subject_id: int) -> list[ProjectDataclass]: + """ + Haalt alle projecten op die bij een bepaald subject horen. + + :param subject_id: Het subject waarvan de projecten opgehaald moeten worden. + :return: Een lijst van projecten die bij een bepaald subject horen. + """ + raise NotImplementedError diff --git a/backend/db/interface/StudentDAO.py b/backend/db/interface/StudentDAO.py new file mode 100644 index 00000000..19e7b6c6 --- /dev/null +++ b/backend/db/interface/StudentDAO.py @@ -0,0 +1,36 @@ +from abc import ABC, abstractmethod + +from domain.models.StudentDataclass import StudentDataclass + + +class StudentDAO(ABC): + @abstractmethod + def get_student(self, ident: int) -> StudentDataclass: + """ + Haalt een student op aan de hand van zijn identificatie. + + :param ident: Het id van de te zoeken student. + :return: De student die overeenkomt met de gegeven id. + :raises ItemNotFoundException: Als geen student met het gegeven id gevonden werd. + """ + raise NotImplementedError + + @abstractmethod + def get_all_students(self) -> list[StudentDataclass]: + """ + Haalt alle studenten op. + + :return: Een lijst van alle studenten. + """ + raise NotImplementedError + + @abstractmethod + def create_student(self, name: str, email: str) -> StudentDataclass: + """ + Maakt een nieuwe student aan. + + :param name: De naam van de nieuwe student + :param email: De email van de nieuwe student + :returns: De nieuw aangemaakte student + """ + raise NotImplementedError diff --git a/backend/db/interface/SubjectDAO.py b/backend/db/interface/SubjectDAO.py index bde7c4a7..cf8a2d0a 100644 --- a/backend/db/interface/SubjectDAO.py +++ b/backend/db/interface/SubjectDAO.py @@ -5,13 +5,12 @@ class SubjectDAO(ABC): @abstractmethod - def create_subject(self, subject: SubjectDataclass) -> None: + def create_subject(self, name: str) -> SubjectDataclass: """ - Creëert een nieuw SubjectDataclass in de database en associeert het met een TeacherDataclass. + Creëert een nieuw SubjectDataclass in de database. - :param subject: De SubjectDataclass domeinmodel-instantie die aan de database moet worden toegevoegd. - :param teacher_id: De identificatie van de TeacherDataclass waarmee het SubjectDataclass geassocieerd wordt. - :raises: ItemNotFoundException: Als er geen TeacherDataclass met de opgegeven `teacher_id` in de database is. + :param name: De naam van het nieuwe vak. + :returns: Het nieuw aangemaakte subject. """ raise NotImplementedError @@ -27,7 +26,7 @@ def get_subject(self, subject_id: int) -> SubjectDataclass: raise NotImplementedError @abstractmethod - def get_subjects(self, teacher_id: int) -> list[SubjectDataclass]: + def get_subjects_of_teacher(self, teacher_id: int) -> list[SubjectDataclass]: """ Haalt de subjects op die door een bepaalde teacher worden gegeven. @@ -35,3 +34,35 @@ def get_subjects(self, teacher_id: int) -> list[SubjectDataclass]: :return: Een lijst van subjects die door de gegeven teacher worden gegeven. """ raise NotImplementedError + + @abstractmethod + def get_subjects_of_student(self, student_id: int) -> list[SubjectDataclass]: + """ + Haalt de subjects op die door een bepaalde student worden gevolgd. + + :param student_id: De student waarvan de subjects opgehaald moeten worden. + :return: Een lijst van subjects die door de gegeven student worden gegeven. + """ + raise NotImplementedError + + @abstractmethod + def add_student_to_subject(self, student_id: int, subject_id: int) -> None: + """ + Voegt een student toe aan een vak. + + :param subject_id: De id van subject die door de student wordt gevolgd. + :param student_id: De student die subject volgt. + :raises: ItemNotFoundException: Als er geen student/subject met de opgegeven id in de database is. + """ + raise NotImplementedError + + @abstractmethod + def add_teacher_to_subject(self, teacher_id: int, subject_id: int) -> None: + """ + Voegt een teacher toe aan een vak. + + :param subject_id: De id van subject die door de teacher gegeven wordt. + :param teacher_id: De teacher die dit subject geeft. + :raises: ItemNotFoundException: Als er geen teacher/subject met de opgegeven id in de database is. + """ + raise NotImplementedError diff --git a/backend/db/interface/SubmissionDAO.py b/backend/db/interface/SubmissionDAO.py new file mode 100644 index 00000000..09651dca --- /dev/null +++ b/backend/db/interface/SubmissionDAO.py @@ -0,0 +1,53 @@ +from abc import ABC, abstractmethod +from datetime import datetime + +from domain.models.SubmissionDataclass import SubmissionDataclass, SubmissionState + + +class SubmissionDAO(ABC): + @abstractmethod + def create_submission(self, student_id: int, group_id: int, message: str, + state: SubmissionState, date_time: datetime) -> SubmissionDataclass: + """ + Creëert een nieuw SubmissionDataClass in de database en associeert het met een StudentDataclass en een + GroupDataClass. + + :param student_id: De identificatie van de StudentDataclass waarmee het SubmissionDataClass geassocieerd wordt. + :param group_id: De identificatie van de GroupDataClass waarmee het SubmissionDataClass geassocieerd wordt + :raises: ItemNotFoundException: Als er geen StudentDataclass of GroupDataClass met de opgegeven `student_id` of + `group_id` in de database is. + :return: De nieuw aangemaakte submission + """ + raise NotImplementedError + + @abstractmethod + def get_submission(self, submission_id: int) -> SubmissionDataclass: + """ + Haalt een SubmissionDataClass op aan de hand van zijn identificatie. + + :param submission_id: De identificatie van het op te halen SubmissionDataClass. + :raises ItemNotFoundException: Als er geen SubmissionDataclass met de opgegeven `project_id` in de database + bestaat. + :returns: De domeinmodel-instantie van het opgehaalde SubmissionDataClass. + """ + raise NotImplementedError + + @abstractmethod + def get_submissions_of_student(self, student_id: int) -> list[SubmissionDataclass]: + """ + Haalt alle projecten op die bij een bepaalde student horen. + + :param student_id: De student waarvan de submissions opgehaald moeten worden. + :return: Een lijst van submissions die bij een bepaalde student horen. + """ + raise NotImplementedError + + @abstractmethod + def get_submissions_of_group(self, group_id: int) -> list[SubmissionDataclass]: + """ + Haalt alle projecten op die bij een bepaalde groep horen. + + :param group_id: De groep waarvan de submissions opgehaald moeten worden. + :return: Een lijst van submissions die bij een bepaalde groep horen. + """ + raise NotImplementedError diff --git a/backend/db/interface/TeacherDAO.py b/backend/db/interface/TeacherDAO.py index 333822fe..5ea45861 100644 --- a/backend/db/interface/TeacherDAO.py +++ b/backend/db/interface/TeacherDAO.py @@ -25,10 +25,12 @@ def get_all_teachers(self) -> list[TeacherDataclass]: raise NotImplementedError @abstractmethod - def create_teacher(self, teacher: TeacherDataclass) -> None: + def create_teacher(self, name: str, email: str) -> TeacherDataclass: """ Maakt een nieuwe teacher aan. - :param teacher: De teacher die aangemaakt moet worden. + :param name: De naam van de nieuwe teacher. + :param email: De email van de nieuwe teacher. + :returns: De nieuw aangemaakte teacher. """ raise NotImplementedError diff --git a/backend/db/interface/UserDAO.py b/backend/db/interface/UserDAO.py new file mode 100644 index 00000000..e4d85b25 --- /dev/null +++ b/backend/db/interface/UserDAO.py @@ -0,0 +1,25 @@ +from abc import ABC, abstractmethod + +from domain.models.UserDataclass import UserDataclass + + +class UserDAO(ABC): + @abstractmethod + def get_user(self, ident: int) -> UserDataclass: + """ + Haalt een user op aan de hand van zijn identificatie. + + :param ident: Het id van de te zoeken user. + :return: De user die overeenkomt met de gegeven id. + :raises ItemNotFoundException: Als geen user met het gegeven id gevonden werd. + """ + raise NotImplementedError + + @abstractmethod + def get_all_users(self) -> list[UserDataclass]: + """ + Haalt alle users op. + + :return: Een lijst van alle users. + """ + raise NotImplementedError diff --git a/backend/fill_database_mock.py b/backend/fill_database_mock.py index 9ba844d8..0981928a 100644 --- a/backend/fill_database_mock.py +++ b/backend/fill_database_mock.py @@ -1,45 +1,54 @@ -import sys +from datetime import datetime + +from psycopg2 import tz from app import app from db.extensions import db -from db.implementation.SqlLesgeverDAO import SqlTeacherDAO -from db.implementation.SqlVakDAO import SqlSubjectDAO -from db.interface.SubjectDAO import SubjectDAO -from db.interface.TeacherDAO import TeacherDAO -from domain.models.SubjectDataclass import SubjectDataclass -from domain.models.TeacherDataclass import TeacherDataclass +from db.implementation.SqlAdminDAO import SqlAdminDAO +from db.implementation.SqlGroupDAO import SqlGroupDAO +from db.implementation.SqlProjectDAO import SqlProjectDAO +from db.implementation.SqlStudentDAO import SqlStudentDAO +from db.implementation.SqlSubjectDAO import SqlSubjectDAO +from db.implementation.SqlTeacherDAO import SqlTeacherDAO if __name__ == "__main__": with app.app_context(): db.create_all() - sys.exit() # De DAO's moeten nog aangemaakt worden - teacher_dao: TeacherDAO = SqlTeacherDAO() - subject_dao: SubjectDAO = SqlSubjectDAO() - - # Maak nieuwe lesgevers aan. - Gunnar = TeacherDataclass(name="Gunnar Brinkmann") - Peter = TeacherDataclass(name="Peter Dawyndt") - Eric = TeacherDataclass(name="Eric Laermans") - - # Voeg lesgevers toe aan de databank via de teacher DAO - teacher_dao.create_teacher(Gunnar) - teacher_dao.create_teacher(Peter) - teacher_dao.create_teacher(Eric) - - # Maak nieuwe subjects aan - AD2 = SubjectDataclass(name="Algoritmen en Datastructuren II") - AD3 = SubjectDataclass(name="Algoritmen en Datastructuren III") - Computergebruik = SubjectDataclass(name="Computergebruik") - ComputationeleBiologie = SubjectDataclass(name="Computationele Biologie") - RAF = SubjectDataclass(name="Redeneren, Abstraheren en Formuleren") - InformationSecurity = SubjectDataclass(name="Information Security") - - # Steek de subjects in de databank - subject_dao.create_subject(AD2, Gunnar.id) - subject_dao.create_subject(AD3, Gunnar.id) - - subject_dao.create_subject(Computergebruik, Peter.id) - subject_dao.create_subject(ComputationeleBiologie, Peter.id) - - subject_dao.create_subject(RAF, Eric.id) - subject_dao.create_subject(InformationSecurity, Eric.id) + + admin_dao = SqlAdminDAO() + student_dao = SqlStudentDAO() + teacher_dao = SqlTeacherDAO() + subject_dao = SqlSubjectDAO() + group_dao = SqlGroupDAO() + project_dao = SqlProjectDAO() + + # maak een vak + objeprog = subject_dao.create_subject(name="OBJECTGERICHTPROGRAMMEREN") + + # maak een project voor dat vak + objeprog_project = project_dao.create_project(subject_id=objeprog.id, + name="PROJECT", + archived=False, + visible=True, + requirements="Maak iets in javafx", + max_students=2, + deadline=datetime(2000, 1, 1, 0, 0, 0, tzinfo=tz.LOCAL)) + + # maak een groepje voor het project van objeprog + groep1 = group_dao.create_group(project_id=objeprog_project.id) + + # maak studenten + student1 = student_dao.create_student("Student1", "Student1@gmail.com") + student2 = student_dao.create_student("Student2", "Student2@gmail.com") + student3 = student_dao.create_student("Student3", "Student3@gmail.com") + + # maak teacher + teacher1 = teacher_dao.create_teacher("Teacher1", "Teacher1@gmail.com") + + # voeg teacher toe aan objeprog + subject_dao.add_teacher_to_subject(teacher1.id, objeprog.id) + + # voeg studenten toe aan de groep + group_dao.add_student_to_group(student1.id, groep1.id) + group_dao.add_student_to_group(student2.id, groep1.id) + group_dao.add_student_to_group(student3.id, groep1.id) diff --git a/backend/pyproject.toml b/backend/pyproject.toml index 47494028..69bedea1 100644 --- a/backend/pyproject.toml +++ b/backend/pyproject.toml @@ -85,7 +85,9 @@ ignore = [ "INP001", # File `...` is part of an implicit namespace package "S101", # is nodig voor de testen "TCH001", # Move application import `...` into a type-checking block (dit is enkel voor performance) - "RUF009" # Do not perform function call `...` in dataclass defaults but needed for sql alchemy + "RUF009", # Do not perform function call `...` in dataclass defaults but needed for sql alchemy + "PLR0913", # Too many arguments in function + "FBT001" # Boolean-typed positional argument in function dfinition ] # Allow fix for all enabled rules (when `--fix`) is provided. diff --git a/backend/routes/teachers.py b/backend/routes/teachers.py index f9ea522d..69c69323 100644 --- a/backend/routes/teachers.py +++ b/backend/routes/teachers.py @@ -3,7 +3,7 @@ from flask import Blueprint, Response, request -from db.implementation.SqlLesgeverDAO import SqlTeacherDAO +from db.implementation.SqlTeacherDAO import SqlTeacherDAO from db.interface.TeacherDAO import TeacherDAO from domain.models.TeacherDataclass import TeacherDataclass from domain.validation.TeacherValidator import TeacherValidator @@ -46,6 +46,6 @@ def create_teacher() -> Response: dao: TeacherDAO = SqlTeacherDAO() lesgever = TeacherDataclass(**teacher_data) # Vul alle velden van het dataobject in met de json - dao.create_teacher(lesgever) + dao.create_teacher(lesgever.name, lesgever.email) return Response(json.dumps(lesgever.to_dict()), status=HTTPStatus.CREATED)