Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 82 additions & 34 deletions rating_api/routes/lecturer.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
import datetime
from typing import Literal

Expand All @@ -6,41 +6,41 @@
from fastapi.exceptions import ValidationException
from fastapi_filter import FilterDepends
from fastapi_sqlalchemy import db
from sqlalchemy import and_

from rating_api.exceptions import AlreadyExists, ObjectNotFound
from rating_api.models import Comment, Lecturer, LecturerUserComment, ReviewStatus
from rating_api.models import (Comment, Lecturer, LecturerUserComment,
ReviewStatus)
from rating_api.schemas.base import StatusResponseModel
from rating_api.schemas.models import (
CommentGet,
LecturerGet,
LecturerGetAll,
LecturerPatch,
LecturerPost,
LecturersFilter,
LecturerUpdateRatingPatch,
LecturerWithRank,
)

from rating_api.schemas.models import (CommentGet, LecturerGet, LecturerGetAll,
LecturerPatch, LecturerPost,
LecturersFilter,
LecturerUpdateRatingPatch,
LecturerWithRank)
from sqlalchemy import and_

lecturer = APIRouter(prefix="/lecturer", tags=["Lecturer"])


@lecturer.post("", response_model=LecturerGet)
async def create_lecturer(
lecturer_info: LecturerPost,
_=Depends(UnionAuth(scopes=["rating.lecturer.create"], allow_none=False, auto_error=True)),
_=Depends(
UnionAuth(scopes=["rating.lecturer.create"], allow_none=False, auto_error=True)
),
) -> LecturerGet:
"""
Scopes: `["rating.lecturer.create"]`

Создает преподавателя в базе данных RatingAPI
"""
get_lecturer: Lecturer = (
Lecturer.query(session=db.session).filter(Lecturer.timetable_id == lecturer_info.timetable_id).one_or_none()
Lecturer.query(session=db.session)
.filter(Lecturer.timetable_id == lecturer_info.timetable_id)
.one_or_none()
)
if get_lecturer is None:
new_lecturer: Lecturer = Lecturer.create(session=db.session, **lecturer_info.model_dump())
new_lecturer: Lecturer = Lecturer.create(
session=db.session, **lecturer_info.model_dump()
)
db.session.commit()
return LecturerGet.model_validate(new_lecturer)
raise AlreadyExists(Lecturer, lecturer_info.timetable_id)
Expand All @@ -49,7 +49,11 @@
@lecturer.patch("/import_rating", response_model=LecturerUpdateRatingPatch)
async def update_lecturer_rating(
lecturer_rank_info: list[LecturerWithRank],
_=Depends(UnionAuth(scopes=["rating.lecturer.update_rating"], allow_none=False, auto_error=True)),
_=Depends(
UnionAuth(
scopes=["rating.lecturer.update_rating"], allow_none=False, auto_error=True
)
),
) -> LecturerUpdateRatingPatch:
"""
Scopes: `["rating.lecturer.update_rating"]`
Expand All @@ -71,12 +75,18 @@
success_fl = False

lecturer_rank_dumped = lecturer_rank.model_dump()
lecturer_rank_dumped["rank_update_ts"] = datetime.datetime.now(tz=datetime.timezone.utc)
lecturer_rank_dumped["rank_update_ts"] = datetime.datetime.now(
tz=datetime.timezone.utc
)

lecturer_id = lecturer_rank_dumped.pop("id")

if Lecturer.get(id=lecturer_id, session=db.session):
updated_lecturers.append(Lecturer.update(id=lecturer_id, session=db.session, **lecturer_rank_dumped))
updated_lecturers.append(
Lecturer.update(
id=lecturer_id, session=db.session, **lecturer_rank_dumped
)
)
else:
success_fl = False

Expand All @@ -91,8 +101,19 @@
return response_validated


@lecturer.get("/timetable-id/{timetable_id}", response_model=LecturerGet)
async def get_lecturer_by_timetable_id(timetable_id: int) -> LecturerGet:
lecturer: Lecturer = Lecturer.query(session=db.session).filter(Lecturer.timetable_id == timetable_id).one_or_none()
if lecturer is None:
raise ObjectNotFound(Lecturer, timetable_id)
result = LecturerGet.model_validate(lecturer)
return result


@lecturer.get("/{id}", response_model=LecturerGet)
async def get_lecturer(id: int, info: list[Literal["comments"]] = Query(default=[])) -> LecturerGet:
async def get_lecturer(
id: int, info: list[Literal["comments"]] = Query(default=[])
) -> LecturerGet:
"""
Scopes: `["rating.lecturer.read"]`

Expand All @@ -102,7 +123,9 @@
Если передано `'comments'`, то возвращаются одобренные комментарии к преподавателю.
Subject лектора возвращшается либо из базы данных, либо из любого аппрувнутого комментария
"""
lecturer: Lecturer = Lecturer.query(session=db.session).filter(Lecturer.id == id).one_or_none()
lecturer: Lecturer = (
Lecturer.query(session=db.session).filter(Lecturer.id == id).one_or_none()
)
if lecturer is None:
raise ObjectNotFound(Lecturer, id)
result = LecturerGet.model_validate(lecturer)
Expand All @@ -114,7 +137,9 @@
if comment.review_status is ReviewStatus.APPROVED
]
if "comments" in info and approved_comments:
result.comments = sorted(approved_comments, key=lambda comment: comment.create_ts, reverse=True)
result.comments = sorted(
approved_comments, key=lambda comment: comment.create_ts, reverse=True
)
if approved_comments:
result.subjects = list({comment.subject for comment in approved_comments})
return result
Expand Down Expand Up @@ -159,7 +184,9 @@
больше, чем переданный 'mark'.
"""
lecturers_query = lecturer_filter.filter(
Lecturer.query(session=db.session).outerjoin(Lecturer.comments).group_by(Lecturer.id)
Lecturer.query(session=db.session)
.outerjoin(Lecturer.comments)
.group_by(Lecturer.id)
)
lecturers_query = lecturer_filter.sort(lecturers_query)
lecturers = lecturers_query.offset(offset).limit(limit).all()
Expand All @@ -178,26 +205,34 @@
if (
mark is not None
and approved_comments
and sum(comment.mark_general for comment in approved_comments) / len(approved_comments) <= mark
and sum(comment.mark_general for comment in approved_comments)
/ len(approved_comments)
<= mark
):
continue
if "comments" in info and approved_comments:
lecturer_to_result.comments = sorted(
approved_comments, key=lambda comment: comment.create_ts, reverse=True
approved_comments,
key=lambda comment: comment.create_ts,
reverse=True,
)
if approved_comments:
lecturer_to_result.subjects = list({comment.subject for comment in approved_comments})
lecturer_to_result.subjects = list(
{comment.subject for comment in approved_comments}
)
result.lecturers.append(lecturer_to_result)
if len(result.lecturers) == 0:
raise ObjectNotFound(Lecturer, 'all')
raise ObjectNotFound(Lecturer, "all")
return result


@lecturer.patch("/{id}", response_model=LecturerGet)
async def update_lecturer(
id: int,
lecturer_info: LecturerPatch,
_=Depends(UnionAuth(scopes=["rating.lecturer.update"], allow_none=False, auto_error=True)),
_=Depends(
UnionAuth(scopes=["rating.lecturer.update"], allow_none=False, auto_error=True)
),
) -> LecturerGet:
"""
Scopes: `["rating.lecturer.update"]`
Expand All @@ -208,22 +243,31 @@

check_timetable_id = (
Lecturer.query(session=db.session)
.filter(and_(Lecturer.timetable_id == lecturer_info.timetable_id, Lecturer.id != id))
.filter(
and_(Lecturer.timetable_id == lecturer_info.timetable_id, Lecturer.id != id)
)
.one_or_none()
)
if check_timetable_id:
raise AlreadyExists(Lecturer, lecturer_info.timetable_id)

result = LecturerGet.model_validate(
Lecturer.update(lecturer.id, **lecturer_info.model_dump(exclude_unset=True), session=db.session)
Lecturer.update(
lecturer.id,
**lecturer_info.model_dump(exclude_unset=True),
session=db.session
)
)
result.comments = None
return result


@lecturer.delete("/{id}", response_model=StatusResponseModel)
async def delete_lecturer(
id: int, _=Depends(UnionAuth(scopes=["rating.lecturer.delete"], allow_none=False, auto_error=True))
id: int,
_=Depends(
UnionAuth(scopes=["rating.lecturer.delete"], allow_none=False, auto_error=True)
),
):
"""
Scopes: `["rating.lecturer.delete"]`
Expand All @@ -234,11 +278,15 @@
for comment in check_lecturer.comments:
Comment.delete(id=comment.uuid, session=db.session)

lecturer_user_comments = LecturerUserComment.query(session=db.session).filter(LecturerUserComment.lecturer_id == id)
lecturer_user_comments = LecturerUserComment.query(session=db.session).filter(
LecturerUserComment.lecturer_id == id
)
for lecturer_user_comment in lecturer_user_comments:
LecturerUserComment.delete(lecturer_user_comment.id, session=db.session)

Lecturer.delete(session=db.session, id=id)
return StatusResponseModel(
status="Success", message="Lecturer has been deleted", ru="Преподаватель удален из RatingAPI"
status="Success",
message="Lecturer has been deleted",
ru="Преподаватель удален из RatingAPI",
)
Loading
Loading