-
Notifications
You must be signed in to change notification settings - Fork 0
Project rates finished refactoring #315
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
b6112c1
a5ae5e0
db9ae2c
6b5cac7
1928176
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,26 @@ | ||
| from typing import Literal | ||
| from dataclasses import dataclass | ||
|
|
||
| from rest_framework.generics import ListAPIView | ||
|
|
||
| from users.models import CustomUser | ||
|
|
||
| NumericTypes: list[str] = ["int", "float"] | ||
|
|
||
| ValidatableTypesNames = Literal[*NumericTypes, "bool", "str"] | ||
|
|
||
| VERBOSE_TYPES = ( | ||
| ("str", "Текст"), | ||
| ("int", "Целочисленное число"), | ||
| ("float", "Число с плавающей точкой"), | ||
| ("bool", "Да или нет"), | ||
| ) | ||
|
|
||
|
|
||
| @dataclass | ||
| class RatesRequestData: | ||
| program_id: int | ||
| user: CustomUser | ||
| view: ListAPIView | ||
| scored: bool | None = None | ||
| project_id: int | None = None |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,70 @@ | ||
| from django.db.models import Count, Q, QuerySet | ||
|
|
||
| from project_rates.models import Criteria, ProjectScore | ||
| from project_rates.serializers import ( | ||
| CriteriaSerializer, | ||
| ProjectScoreSerializer, | ||
| ProjectScoreGetSerializer, | ||
| ) | ||
| from projects.models import Project | ||
|
|
||
|
|
||
| def get_querysets(RatesRequestData) -> dict[str, QuerySet]: | ||
| program_id = RatesRequestData.program_id | ||
| project_id = RatesRequestData.project_id | ||
| user = RatesRequestData.user | ||
|
|
||
| criterias = Criteria.objects.prefetch_related("partner_program").filter( | ||
| partner_program_id=program_id | ||
| ) | ||
| scores = ProjectScore.objects.prefetch_related("criteria").filter( | ||
| criteria__in=criterias.values_list("id", flat=True), user=user | ||
| ) | ||
|
|
||
| if project_id: | ||
| projects = [Project.objects.get(id=project_id)] | ||
| else: | ||
| projects = Project.objects.filter( | ||
| partner_program_profiles__partner_program_id=program_id | ||
| ).distinct() | ||
|
|
||
| if RatesRequestData.scored: | ||
| criterias_quantity = len(criterias) | ||
| projects = projects.annotate( | ||
| user_scores_count=Count("scores", filter=Q(scores__user=user)) | ||
| ).filter(user_scores_count=criterias_quantity) | ||
|
|
||
| if not project_id: | ||
| projects = RatesRequestData.view.paginate_queryset(projects) | ||
|
|
||
| return { | ||
yakser marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| "criterias_queryset": criterias, | ||
| "scores_queryset": scores, | ||
| "projects_queryset": projects, | ||
| } | ||
|
|
||
|
|
||
| def serialize_project_criterias(querysets: dict[str, QuerySet]) -> list[dict]: | ||
| criteria_serializer = CriteriaSerializer(querysets["criterias_queryset"], many=True) | ||
| scores_serializer = ProjectScoreSerializer(querysets["scores_queryset"], many=True) | ||
|
|
||
| projects_serializer = ProjectScoreGetSerializer( | ||
| querysets["projects_queryset"], | ||
| context={ | ||
| "data_criterias": criteria_serializer.data, | ||
| "data_scores": scores_serializer.data, | ||
| }, | ||
| many=True, | ||
| ) | ||
| return projects_serializer.data | ||
|
|
||
|
|
||
| def count_scored_criterias(project_data: dict): | ||
| filled_values = sum( | ||
| 1 | ||
| for criteria in project_data["criterias"] | ||
| if criteria["name"] == "Комментарий" or criteria.get("value") | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. не понял логику проверки на заполненность То есть коммент может быть и пустым, но будет считаться как заполненное поле?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. комментарий идее опционален |
||
| ) | ||
|
|
||
| if filled_values == len(project_data["criterias"]): | ||
| project_data["is_scored"] = True | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,32 +1,38 @@ | ||
| class ProjectScoreValidate: | ||
| def __init__(self, **kwargs): | ||
| self.criteria_type = kwargs.get("criteria_type") | ||
| self.value = kwargs.get("value") | ||
| self.criteria_min_value = kwargs.get("criteria_min_value") | ||
| self.criteria_max_value = kwargs.get("criteria_max_value") | ||
| from project_rates.constants import ValidatableTypesNames, NumericTypes | ||
|
|
||
| self._validate_data_type() | ||
| self._validate_numeric_limits() | ||
|
|
||
| def _validate_data_type(self): | ||
| if self.criteria_type in ["float", "int"]: | ||
| class ProjectScoreValidator: | ||
| @classmethod | ||
| def validate(cls, **kwargs): | ||
| criteria_type: ValidatableTypesNames = kwargs.get("criteria_type") | ||
| value: str = kwargs.get("value") | ||
| criteria_min_value: float | None = kwargs.get("criteria_min_value") | ||
| criteria_max_value: float | None = kwargs.get("criteria_max_value") | ||
|
|
||
| cls._validate_data_type(criteria_type, value) | ||
| if criteria_type in NumericTypes: | ||
| cls._validate_numeric_limits( | ||
| criteria_min_value, criteria_max_value, float(value) | ||
| ) | ||
|
|
||
| @staticmethod | ||
| def _validate_data_type(criteria_type: str, value: str): | ||
| if criteria_type in NumericTypes: | ||
| try: | ||
| float(self.value) | ||
| float(value) | ||
| except ValueError: | ||
| raise ValueError("Введённое значение не соответствует формату!") | ||
| except TypeError: | ||
| raise TypeError("Вы не ввели никакие данные!") | ||
|
|
||
| elif (self.criteria_type == "bool") and (self.value not in ["True", "False"]): | ||
| elif (criteria_type == "bool") and (value not in ["True", "False"]): | ||
| raise TypeError("Введённое значение не соответствует формату!") | ||
|
|
||
| def _validate_numeric_limits(self): | ||
| if self.criteria_type in ["int", "float"]: | ||
| if self.criteria_min_value is not None and self.criteria_min_value > float( | ||
| self.value | ||
| ): | ||
| raise ValueError("Оценка этого критерия принизила допустимые значения!") | ||
| elif self.criteria_max_value is not None and self.criteria_max_value < float( | ||
| self.value | ||
| ): | ||
| raise ValueError("Оценка этого критерия превысила допустимые значения!") | ||
| @staticmethod | ||
| def _validate_numeric_limits( | ||
| min_value: float | None, max_value: float | None, value: float | ||
| ): | ||
| if min_value is not None and min_value > value: | ||
| raise ValueError("Оценка этого критерия ниже допустимого значения!") | ||
| elif max_value is not None and max_value < value: | ||
| raise ValueError("Оценка этого критерия превысила допустимое значение!") |
Uh oh!
There was an error while loading. Please reload this page.