from flask import abort, current_app from apiflask import APIBlueprint from flask_sqlalchemy import get_debug_queries from ...students.models import Group, Student, YearGroup, ProjectGradeSheet from ...project_supervisor.models import ProjectSupervisor, YearGroupProjectSupervisors from ..schemas import GroupEditSchema, GroupsPaginationSchema, GroupCreateSchema, MessageSchema, GroupQuerySchema, \ DetailGroupSchema from ...dependencies import db from ...base.utils import paginate_models from ..utils import attach_points_for_first_and_second_term_to_group_models bp = APIBlueprint("groups", __name__, url_prefix="/groups") @bp.get("//") @bp.input(GroupQuerySchema, location='query') @bp.output(GroupsPaginationSchema) def list_groups(year_group_id: int, query: dict) -> dict: search_name = query.get('name') page = query.get('page') per_page = query.get('per_page') groups_query = Group.search_by_name(year_group_id, search_name) data = paginate_models(page, groups_query, per_page) items = data['items'] attach_points_for_first_and_second_term_to_group_models(items) return { "groups": items, "max_pages": data['max_pages'] } @bp.post("//") @bp.input(GroupCreateSchema) @bp.output(MessageSchema, status_code=201) def create_group(year_group_id: int, data: dict) -> dict: name = data['name'] students_indexes = data['students'] project_supervisor_id = data['project_supervisor_id'] yg = YearGroup.query.filter(YearGroup.id == year_group_id).first() if yg is None: abort(404, "Not found year group!") project_supervisor = ProjectSupervisor.query.filter_by(id=project_supervisor_id).first() limit_student_per_group = current_app.config.get('LIMIT_STUDENTS_PER_GROUP') if project_supervisor is None: abort(404, f"Not found project supervisor!") elif limit_student_per_group is not None and limit_student_per_group < len(students_indexes): abort(400, f"Too much students you want add to group, " f"The group can have only {limit_student_per_group} students") limit = db.session.query(db.func.count(ProjectSupervisor.id)). \ join(Group).filter(ProjectSupervisor.id == project_supervisor_id).group_by(ProjectSupervisor.id).scalar() ygps = YearGroupProjectSupervisors.query. \ filter(YearGroupProjectSupervisors.year_group_id == year_group_id, YearGroupProjectSupervisors.project_supervisor_id == project_supervisor_id).first() if limit is not None and ygps is not None and limit >= ygps.limit_group: abort(400, "Can't create new group, project supervisor achieved a limit of groups") group = Group(name=name, project_supervisor_id=project_supervisor_id, year_group_id=year_group_id) students_without_groups = db.session.query(Student, Group). \ join(Group, Student.groups). \ filter(Group.year_group_id == year_group_id). \ filter(db.or_(*[Student.index == idx for idx in students_indexes])).all() if len(students_without_groups) > 0: abort(400, "One or more students have already belonged to group!") students = db.session.query(Student).filter(Student.index.in_(students_indexes)).all() if len(students) != len(students_indexes): abort(404, "Not found students!") db.session.add(group) db.session.commit() for student in students: group.students.append(student) db.session.commit() pgs = ProjectGradeSheet(group_id=group.id) db.session.add(pgs) db.session.commit() return {"message": "Group was created!"} @bp.get("//detail/") @bp.output(DetailGroupSchema) def detail_group(id: int) -> Group: group = Group.query.filter_by(id=id).first() if group is None: abort(404, f"Not found group!") return group @bp.delete("//") @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(404, f"Not found group!") group.students = [] db.session.delete(group) db.session.commit() return {"message": "Group was deleted!"} @bp.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() if group is None: abort(404, f"Not found group!") students_indexes = data.get('students') name = data.get('name') project_supervisor_id = data.get('project_supervisor_id') if students_indexes is not None: students = db.session.query(Student).filter(Student.index.in_(students_indexes)).all() if len(students_indexes) != len(students): abort(404, 'Not found students!') group.students = students if name is not None: group.name = name if project_supervisor_id is not None: ps = ProjectSupervisor.query.filter(ProjectSupervisor.id == project_supervisor_id).first() if ps is None: abort(404, "Not found project supervisor!") group.project_supervisor_id = project_supervisor_id db.session.commit() return {"message": "Group was updated!"}