diff --git a/backend/app/coordinator/routes/groups.py b/backend/app/coordinator/routes/groups.py index 54a768d..83c2feb 100644 --- a/backend/app/coordinator/routes/groups.py +++ b/backend/app/coordinator/routes/groups.py @@ -5,8 +5,8 @@ from flask_sqlalchemy import get_debug_queries from ...students.models import Group, Student from ...project_supervisor.models import ProjectSupervisor from ..schemas import GroupSchema, GroupEditSchema, GroupsPaginationSchema, \ - GroupCreateSchema, MessageSchema, FileSchema, GroupQuerySchema -from ...dependencies import db, ma + GroupCreateSchema, MessageSchema, GroupQuerySchema +from ...dependencies import db from ...base.utils import paginate_models bp = APIBlueprint("groups", __name__, url_prefix="/groups") @@ -19,7 +19,7 @@ def list_groups(query: dict) -> dict: search_name = query.get('name') page = query.get('page') per_page = query.get('per_page') - + groups_query = Group.search_by_name(search_name) response = paginate_models(page, groups_query, per_page) @@ -36,29 +36,36 @@ def list_groups(query: dict) -> dict: @bp.output(MessageSchema) def create_group(data: dict) -> dict: name = data['name'] - students = data['students'] + students_indexes = data['students'] project_supervisor_id = data['project_supervisor_id'] - group = Group.query.filter_by(name=name).first() - if group is not None: - abort(400, "Group has already exists!") - - project_supervisor = ProjectSupervisor.query.filter_by(id=project_supervisor_id).first() - if project_supervisor is None: - abort(404, f"Student with id {project_supervisor_id} doesn't exist!") - - group = Group(name=name, project_supervisor_id = data['project_supervisor_id']) + # can assign a new group to project_supervisor + result = db.session.query(ProjectSupervisor.count_groups - db.func.count(ProjectSupervisor.id)). \ + join(Group).filter(ProjectSupervisor.id == project_supervisor_id). \ + group_by(ProjectSupervisor.id).scalar() + if result is None: + abort(400, "Project Supervisor doesnt exist") + elif result <= 0: + abort(400, "Can't create new group, project supervisor achieved a limit of groups") + + group = Group(name=name, project_supervisor_id=project_supervisor_id) + + students_without_groups = db.session.query(Student).join(Group, isouter=True) \ + .filter(Group.id.is_(None)).filter(Student.index.in_(students_indexes)).count() + + if students_without_groups != len(students_indexes): + abort(400, "One or more students have already belonged to group!") + + students = db.session.query(Student).filter(Student.index.in_(students_indexes)).all() for student in students: - st = Student.query(index = student.index).first() - if st is None: - abort(404, 'Not found student!') - st.group_id = group.id - + student.group_id = group.id + + db.session.add_all(students) db.session.add(group) db.session.commit() - return {"message": "Student was created!"} + return {"message": "Project Supervisor was created!"} @bp.route("//", methods=["GET"]) @@ -87,13 +94,13 @@ def delete_group(id: int) -> dict: def edit_group(id: int, data: dict) -> dict: if not data: abort(400, 'You have passed empty data!') - + group_query = Group.query.filter_by(id=id) group = group_query.first() if group is None: abort(400, f"Group with id {id} doesn't exist!") - + group_query.update(group) db.session.commit() return {"message": "Group was updated!"} diff --git a/backend/app/coordinator/schemas.py b/backend/app/coordinator/schemas.py index d6ab649..47be5cc 100644 --- a/backend/app/coordinator/schemas.py +++ b/backend/app/coordinator/schemas.py @@ -3,6 +3,7 @@ from ..students.models import Student, Group from ..project_supervisor.models import ProjectSupervisor from marshmallow import fields, validate, ValidationError + def validate_index(index): if len(str(index)) > 6: raise ValidationError("Length of index is too long!") @@ -18,7 +19,7 @@ class ProjectSupervisorSchema(ma.SQLAlchemyAutoSchema): class GroupSchema(ma.SQLAlchemyAutoSchema): project_supervisor = fields.Nested(ProjectSupervisorSchema) - + class Meta: model = Group @@ -81,8 +82,8 @@ class GroupsPaginationSchema(ma.Schema): class GroupCreateSchema(ma.Schema): name = fields.Str(validate=validate.Length(min=1, max=255), required=True) - project_supervisor_id = fields.Integer(validate=validate_index, required=True) - students = fields.List(fields.Nested(StudentSchema), validate=validate.Length(min=1, max=255), required=True) + project_supervisor_id = fields.Integer(required=True) + students = fields.List(fields.Integer(validate=validate_index, required=True)) class GroupEditSchema(ma.Schema): diff --git a/backend/app/project_supervisor/models.py b/backend/app/project_supervisor/models.py index 6d296a6..5f0bd6b 100644 --- a/backend/app/project_supervisor/models.py +++ b/backend/app/project_supervisor/models.py @@ -6,6 +6,7 @@ from sqlalchemy import or_ from sqlalchemy.sql import text from ..base.utils import order_by_column_name + class ProjectSupervisor(Base, Person): __tablename__ = "project_supervisors" @@ -21,16 +22,15 @@ class ProjectSupervisor(Base, Person): project_supervisors_query = cls.query if mode is not None: - project_supervisors_query = project_supervisors_query.filter(mode != 1-mode) + project_supervisors_query = project_supervisors_query.filter(mode != 1 - mode) if fullname is not None: - """This works only for sqlite3 database - concat function doesn't exist so i used builtin concat - operator specific only for sqlite db - || """ project_supervisors_query = project_supervisors_query.filter( - text("project_supervisorss_first_name || ' ' || project_supervisorss_last_name LIKE :fullname ") - ).params(fullname=f'{fullname}%') + (ProjectSupervisor.first_name + ' ' + ProjectSupervisor.last_name).like(f'{fullname}%')) - project_supervisors_query = order_by_column_name(project_supervisors_query, ProjectSupervisor.first_name, order_by_first_name) - project_supervisors_query = order_by_column_name(project_supervisors_query, ProjectSupervisor.last_name, order_by_last_name) + project_supervisors_query = order_by_column_name(project_supervisors_query, ProjectSupervisor.first_name, + order_by_first_name) + project_supervisors_query = order_by_column_name(project_supervisors_query, ProjectSupervisor.last_name, + order_by_last_name) return project_supervisors_query diff --git a/backend/app/students/models.py b/backend/app/students/models.py index d41dd3d..4bfeef3 100644 --- a/backend/app/students/models.py +++ b/backend/app/students/models.py @@ -23,15 +23,11 @@ class Group(Base): group_query = cls.query if search_name is not None: - group_query = group_query.filter( - text("groups_name LIKE :search_name ") - ).params(search_name=f'{search_name}%') - + group_query = group_query.filter(Group.name.like(f'{search_name}%')) + return group_query - - class Student(Person): __tablename__ = "students" @@ -52,11 +48,7 @@ class Student(Person): student_query = student_query.filter_by(mode=mode) if fullname is not None: - """This works only for sqlite3 database - concat function doesn't exist so i used builtin concat - operator specific only for sqlite db - || """ - student_query = student_query.filter( - text("students_first_name || ' ' || students_last_name LIKE :fullname ") - ).params(fullname=f'{fullname}%') + student_query = student_query.filter((Student.first_name + ' ' + Student.last_name).like(f'{fullname}%')) student_query = order_by_column_name(student_query, Student.first_name, order_by_first_name) student_query = order_by_column_name(student_query, Student.last_name, order_by_last_name)