mirror of
https://gitlab.com/megazordpobeda/DataRush.git
synced 2026-05-23 03:57:09 +00:00
feat: added review module
This commit is contained in:
@@ -1,16 +1,14 @@
|
||||
from datetime import datetime
|
||||
from typing import Literal
|
||||
from uuid import UUID
|
||||
|
||||
from ninja import ModelSchema, Schema
|
||||
from pydantic import Field
|
||||
|
||||
from apps.review.models import Review, Reviewer
|
||||
from apps.review.models import Review, Reviewer, ReviewStatusChoices
|
||||
from apps.task.models import CompetitionTaskSubmission
|
||||
|
||||
|
||||
class PingOut(Schema):
|
||||
status: str = "ok"
|
||||
|
||||
|
||||
class ReviewerOut(ModelSchema):
|
||||
id: UUID
|
||||
|
||||
@@ -19,20 +17,81 @@ class ReviewerOut(ModelSchema):
|
||||
exclude = ("token",)
|
||||
|
||||
|
||||
class CriteriaMarkOut(Schema):
|
||||
slug: str
|
||||
mark: float
|
||||
|
||||
|
||||
class CriteriaOut(Schema):
|
||||
name: str
|
||||
slug: str
|
||||
max_value: int
|
||||
min_value: int
|
||||
|
||||
|
||||
class SubmissionOut(ModelSchema):
|
||||
id: UUID
|
||||
status: Literal["sent", "checking", "checked"]
|
||||
review_status: Literal["not_checked", "checked", "checking"]
|
||||
evaluation: list[CriteriaMarkOut] | None = None
|
||||
criteries: list[CriteriaOut] | None = None
|
||||
submitted_at: datetime = Field(..., alias="timestamp")
|
||||
|
||||
@staticmethod
|
||||
def resolve_criteries(self, context) -> list[CriteriaOut] | None:
|
||||
criteries = self.task.criteries
|
||||
return criteries
|
||||
|
||||
@staticmethod
|
||||
def resolve_evaluation(self, context) -> list[CriteriaMarkOut] | None:
|
||||
if not (
|
||||
review := Review.objects.filter(
|
||||
reviewer=context.get("request").auth, submission=self
|
||||
).first()
|
||||
):
|
||||
return None
|
||||
return review.evaluation
|
||||
|
||||
@staticmethod
|
||||
def resolve_review_status(self, context):
|
||||
reviewer = context.get("request").auth
|
||||
if not (
|
||||
review := Review.objects.filter(
|
||||
reviewer=reviewer, submission=self
|
||||
).first()
|
||||
):
|
||||
return ReviewStatusChoices.NOT_CHECKED.value
|
||||
return review.state
|
||||
|
||||
class Meta:
|
||||
model = CompetitionTaskSubmission
|
||||
exclude = ("user",)
|
||||
fields = (
|
||||
"id",
|
||||
"task",
|
||||
"content",
|
||||
"stdout",
|
||||
"result",
|
||||
"earned_points",
|
||||
"reviewed_at",
|
||||
)
|
||||
|
||||
|
||||
class CriteriaMarkIn(Schema):
|
||||
slug: str
|
||||
mark: float
|
||||
|
||||
|
||||
class EvaluationIn(Schema):
|
||||
evaluation: list[CriteriaMarkIn]
|
||||
|
||||
|
||||
class SubmissionsOut(Schema):
|
||||
submissions: list = None
|
||||
submissions: list[SubmissionOut | None] = []
|
||||
|
||||
@staticmethod
|
||||
def resolve_submissions(self, context) -> list[SubmissionOut]:
|
||||
return list(
|
||||
Review.objects.filter(reviewer=context.get("request").auth)
|
||||
def resolve_submissions(self, context) -> list[SubmissionOut | None]:
|
||||
submissions = list(
|
||||
CompetitionTaskSubmission.objects.filter(
|
||||
reviews__reviewer=context.get("request").auth
|
||||
)
|
||||
)
|
||||
return submissions
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
from datetime import datetime
|
||||
from http import HTTPStatus as status
|
||||
from uuid import UUID
|
||||
|
||||
@@ -7,31 +8,19 @@ from ninja import Router
|
||||
|
||||
from api.v1 import schemas as global_schemas
|
||||
from api.v1.review import schemas
|
||||
from apps.review.models import Review, ReviewStatusChoices
|
||||
from apps.task.models import CompetitionTaskSubmission
|
||||
|
||||
router = Router(tags=["review"])
|
||||
|
||||
|
||||
@router.get(
|
||||
"{token}/submissions",
|
||||
response={
|
||||
status.OK: schemas.SubmissionsOut,
|
||||
},
|
||||
description="Список отправок, на проверку которых назначен ревьюер",
|
||||
)
|
||||
def get_submissions(
|
||||
request: HttpRequest, token: str
|
||||
) -> tuple[status, schemas.SubmissionsOut]:
|
||||
return status.OK, schemas.SubmissionsOut()
|
||||
|
||||
|
||||
@router.get(
|
||||
"{token}",
|
||||
response={
|
||||
status.OK: schemas.ReviewerOut,
|
||||
status.UNAUTHORIZED: global_schemas.UnauthorizedError,
|
||||
},
|
||||
description="token есть и в сваггер авторизации, но оно не работает, не верьте. подставляйте токен вручную в query",
|
||||
description="token есть и в сваггер авторизации, но оно не работает, не верьте. подставляйте токен вручную в path",
|
||||
)
|
||||
def get_reviewer_profile(request: HttpRequest, token: str):
|
||||
return status.OK, request.auth
|
||||
@@ -47,4 +36,56 @@ def get_submission(
|
||||
request: HttpRequest, token: str, submition_id: UUID
|
||||
) -> tuple[status, schemas.SubmissionsOut]:
|
||||
submission = get_object_or_404(CompetitionTaskSubmission, id=submition_id)
|
||||
reviewer = request.auth
|
||||
|
||||
review = Review.objects.get(reviewer=reviewer, submission=submission)
|
||||
if review.state == ReviewStatusChoices.NOT_CHECKED.value:
|
||||
review.state = ReviewStatusChoices.CHECKING.value
|
||||
review.save()
|
||||
|
||||
return status.OK, submission
|
||||
|
||||
|
||||
@router.get(
|
||||
"{token}/submissions",
|
||||
response={
|
||||
status.OK: schemas.SubmissionsOut,
|
||||
},
|
||||
description="Список отправок, на проверку которых назначен ревьюер",
|
||||
)
|
||||
def get_submissions(
|
||||
request: HttpRequest, token: str
|
||||
) -> tuple[status, schemas.SubmissionsOut]:
|
||||
return status.OK, schemas.SubmissionsOut()
|
||||
|
||||
|
||||
@router.post(
|
||||
"{token}/submissions/{submition_id}/evaluate",
|
||||
response={
|
||||
status.OK: schemas.SubmissionOut,
|
||||
},
|
||||
description="Оценка посылки. В body отправляется список с slug критерия и оценкой по этому критерию",
|
||||
)
|
||||
def evaluate_submission(
|
||||
request: HttpRequest,
|
||||
token: str,
|
||||
submition_id: UUID,
|
||||
evaluation_info: schemas.EvaluationIn,
|
||||
) -> tuple[status, schemas.SubmissionsOut]:
|
||||
submission = get_object_or_404(CompetitionTaskSubmission, id=submition_id)
|
||||
reviewer = request.auth
|
||||
|
||||
review = Review.objects.get(reviewer=reviewer, submission=submission)
|
||||
evaluation = evaluation_info.dict()["evaluation"]
|
||||
review.evaluation = evaluation
|
||||
review.state = ReviewStatusChoices.CHECKED.value
|
||||
review.submission.reviewed_at = datetime.now()
|
||||
|
||||
points = 0
|
||||
for criterea in evaluation:
|
||||
points += criterea["mark"]
|
||||
review.submission.earned_points = points
|
||||
|
||||
review.save()
|
||||
|
||||
return status.OK, review.submission
|
||||
|
||||
@@ -6,7 +6,12 @@ from ninja import Router
|
||||
from ninja.errors import AuthenticationError
|
||||
|
||||
from api.v1.auth import BearerAuth
|
||||
from api.v1.schemas import BadRequestError, ForbiddenError, NotFoundError, ConflictError
|
||||
from api.v1.schemas import (
|
||||
BadRequestError,
|
||||
ConflictError,
|
||||
ForbiddenError,
|
||||
NotFoundError,
|
||||
)
|
||||
from api.v1.user.schemas import (
|
||||
LoginSchema,
|
||||
RegisterSchema,
|
||||
|
||||
Reference in New Issue
Block a user