From 9a927ded84ef4352595f68c340651cd2c24f10b9 Mon Sep 17 00:00:00 2001 From: Bavisetti Narayan <72156168+NarayanBavisetti@users.noreply.github.com> Date: Thu, 4 Jul 2024 19:50:08 +0530 Subject: [PATCH] chore: estimate points float field (#5038) --- apiserver/plane/api/views/cycle.py | 14 ++--- apiserver/plane/app/serializers/module.py | 12 ++--- apiserver/plane/app/views/cycle/base.py | 62 +++++++++++------------ apiserver/plane/app/views/module/base.py | 37 +++++++------- apiserver/plane/utils/analytics_plot.py | 24 ++++++--- 5 files changed, 81 insertions(+), 68 deletions(-) diff --git a/apiserver/plane/api/views/cycle.py b/apiserver/plane/api/views/cycle.py index 9e7be5180..a95a4d5f4 100644 --- a/apiserver/plane/api/views/cycle.py +++ b/apiserver/plane/api/views/cycle.py @@ -12,7 +12,7 @@ from django.db.models import ( OuterRef, Q, Sum, - IntegerField, + FloatField, ) from django.db.models.functions import Cast @@ -867,12 +867,12 @@ class TransferCycleIssueAPIEndpoint(BaseAPIView): .values("display_name", "assignee_id", "avatar") .annotate( total_estimates=Sum( - Cast("estimate_point__value", IntegerField()) + Cast("estimate_point__value", FloatField()) ) ) .annotate( completed_estimates=Sum( - Cast("estimate_point__value", IntegerField()), + Cast("estimate_point__value", FloatField()), filter=Q( completed_at__isnull=False, archived_at__isnull=True, @@ -882,7 +882,7 @@ class TransferCycleIssueAPIEndpoint(BaseAPIView): ) .annotate( pending_estimates=Sum( - Cast("estimate_point__value", IntegerField()), + Cast("estimate_point__value", FloatField()), filter=Q( completed_at__isnull=True, archived_at__isnull=True, @@ -921,12 +921,12 @@ class TransferCycleIssueAPIEndpoint(BaseAPIView): .values("label_name", "color", "label_id") .annotate( total_estimates=Sum( - Cast("estimate_point__value", IntegerField()) + Cast("estimate_point__value", FloatField()) ) ) .annotate( completed_estimates=Sum( - Cast("estimate_point__value", IntegerField()), + Cast("estimate_point__value", FloatField()), filter=Q( completed_at__isnull=False, archived_at__isnull=True, @@ -936,7 +936,7 @@ class TransferCycleIssueAPIEndpoint(BaseAPIView): ) .annotate( pending_estimates=Sum( - Cast("estimate_point__value", IntegerField()), + Cast("estimate_point__value", FloatField()), filter=Q( completed_at__isnull=True, archived_at__isnull=True, diff --git a/apiserver/plane/app/serializers/module.py b/apiserver/plane/app/serializers/module.py index bb759784e..222c95150 100644 --- a/apiserver/plane/app/serializers/module.py +++ b/apiserver/plane/app/serializers/module.py @@ -177,8 +177,8 @@ class ModuleSerializer(DynamicBaseSerializer): started_issues = serializers.IntegerField(read_only=True) unstarted_issues = serializers.IntegerField(read_only=True) backlog_issues = serializers.IntegerField(read_only=True) - total_estimate_points = serializers.IntegerField(read_only=True) - completed_estimate_points = serializers.IntegerField(read_only=True) + total_estimate_points = serializers.FloatField(read_only=True) + completed_estimate_points = serializers.FloatField(read_only=True) class Meta: model = Module @@ -222,10 +222,10 @@ class ModuleSerializer(DynamicBaseSerializer): class ModuleDetailSerializer(ModuleSerializer): link_module = ModuleLinkSerializer(read_only=True, many=True) sub_issues = serializers.IntegerField(read_only=True) - backlog_estimate_points = serializers.IntegerField(read_only=True) - unstarted_estimate_points = serializers.IntegerField(read_only=True) - started_estimate_points = serializers.IntegerField(read_only=True) - cancelled_estimate_points = serializers.IntegerField(read_only=True) + backlog_estimate_points = serializers.FloatField(read_only=True) + unstarted_estimate_points = serializers.FloatField(read_only=True) + started_estimate_points = serializers.FloatField(read_only=True) + cancelled_estimate_points = serializers.FloatField(read_only=True) class Meta(ModuleSerializer.Meta): fields = ModuleSerializer.Meta.fields + ["link_module", "sub_issues", "backlog_estimate_points", "unstarted_estimate_points", "started_estimate_points", "cancelled_estimate_points"] diff --git a/apiserver/plane/app/views/cycle/base.py b/apiserver/plane/app/views/cycle/base.py index 2fbdc33e6..65d65e525 100644 --- a/apiserver/plane/app/views/cycle/base.py +++ b/apiserver/plane/app/views/cycle/base.py @@ -19,7 +19,7 @@ from django.db.models import ( When, Subquery, Sum, - IntegerField, + FloatField, ) from django.db.models.functions import Coalesce, Cast from django.utils import timezone @@ -86,7 +86,7 @@ class CycleViewSet(BaseViewSet): .values("issue_cycle__cycle_id") .annotate( backlog_estimate_point=Sum( - Cast("estimate_point__value", IntegerField()) + Cast("estimate_point__value", FloatField()) ) ) .values("backlog_estimate_point")[:1] @@ -100,7 +100,7 @@ class CycleViewSet(BaseViewSet): .values("issue_cycle__cycle_id") .annotate( unstarted_estimate_point=Sum( - Cast("estimate_point__value", IntegerField()) + Cast("estimate_point__value", FloatField()) ) ) .values("unstarted_estimate_point")[:1] @@ -114,7 +114,7 @@ class CycleViewSet(BaseViewSet): .values("issue_cycle__cycle_id") .annotate( started_estimate_point=Sum( - Cast("estimate_point__value", IntegerField()) + Cast("estimate_point__value", FloatField()) ) ) .values("started_estimate_point")[:1] @@ -128,7 +128,7 @@ class CycleViewSet(BaseViewSet): .values("issue_cycle__cycle_id") .annotate( cancelled_estimate_point=Sum( - Cast("estimate_point__value", IntegerField()) + Cast("estimate_point__value", FloatField()) ) ) .values("cancelled_estimate_point")[:1] @@ -142,7 +142,7 @@ class CycleViewSet(BaseViewSet): .values("issue_cycle__cycle_id") .annotate( completed_estimate_points=Sum( - Cast("estimate_point__value", IntegerField()) + Cast("estimate_point__value", FloatField()) ) ) .values("completed_estimate_points")[:1] @@ -155,7 +155,7 @@ class CycleViewSet(BaseViewSet): .values("issue_cycle__cycle_id") .annotate( total_estimate_points=Sum( - Cast("estimate_point__value", IntegerField()) + Cast("estimate_point__value", FloatField()) ) ) .values("total_estimate_points")[:1] @@ -287,37 +287,37 @@ class CycleViewSet(BaseViewSet): .annotate( backlog_estimate_points=Coalesce( Subquery(backlog_estimate_point), - Value(0, output_field=IntegerField()), + Value(0, output_field=FloatField()), ), ) .annotate( unstarted_estimate_points=Coalesce( Subquery(unstarted_estimate_point), - Value(0, output_field=IntegerField()), + Value(0, output_field=FloatField()), ), ) .annotate( started_estimate_points=Coalesce( Subquery(started_estimate_point), - Value(0, output_field=IntegerField()), + Value(0, output_field=FloatField()), ), ) .annotate( cancelled_estimate_points=Coalesce( Subquery(cancelled_estimate_point), - Value(0, output_field=IntegerField()), + Value(0, output_field=FloatField()), ), ) .annotate( completed_estimate_points=Coalesce( Subquery(completed_estimate_point), - Value(0, output_field=IntegerField()), + Value(0, output_field=FloatField()), ), ) .annotate( total_estimate_points=Coalesce( Subquery(total_estimate_point), - Value(0, output_field=IntegerField()), + Value(0, output_field=FloatField()), ), ) .order_by("-is_favorite", "name") @@ -395,12 +395,12 @@ class CycleViewSet(BaseViewSet): .values("display_name", "assignee_id", "avatar") .annotate( total_estimates=Sum( - Cast("estimate_point__value", IntegerField()) + Cast("estimate_point__value", FloatField()) ) ) .annotate( completed_estimates=Sum( - Cast("estimate_point__value", IntegerField()), + Cast("estimate_point__value", FloatField()), filter=Q( completed_at__isnull=False, archived_at__isnull=True, @@ -410,7 +410,7 @@ class CycleViewSet(BaseViewSet): ) .annotate( pending_estimates=Sum( - Cast("estimate_point__value", IntegerField()), + Cast("estimate_point__value", FloatField()), filter=Q( completed_at__isnull=True, archived_at__isnull=True, @@ -433,12 +433,12 @@ class CycleViewSet(BaseViewSet): .values("label_name", "color", "label_id") .annotate( total_estimates=Sum( - Cast("estimate_point__value", IntegerField()) + Cast("estimate_point__value", FloatField()) ) ) .annotate( completed_estimates=Sum( - Cast("estimate_point__value", IntegerField()), + Cast("estimate_point__value", FloatField()), filter=Q( completed_at__isnull=False, archived_at__isnull=True, @@ -448,7 +448,7 @@ class CycleViewSet(BaseViewSet): ) .annotate( pending_estimates=Sum( - Cast("estimate_point__value", IntegerField()), + Cast("estimate_point__value", FloatField()), filter=Q( completed_at__isnull=True, archived_at__isnull=True, @@ -836,12 +836,12 @@ class CycleViewSet(BaseViewSet): .values("display_name", "assignee_id", "avatar") .annotate( total_estimates=Sum( - Cast("estimate_point__value", IntegerField()) + Cast("estimate_point__value", FloatField()) ) ) .annotate( completed_estimates=Sum( - Cast("estimate_point__value", IntegerField()), + Cast("estimate_point__value", FloatField()), filter=Q( completed_at__isnull=False, archived_at__isnull=True, @@ -851,7 +851,7 @@ class CycleViewSet(BaseViewSet): ) .annotate( pending_estimates=Sum( - Cast("estimate_point__value", IntegerField()), + Cast("estimate_point__value", FloatField()), filter=Q( completed_at__isnull=True, archived_at__isnull=True, @@ -874,12 +874,12 @@ class CycleViewSet(BaseViewSet): .values("label_name", "color", "label_id") .annotate( total_estimates=Sum( - Cast("estimate_point__value", IntegerField()) + Cast("estimate_point__value", FloatField()) ) ) .annotate( completed_estimates=Sum( - Cast("estimate_point__value", IntegerField()), + Cast("estimate_point__value", FloatField()), filter=Q( completed_at__isnull=False, archived_at__isnull=True, @@ -889,7 +889,7 @@ class CycleViewSet(BaseViewSet): ) .annotate( pending_estimates=Sum( - Cast("estimate_point__value", IntegerField()), + Cast("estimate_point__value", FloatField()), filter=Q( completed_at__isnull=True, archived_at__isnull=True, @@ -1234,12 +1234,12 @@ class TransferCycleIssueEndpoint(BaseAPIView): .values("display_name", "assignee_id", "avatar") .annotate( total_estimates=Sum( - Cast("estimate_point__value", IntegerField()) + Cast("estimate_point__value", FloatField()) ) ) .annotate( completed_estimates=Sum( - Cast("estimate_point__value", IntegerField()), + Cast("estimate_point__value", FloatField()), filter=Q( completed_at__isnull=False, archived_at__isnull=True, @@ -1249,7 +1249,7 @@ class TransferCycleIssueEndpoint(BaseAPIView): ) .annotate( pending_estimates=Sum( - Cast("estimate_point__value", IntegerField()), + Cast("estimate_point__value", FloatField()), filter=Q( completed_at__isnull=True, archived_at__isnull=True, @@ -1288,12 +1288,12 @@ class TransferCycleIssueEndpoint(BaseAPIView): .values("label_name", "color", "label_id") .annotate( total_estimates=Sum( - Cast("estimate_point__value", IntegerField()) + Cast("estimate_point__value", FloatField()) ) ) .annotate( completed_estimates=Sum( - Cast("estimate_point__value", IntegerField()), + Cast("estimate_point__value", FloatField()), filter=Q( completed_at__isnull=False, archived_at__isnull=True, @@ -1303,7 +1303,7 @@ class TransferCycleIssueEndpoint(BaseAPIView): ) .annotate( pending_estimates=Sum( - Cast("estimate_point__value", IntegerField()), + Cast("estimate_point__value", FloatField()), filter=Q( completed_at__isnull=True, archived_at__isnull=True, diff --git a/apiserver/plane/app/views/module/base.py b/apiserver/plane/app/views/module/base.py index ca0f56283..084204595 100644 --- a/apiserver/plane/app/views/module/base.py +++ b/apiserver/plane/app/views/module/base.py @@ -17,6 +17,7 @@ from django.db.models import ( UUIDField, Value, Sum, + FloatField, ) from django.db.models.functions import Coalesce, Cast from django.core.serializers.json import DjangoJSONEncoder @@ -138,7 +139,7 @@ class ModuleViewSet(BaseViewSet): .values("issue_module__module_id") .annotate( completed_estimate_points=Sum( - Cast("estimate_point__value", IntegerField()) + Cast("estimate_point__value", FloatField()) ) ) .values("completed_estimate_points")[:1] @@ -152,7 +153,7 @@ class ModuleViewSet(BaseViewSet): .values("issue_module__module_id") .annotate( total_estimate_points=Sum( - Cast("estimate_point__value", IntegerField()) + Cast("estimate_point__value", FloatField()) ) ) .values("total_estimate_points")[:1] @@ -166,7 +167,7 @@ class ModuleViewSet(BaseViewSet): .values("issue_module__module_id") .annotate( backlog_estimate_point=Sum( - Cast("estimate_point__value", IntegerField()) + Cast("estimate_point__value", FloatField()) ) ) .values("backlog_estimate_point")[:1] @@ -180,7 +181,7 @@ class ModuleViewSet(BaseViewSet): .values("issue_module__module_id") .annotate( unstarted_estimate_point=Sum( - Cast("estimate_point__value", IntegerField()) + Cast("estimate_point__value", FloatField()) ) ) .values("unstarted_estimate_point")[:1] @@ -194,7 +195,7 @@ class ModuleViewSet(BaseViewSet): .values("issue_module__module_id") .annotate( started_estimate_point=Sum( - Cast("estimate_point__value", IntegerField()) + Cast("estimate_point__value", FloatField()) ) ) .values("started_estimate_point")[:1] @@ -208,7 +209,7 @@ class ModuleViewSet(BaseViewSet): .values("issue_module__module_id") .annotate( cancelled_estimate_point=Sum( - Cast("estimate_point__value", IntegerField()) + Cast("estimate_point__value", FloatField()) ) ) .values("cancelled_estimate_point")[:1] @@ -270,37 +271,37 @@ class ModuleViewSet(BaseViewSet): .annotate( backlog_estimate_points=Coalesce( Subquery(backlog_estimate_point), - Value(0, output_field=IntegerField()), + Value(0, output_field=FloatField()), ), ) .annotate( unstarted_estimate_points=Coalesce( Subquery(unstarted_estimate_point), - Value(0, output_field=IntegerField()), + Value(0, output_field=FloatField()), ), ) .annotate( started_estimate_points=Coalesce( Subquery(started_estimate_point), - Value(0, output_field=IntegerField()), + Value(0, output_field=FloatField()), ), ) .annotate( cancelled_estimate_points=Coalesce( Subquery(cancelled_estimate_point), - Value(0, output_field=IntegerField()), + Value(0, output_field=FloatField()), ), ) .annotate( completed_estimate_points=Coalesce( Subquery(completed_estimate_point), - Value(0, output_field=IntegerField()), + Value(0, output_field=FloatField()), ), ) .annotate( total_estimate_points=Coalesce( Subquery(total_estimate_point), - Value(0, output_field=IntegerField()), + Value(0, output_field=FloatField()), ), ) .annotate( @@ -475,12 +476,12 @@ class ModuleViewSet(BaseViewSet): ) .annotate( total_estimates=Sum( - Cast("estimate_point__value", IntegerField()) + Cast("estimate_point__value", FloatField()) ), ) .annotate( completed_estimates=Sum( - Cast("estimate_point__value", IntegerField()), + Cast("estimate_point__value", FloatField()), filter=Q( completed_at__isnull=False, archived_at__isnull=True, @@ -490,7 +491,7 @@ class ModuleViewSet(BaseViewSet): ) .annotate( pending_estimates=Sum( - Cast("estimate_point__value", IntegerField()), + Cast("estimate_point__value", FloatField()), filter=Q( completed_at__isnull=True, archived_at__isnull=True, @@ -513,12 +514,12 @@ class ModuleViewSet(BaseViewSet): .values("label_name", "color", "label_id") .annotate( total_estimates=Sum( - Cast("estimate_point__value", IntegerField()) + Cast("estimate_point__value", FloatField()) ), ) .annotate( completed_estimates=Sum( - Cast("estimate_point__value", IntegerField()), + Cast("estimate_point__value", FloatField()), filter=Q( completed_at__isnull=False, archived_at__isnull=True, @@ -528,7 +529,7 @@ class ModuleViewSet(BaseViewSet): ) .annotate( pending_estimates=Sum( - Cast("estimate_point__value", IntegerField()), + Cast("estimate_point__value", FloatField()), filter=Q( completed_at__isnull=True, archived_at__isnull=True, diff --git a/apiserver/plane/utils/analytics_plot.py b/apiserver/plane/utils/analytics_plot.py index 59ddbd933..0d2564a04 100644 --- a/apiserver/plane/utils/analytics_plot.py +++ b/apiserver/plane/utils/analytics_plot.py @@ -137,7 +137,7 @@ def burndown_plot( estimate__isnull=False, estimate__type="points", ).exists() - if estimate_type and plot_type == "points": + if estimate_type and plot_type == "points" and cycle_id: issue_estimates = Issue.objects.filter( workspace__slug=slug, project_id=project_id, @@ -145,7 +145,18 @@ def burndown_plot( estimate_point__isnull=False, ).values_list("estimate_point__value", flat=True) - issue_estimates = [int(value) for value in issue_estimates] + issue_estimates = [float(value) for value in issue_estimates] + total_estimate_points = sum(issue_estimates) + + if estimate_type and plot_type == "points" and module_id: + issue_estimates = Issue.objects.filter( + workspace__slug=slug, + project_id=project_id, + issue_module__module_id=module_id, + estimate_point__isnull=False, + ).values_list("estimate_point__value", flat=True) + + issue_estimates = [float(value) for value in issue_estimates] total_estimate_points = sum(issue_estimates) if cycle_id: @@ -227,12 +238,12 @@ def burndown_plot( .order_by("date") ) - for date in date_range: - if plot_type == "points": + if plot_type == "points": + for date in date_range: cumulative_pending_issues = total_estimate_points total_completed = 0 total_completed = sum( - int(item["estimate_point__value"]) + float(item["estimate_point__value"]) for item in completed_issues_estimate_point_distribution if item["date"] is not None and item["date"] <= date ) @@ -241,7 +252,8 @@ def burndown_plot( chart_data[str(date)] = None else: chart_data[str(date)] = cumulative_pending_issues - else: + else: + for date in date_range: cumulative_pending_issues = total_issues total_completed = 0 total_completed = sum(