From fb165d080e043985dec6c89fd0a5e7460fc5b476 Mon Sep 17 00:00:00 2001 From: pablohashescobar <118773738+pablohashescobar@users.noreply.github.com> Date: Thu, 11 May 2023 16:56:48 +0530 Subject: [PATCH] feat: estimate points data in cycles list endpoint (#1015) * feat: estimate points data in cycles list endpoint * dev: prefetch for assignees * dev: update sum for estimate points --- apiserver/plane/api/serializers/cycle.py | 5 +- apiserver/plane/api/views/cycle.py | 101 +++++++++++++++++++---- 2 files changed, 91 insertions(+), 15 deletions(-) diff --git a/apiserver/plane/api/serializers/cycle.py b/apiserver/plane/api/serializers/cycle.py index d6d281357..5c1c68fb8 100644 --- a/apiserver/plane/api/serializers/cycle.py +++ b/apiserver/plane/api/serializers/cycle.py @@ -19,7 +19,10 @@ class CycleSerializer(BaseSerializer): started_issues = serializers.IntegerField(read_only=True) unstarted_issues = serializers.IntegerField(read_only=True) backlog_issues = serializers.IntegerField(read_only=True) - assignees = serializers.SerializerMethodField() + assignees = serializers.SerializerMethodField(read_only=True) + total_estimates = serializers.IntegerField(read_only=True) + completed_estimates = serializers.IntegerField(read_only=True) + started_estimates = serializers.IntegerField(read_only=True) workspace_detail = WorkspaceLiteSerializer(read_only=True, source="workspace") project_detail = ProjectLiteSerializer(read_only=True, source="project") diff --git a/apiserver/plane/api/views/cycle.py b/apiserver/plane/api/views/cycle.py index f61a93487..ee85f22e1 100644 --- a/apiserver/plane/api/views/cycle.py +++ b/apiserver/plane/api/views/cycle.py @@ -3,7 +3,7 @@ import json # Django imports from django.db import IntegrityError -from django.db.models import OuterRef, Func, F, Q, Exists, OuterRef, Count, Prefetch +from django.db.models import OuterRef, Func, F, Q, Exists, OuterRef, Count, Prefetch, Sum from django.core import serializers from django.utils import timezone from django.utils.decorators import method_decorator @@ -24,13 +24,13 @@ from plane.api.serializers import ( ) from plane.api.permissions import ProjectEntityPermission from plane.db.models import ( + User, Cycle, CycleIssue, Issue, CycleFavorite, IssueLink, IssueAttachment, - User, ) from plane.bgtasks.issue_activites_task import issue_activity from plane.utils.grouper import group_results @@ -119,6 +119,25 @@ class CycleViewSet(BaseViewSet): filter=Q(issue_cycle__issue__state__group="backlog"), ) ) + .annotate(total_estimates=Sum("issue_cycle__issue__estimate_point")) + .annotate( + completed_estimates=Sum( + "issue_cycle__issue__estimate_point", + filter=Q(issue_cycle__issue__state__group="completed"), + ) + ) + .annotate( + started_estimates=Sum( + "issue_cycle__issue__estimate_point", + filter=Q(issue_cycle__issue__state__group="started"), + ) + ) + .prefetch_related( + Prefetch( + "issue_cycle__issue__assignees", + queryset=User.objects.only("avatar", "first_name", "id").distinct(), + ) + ) .order_by("-is_favorite", "name") .distinct() ) @@ -414,11 +433,10 @@ class CycleDateCheckEndpoint(BaseAPIView): try: start_date = request.data.get("start_date", False) end_date = request.data.get("end_date", False) - cycle_id = request.data.get("cycle_id", False) if not start_date or not end_date: return Response( - {"error": "Start date and end date are required"}, + {"error": "Start date and end date both are required"}, status=status.HTTP_400_BAD_REQUEST, ) @@ -430,11 +448,6 @@ class CycleDateCheckEndpoint(BaseAPIView): project_id=project_id, ) - if cycle_id: - cycles = cycles.filter( - ~Q(pk=cycle_id), - ) - if cycles.exists(): return Response( { @@ -508,10 +521,25 @@ class CurrentUpcomingCyclesEndpoint(BaseAPIView): filter=Q(issue_cycle__issue__state__group="backlog"), ) ) + .annotate(total_estimates=Sum("issue_cycle__issue__estimate_point")) + .annotate( + completed_estimates=Sum( + "issue_cycle__issue__estimate_point", + filter=Q(issue_cycle__issue__state__group="completed"), + ) + ) + .annotate( + started_estimates=Sum( + "issue_cycle__issue__estimate_point", + filter=Q(issue_cycle__issue__state__group="started"), + ) + ) .prefetch_related( Prefetch( "issue_cycle__issue__assignees", - queryset=User.objects.only("avatar", "first_name", "id").distinct(), + queryset=User.objects.only( + "avatar", "first_name", "id" + ).distinct(), ) ) .order_by("name", "-is_favorite") @@ -558,10 +586,25 @@ class CurrentUpcomingCyclesEndpoint(BaseAPIView): filter=Q(issue_cycle__issue__state__group="backlog"), ) ) + .annotate(total_estimates=Sum("issue_cycle__issue__estimate_point")) + .annotate( + completed_estimates=Sum( + "issue_cycle__issue__estimate_point", + filter=Q(issue_cycle__issue__state__group="completed"), + ) + ) + .annotate( + started_estimates=Sum( + "issue_cycle__issue__estimate_point", + filter=Q(issue_cycle__issue__state__group="started"), + ) + ) .prefetch_related( Prefetch( "issue_cycle__issue__assignees", - queryset=User.objects.only("avatar", "first_name", "id").distinct(), + queryset=User.objects.only( + "avatar", "first_name", "id" + ).distinct(), ) ) .order_by("name", "-is_favorite") @@ -576,7 +619,7 @@ class CurrentUpcomingCyclesEndpoint(BaseAPIView): ) except Exception as e: - print(e) + capture_exception(e) return Response( {"error": "Something went wrong please try again later"}, status=status.HTTP_400_BAD_REQUEST, @@ -637,10 +680,25 @@ class CompletedCyclesEndpoint(BaseAPIView): filter=Q(issue_cycle__issue__state__group="backlog"), ) ) + .annotate(total_estimates=Sum("issue_cycle__issue__estimate_point")) + .annotate( + completed_estimates=Sum( + "issue_cycle__issue__estimate_point", + filter=Q(issue_cycle__issue__state__group="completed"), + ) + ) + .annotate( + started_estimates=Sum( + "issue_cycle__issue__estimate_point", + filter=Q(issue_cycle__issue__state__group="started"), + ) + ) .prefetch_related( Prefetch( "issue_cycle__issue__assignees", - queryset=User.objects.only("avatar", "first_name", "id").distinct(), + queryset=User.objects.only( + "avatar", "first_name", "id" + ).distinct(), ) ) .order_by("name", "-is_favorite") @@ -718,10 +776,25 @@ class DraftCyclesEndpoint(BaseAPIView): filter=Q(issue_cycle__issue__state__group="backlog"), ) ) + .annotate(total_estimates=Sum("issue_cycle__issue__estimate_point")) + .annotate( + completed_estimates=Sum( + "issue_cycle__issue__estimate_point", + filter=Q(issue_cycle__issue__state__group="completed"), + ) + ) + .annotate( + started_estimates=Sum( + "issue_cycle__issue__estimate_point", + filter=Q(issue_cycle__issue__state__group="started"), + ) + ) .prefetch_related( Prefetch( "issue_cycle__issue__assignees", - queryset=User.objects.only("avatar", "first_name", "id").distinct(), + queryset=User.objects.only( + "avatar", "first_name", "id" + ).distinct(), ) ) .order_by("name", "-is_favorite")