Skip to content

Commit

Permalink
Merge pull request #443 from PROCOLLAB-github/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
sh1nkey authored Sep 30, 2024
2 parents 358a113 + 8531bb5 commit 4fe424f
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 177 deletions.
5 changes: 3 additions & 2 deletions chats/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
ProjectChatMessage,
)
from files.serializers import UserFileSerializer
from users.serializers import UserListSerializer, UserDetailSerializer
from users.serializers import UserListSerializer, UserDetailSerializer, UserChatSerializer


class DirectChatListSerializer(serializers.ModelSerializer):
Expand Down Expand Up @@ -128,7 +128,8 @@ class Meta:


class DirectChatMessageListSerializer(serializers.ModelSerializer):
author = UserDetailSerializer()
# author = UserDetailSerializer()
author = UserChatSerializer()
reply_to = DirectChatMessageSerializer(allow_null=True)
files = serializers.SerializerMethodField()

Expand Down
76 changes: 33 additions & 43 deletions project_rates/serializers.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
from rest_framework import serializers

from core.services import get_views_count
from .models import Criteria, ProjectScore
from projects.models import Project
from .models import Criteria, ProjectScore
from .typing import CriteriasResponse, ProjectScoresResponse
from .validators import ProjectScoreValidator


Expand Down Expand Up @@ -40,14 +41,26 @@ class Meta:


class ProjectScoreSerializer(serializers.ModelSerializer):
criteria = CriteriaSerializer()

class Meta:
model = ProjectScore
fields = ["criteria_id", "project_id", "value"]
fields = [
"criteria",
"value",
]

def to_representation(self, instance):
"""For a 'flat' structure without nesting."""
representation = super().to_representation(instance)
criteria_data = representation.pop("criteria")
return {**criteria_data, **representation}


class ProjectScoreGetSerializer(serializers.ModelSerializer):
views_count = serializers.SerializerMethodField(method_name="count_views")
class ProjectListForRateSerializer(serializers.ModelSerializer):
views_count = serializers.SerializerMethodField()
criterias = serializers.SerializerMethodField()
scored = serializers.SerializerMethodField()

class Meta:
model = Project
Expand All @@ -61,45 +74,22 @@ class Meta:
"industry",
"region",
"views_count",
"scored",
"criterias",
]

def get_criterias(self, obj):
criterias = []
for criteria in self.context["data_criterias"]:
copied_criteria = criteria.copy()
for score in self.context["data_scores"]:
if (
criteria["id"] == score["criteria_id"]
and obj.id == score["project_id"]
):
copied_criteria["value"] = score["value"]

criterias.append(copied_criteria)
return criterias

@classmethod
def count_views(cls, project):
return get_views_count(project)


class ScoredProjectsSerializer(ProjectScoreGetSerializer):
scores_count = serializers.IntegerField()

class Meta(ProjectScoreGetSerializer.Meta):
fields = ProjectScoreGetSerializer.Meta.fields + ["scores_count"]


def serialize_data_func(criteria_to_get: list, data: dict):
criteria = Criteria.objects.in_bulk(criteria_to_get)

for criterion in data:
needed_criteria = criteria.get(int(criterion["criterion_id"]))

ProjectScoreValidator(
criteria_type=needed_criteria.type,
value=criterion["value"],
criteria_min_value=needed_criteria.min_value,
criteria_max_value=needed_criteria.max_value,
)
criterion["criteria_id"] = criterion.pop("criterion_id")
def get_views_count(self, obj) -> int:
return get_views_count(obj)

def get_criterias(self, obj) -> CriteriasResponse | ProjectScoresResponse:
program_id = self.context["view"].kwargs.get("program_id")
if obj.scored:
scores = ProjectScore.objects.filter(project=obj).select_related("criteria")
serializer = ProjectScoreSerializer(scores, many=True)
else:
cirterias = Criteria.objects.filter(partner_program__id=program_id)
serializer = CriteriaSerializer(cirterias, many=True)
return serializer.data

def get_scored(self, obj) -> bool:
return bool(obj.scored)
70 changes: 0 additions & 70 deletions project_rates/services.py

This file was deleted.

14 changes: 14 additions & 0 deletions project_rates/typing.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from typing import TypedDict


class CriteriasResponse(TypedDict):
id: int
name: str
description: str
type: str
min_value: int | float | None
max_value: int | float | None


class ProjectScoresResponse(CriteriasResponse):
value: str
6 changes: 2 additions & 4 deletions project_rates/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,10 @@

from project_rates.views import (
RateProject,
RateProjects,
RateProjectsDetails,
ProjectListForRate,
)

urlpatterns = [
path("rate/<int:project_id>", RateProject.as_view()),
path("<int:program_id>", RateProjects.as_view()),
path("details", RateProjectsDetails.as_view()),
path("<int:program_id>", ProjectListForRate.as_view()),
]
79 changes: 21 additions & 58 deletions project_rates/views.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
from django.contrib.auth import get_user_model
from django.db.models import QuerySet
from django.db.models import QuerySet, Count

from rest_framework import generics, status
from rest_framework.response import Response

from project_rates.constants import RatesRequestData
from project_rates.services import (
get_querysets,
serialize_project_criterias,
count_scored_criterias,
)
from django_filters import rest_framework as filters

from partner_programs.models import PartnerProgramUserProfile
from projects.models import Project
from projects.filters import ProjectFilter
from project_rates.models import ProjectScore
from project_rates.pagination import RateProjectsPagination
from project_rates.serializers import (
ProjectScoreCreateSerializer,
ProjectScoreGetSerializer,
ProjectListForRateSerializer,
)
from users.models import Expert
from users.permissions import IsExpert, IsExpertPost
Expand Down Expand Up @@ -70,57 +69,21 @@ def create(self, request, *args, **kwargs) -> Response:
return Response({"error": str(e)}, status=status.HTTP_400_BAD_REQUEST)


class RateProjects(generics.ListAPIView):
serializer_class = ProjectScoreGetSerializer
class ProjectListForRate(generics.ListAPIView):
permission_classes = [IsExpert]
serializer_class = ProjectListForRateSerializer
filter_backends = [filters.DjangoFilterBackend]
filterset_class = ProjectFilter
pagination_class = RateProjectsPagination

def get_request_data(self) -> RatesRequestData:
scored = True if self.request.query_params.get("scored") == "true" else False

return RatesRequestData(
program_id=self.kwargs.get("program_id"),
user=self.request.user,
view=self,
scored=scored,
def get_queryset(self) -> QuerySet[Project]:
projects_ids = PartnerProgramUserProfile.objects.filter(
project__isnull=False,
partner_program__id=self.kwargs.get("program_id")
).values_list("project__id", flat=True)
# `Count` the easiest way to check for rate exist (0 -> does not exist).
return (
Project.objects
.filter(draft=False, id__in=projects_ids)
.annotate(scored=Count("scores"))
)

def get_querysets_dict(self) -> dict[str, QuerySet]:
return get_querysets(self.get_request_data())

def serialize_querysets(self) -> list[dict]:
return serialize_project_criterias(self.get_querysets_dict())

def get(self, request, *args, **kwargs) -> Response:
serialized_data = self.serialize_querysets()

if self.request.query_params.get("scored") == "true":
[project.update({"is_scored": True}) for project in serialized_data]
else:
[count_scored_criterias(project) for project in serialized_data]

return self.get_paginated_response(serialized_data)


class RateProjectsDetails(RateProjects):
permission_classes = [IsExpertPost] # потом решить проблему с этим

def get_request_data(self) -> RatesRequestData:
request_data = super().get_request_data()

project_id = self.request.query_params.get("project_id")
program_id = self.request.query_params.get("program_id")

request_data.project_id = int(project_id) if project_id else None
request_data.program_id = int(program_id) if program_id else None
return request_data

def get(self, request, *args, **kwargs):
try:
serialized_data = self.serialize_querysets()[0]

count_scored_criterias(serialized_data)

return Response(serialized_data, status=status.HTTP_200_OK)
except Exception as e:
return Response({"error": str(e)}, status=status.HTTP_400_BAD_REQUEST)
23 changes: 23 additions & 0 deletions users/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -502,6 +502,29 @@ def _update_user_education(self, instance: CustomUser, data: list[dict]) -> None
])


class UserChatSerializer(serializers.ModelSerializer[CustomUser]):
is_online = serializers.SerializerMethodField()

def get_is_online(self, user: CustomUser):
request = self.context.get("request")
if request and request.user.is_authenticated and request.user.id == user.id:
return True
cache_key = get_user_online_cache_key(user)
return cache.get(cache_key, False)

class Meta:
model = CustomUser
fields = [
"id",
"first_name",
"last_name",
"patronymic",
"avatar",
"is_active",
"is_online",
]


class UserListSerializer(
serializers.ModelSerializer[CustomUser], SkillsWriteSerializerMixin
):
Expand Down

0 comments on commit 4fe424f

Please sign in to comment.