diff --git a/backend/app/coordinator/routes/groups.py b/backend/app/coordinator/routes/groups.py index c35ebb4..54a768d 100644 --- a/backend/app/coordinator/routes/groups.py +++ b/backend/app/coordinator/routes/groups.py @@ -2,130 +2,98 @@ from flask import abort from apiflask import APIBlueprint 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 +from ...base.utils import paginate_models bp = APIBlueprint("groups", __name__, url_prefix="/groups") @bp.route("/", methods=["GET"]) -def list_groups(): - """ - groups = (QUERY: get all groups(includes supervisor project) and filter by name) +@bp.input(GroupQuerySchema, location='query') +@bp.output(GroupsPaginationSchema) +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) - # paginate groups - - return groups - """ + response = paginate_models(page, groups_query, per_page) + if (message := response.get('message')) is not None: + abort(response['status_code'], message) + return { + "groups": response['items'], + "max_pages": response['max_pages'] + } @bp.route("/", methods=["POST"]) -def create_group() -> dict: - """ - Create group: - body: - { - name:"system pri", - project_supervisor: id - students:[index1, index2] - } +@bp.input(GroupCreateSchema) +@bp.output(MessageSchema) +def create_group(data: dict) -> dict: + name = data['name'] + students = 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() - 1. if (QUERY: check if all students exist in database): - abort() + 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']) - project_supervisor = (QUERY: get project_supervisor by id) - 2. if project_supervisor is None: - abort() + 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 + + db.session.add(group) + db.session.commit() - 3. if (QUERY: check if project_supervisor can have new group -> (limit_group - count(groups.id)) > 0): - abort() - - 4. If no errors, you can create a group - - return message - """ + return {"message": "Student was created!"} @bp.route("//", methods=["GET"]) -def detail_group(id: int): - """ - group = (QUERY: get group by id) - if (group is none): - abort() +@bp.output(GroupSchema) +def detail_group(id: int) -> Group: + group = Group.query.filter_by(id=id).first() + if group is None: + abort(400, f"Group with id {id} doesn't exist!") return group - """ @bp.route("//", methods=["DELETE"]) -def delete_group(id: int): - """ - group = (QUERY: get group by id) - if (group is none): - abort() - delete group - return message - """ +@bp.output(MessageSchema, status_code=202) +def delete_group(id: int) -> dict: + group = Group.query.filter_by(id=id).first() + if group is None: + abort(400, f"Group with id {id} doesn't exist!") + db.session.delete(group) + db.session.commit() + return {"message": "Group was deleted!"} -@bp.route("//name", methods=["PUT"]) -def edit_group_name(id: int): - """ - body: - { - name: "name_group" - } +@bp.route("/", methods=["PUT"]) +@bp.input(GroupEditSchema) +@bp.output(MessageSchema) +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() - group = (QUERY: get group by id) - if (group is none): - abort() - update group - return message - """ - - -@bp.route("//project_supervisor", methods=["PUT"]) -def edit_group_project_supervisor(id: int): - """ - body: - { - project_supervisor_id: 23 - } - - group = (QUERY: get group by id) - if (group is none): - abort() - - project_supervisor = (QUERY: get project_supervisor by id) - if project_supervisor is None: - abort() - - if (QUERY: check if project_supervisor can be assigned to new group -> (limit_group - count(groups.id)) > 0 ): - abort() - - update group - - return message - """ - - -@bp.route("//students", methods=["PUT"]) -def edit_group_student(id: int): - """ - body: - { - index: 344331 - } - - group = (QUERY: get group by id) - if (group is none): - abort() - - student = (QUERY: get student by index) - if student is None: - abort() - - if (QUERY: check if the student's have a group in database): - abort() - - update group - return message - """ + 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 e525675..048128f 100644 --- a/backend/app/coordinator/schemas.py +++ b/backend/app/coordinator/schemas.py @@ -1,6 +1,7 @@ from ..dependencies import ma from ..students.models import Student, Group from marshmallow import fields, validate, ValidationError +from ..project_supervisor.schemas import ProjectSupervisorSchema def validate_index(index): @@ -9,11 +10,11 @@ def validate_index(index): elif len(str(index)) < 6: raise ValidationError("Length of index is too short!") - class GroupSchema(ma.SQLAlchemyAutoSchema): + project_supervisor = fields.Nested(ProjectSupervisorSchema) + class Meta: model = Group - include_relationships = False class StudentSchema(ma.SQLAlchemyAutoSchema): @@ -31,6 +32,7 @@ class StudentsPaginationSchema(ma.Schema): class StudentCreateSchema(ma.Schema): first_name = fields.Str(validate=validate.Length(min=1, max=255), required=True) last_name = fields.Str(validate=validate.Length(min=1, max=255), required=True) + pesel = fields.Str(validate=validate.Length(min=0, max=11), required=True) index = fields.Integer(validate=validate_index, required=True) mode = fields.Boolean(required=True) @@ -38,6 +40,7 @@ class StudentCreateSchema(ma.Schema): class StudentEditSchema(ma.Schema): first_name = fields.Str(validate=validate.Length(min=1, max=255)) last_name = fields.Str(validate=validate.Length(min=1, max=255)) + pesel = fields.Str(validate=validate.Length(min=0, max=11)) index = fields.Integer(validate=validate_index) mode = fields.Boolean() @@ -55,4 +58,28 @@ class StudentQuerySchema(ma.Schema): order_by_first_name = fields.Str() order_by_last_name = fields.Str() page = fields.Integer() + per_page = fields.Integer() mode = fields.Boolean() + + +class GroupQuerySchema(ma.Schema): + name = fields.Str() + page = fields.Integer() + per_page = fields.Integer() + + +class GroupsPaginationSchema(ma.Schema): + groups = fields.List(fields.Nested(GroupSchema)) + max_pages = fields.Integer() + + +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) + + +class GroupEditSchema(ma.Schema): + name = fields.Str(validate=validate.Length(min=1, max=255)) + project_supervisor_id = fields.Integer(validate=validate_index) + students = fields.List(fields.Nested(StudentSchema), validate=validate.Length(min=1, max=255)) \ No newline at end of file diff --git a/backend/app/project_supervisor/schemas.py b/backend/app/project_supervisor/schemas.py index 8b13789..66ef104 100644 --- a/backend/app/project_supervisor/schemas.py +++ b/backend/app/project_supervisor/schemas.py @@ -1 +1,8 @@ +from ..dependencies import ma +from ..project_supervisor.models import ProjectSupervisor + +class ProjectSupervisorSchema(ma.SQLAlchemyAutoSchema): + class Meta: + model = ProjectSupervisor + include_relationships = False diff --git a/backend/app/students/models.py b/backend/app/students/models.py index 321506c..d41dd3d 100644 --- a/backend/app/students/models.py +++ b/backend/app/students/models.py @@ -10,15 +10,32 @@ class Group(Base): __tablename__ = "groups" name = db.Column(db.String(60), nullable=False) + cdyd_kod = db.Column(db.String(60), default='2022/SZ') + prz_kod = db.Column(db.String(60), default='06-DPRILI0') + tzaj_kod = db.Column(db.String(60), default='LAB') project_supervisor_id = db.Column(db.Integer, db.ForeignKey('project_supervisors.id')) project_supervisor = db.relationship('ProjectSupervisor', backref='groups', lazy=True) points_for_first_term = db.Column(db.Integer, default=0, nullable=False) points_for_second_term = db.Column(db.Integer, default=0, nullable=False) + @classmethod + def search_by_name(cls, search_name: str = None) -> BaseQuery: + 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}%') + + return group_query + + + class Student(Person): __tablename__ = "students" + pesel = db.Column(db.String(11), default='') index = db.Column(db.Integer, primary_key=True) group_id = db.Column(db.Integer, db.ForeignKey('groups.id')) group = db.relationship('Group', backref='students', lazy=True) diff --git a/backend/migrations/versions/ceaefb33117e_.py b/backend/migrations/versions/ceaefb33117e_.py new file mode 100644 index 0000000..622b9fd --- /dev/null +++ b/backend/migrations/versions/ceaefb33117e_.py @@ -0,0 +1,34 @@ +"""empty message + +Revision ID: ceaefb33117e +Revises: 151d3b6306ec +Create Date: 2022-06-12 17:43:24.714877 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = 'ceaefb33117e' +down_revision = '151d3b6306ec' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.add_column('groups', sa.Column('cdyd_kod', sa.String(length=60), nullable=True)) + op.add_column('groups', sa.Column('prz_kod', sa.String(length=60), nullable=True)) + op.add_column('groups', sa.Column('tzaj_kod', sa.String(length=60), nullable=True)) + op.add_column('students', sa.Column('pesel', sa.String(length=11), nullable=True)) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_column('students', 'pesel') + op.drop_column('groups', 'tzaj_kod') + op.drop_column('groups', 'prz_kod') + op.drop_column('groups', 'cdyd_kod') + # ### end Alembic commands ###