From 1255552ebe5eb15fab0ad87cf80716773b516804 Mon Sep 17 00:00:00 2001 From: pablohashescobar <118773738+pablohashescobar@users.noreply.github.com> Date: Tue, 28 Feb 2023 02:08:55 +0530 Subject: [PATCH] refactor: create new endpoints for date checking getting current upcoming and past cycles (#343) * refactor: create new endpoints for date checking getting current upcoming and past cycles * refactor: rename endpoint to match consistency --- apiserver/plane/api/urls.py | 18 ++++++ apiserver/plane/api/views/__init__.py | 8 ++- apiserver/plane/api/views/cycle.py | 92 ++++++++++++++++++++++++++- apiserver/plane/db/models/cycle.py | 13 +--- 4 files changed, 117 insertions(+), 14 deletions(-) diff --git a/apiserver/plane/api/urls.py b/apiserver/plane/api/urls.py index f267ff16a..abed2de62 100644 --- a/apiserver/plane/api/urls.py +++ b/apiserver/plane/api/urls.py @@ -78,6 +78,9 @@ from plane.api.views import ( # Cycles CycleViewSet, CycleIssueViewSet, + CycleDateCheckEndpoint, + CurrentUpcomingCyclesEndpoint, + CompletedCyclesEndpoint, ## End Cycles # Modules ModuleViewSet, @@ -490,6 +493,21 @@ urlpatterns = [ ), name="project-cycle", ), + path( + "workspaces//projects//cycles/date-check/", + CycleDateCheckEndpoint.as_view(), + name="project-cycle", + ), + path( + "workspaces//projects//cycles/current-upcoming-cycles/", + CurrentUpcomingCyclesEndpoint.as_view(), + name="project-cycle", + ), + path( + "workspaces//projects//cycles/completed-cycles/", + CompletedCyclesEndpoint.as_view(), + name="project-cycle", + ), ## End Cycles # Issue path( diff --git a/apiserver/plane/api/views/__init__.py b/apiserver/plane/api/views/__init__.py index 275642c50..9f9fd87d4 100644 --- a/apiserver/plane/api/views/__init__.py +++ b/apiserver/plane/api/views/__init__.py @@ -39,7 +39,13 @@ from .workspace import ( from .state import StateViewSet from .shortcut import ShortCutViewSet from .view import ViewViewSet -from .cycle import CycleViewSet, CycleIssueViewSet +from .cycle import ( + CycleViewSet, + CycleIssueViewSet, + CycleDateCheckEndpoint, + CurrentUpcomingCyclesEndpoint, + CompletedCyclesEndpoint, +) from .asset import FileAssetEndpoint from .issue import ( IssueViewSet, diff --git a/apiserver/plane/api/views/cycle.py b/apiserver/plane/api/views/cycle.py index 682cdedca..de7bb25fd 100644 --- a/apiserver/plane/api/views/cycle.py +++ b/apiserver/plane/api/views/cycle.py @@ -2,8 +2,9 @@ import json # Django imports -from django.db.models import OuterRef, Func, F +from django.db.models import OuterRef, Func, F, Q from django.core import serializers +from django.utils import timezone # Third party imports from rest_framework.response import Response @@ -11,7 +12,7 @@ from rest_framework import status from sentry_sdk import capture_exception # Module imports -from . import BaseViewSet +from . import BaseViewSet, BaseAPIView from plane.api.serializers import CycleSerializer, CycleIssueSerializer from plane.api.permissions import ProjectEntityPermission from plane.db.models import Cycle, CycleIssue, Issue @@ -206,3 +207,90 @@ class CycleIssueViewSet(BaseViewSet): {"error": "Something went wrong please try again later"}, status=status.HTTP_400_BAD_REQUEST, ) + + +class CycleDateCheckEndpoint(BaseAPIView): + def post(self, request, slug, project_id): + try: + start_date = request.data.get("start_date") + end_date = request.data.get("end_date") + + cycles = Cycle.objects.filter( + Q(start_date__lte=start_date, end_date__gte=start_date) + | Q(start_date__gte=end_date, end_date__lte=end_date), + workspace__slug=slug, + project_id=project_id, + ) + + if cycles.exists(): + return Response( + { + "error": "You have a cycle already on the given dates, if you want to create your draft cycle you can do that by removing dates", + "cycles": CycleSerializer(cycles, many=True).data, + "status": False, + } + ) + else: + return Response({"status": True}, status=status.HTTP_200_OK) + except Exception as e: + capture_exception(e) + return Response( + {"error": "Something went wrong please try again later"}, + status=status.HTTP_400_BAD_REQUEST, + ) + + +class CurrentUpcomingCyclesEndpoint(BaseAPIView): + def get(self, request, slug, project_id): + try: + current_cycle = Cycle.objects.filter( + workspace__slug=slug, + project_id=project_id, + start_date__lte=timezone.now(), + end_date__gte=timezone.now(), + ) + + upcoming_cycle = Cycle.objects.filter( + workspace__slug=slug, + project_id=project_id, + start_date__gte=timezone.now(), + ) + + return Response( + { + "current_cycle": CycleSerializer(current_cycle, many=True).data, + "upcoming_cycle": CycleSerializer(upcoming_cycle, many=True).data, + }, + status=status.HTTP_200_OK, + ) + + except Exception as e: + capture_exception(e) + return Response( + {"error": "Something went wrong please try again later"}, + status=status.HTTP_400_BAD_REQUEST, + ) + + +class CompletedCyclesEndpoint(BaseAPIView): + def get(self, request, slug, project_id): + try: + past_cycles = Cycle.objects.filter( + workspace__slug=slug, + project_id=project_id, + end_date__lte=timezone.now(), + ) + + return Response( + { + "past_cycles": CycleSerializer(past_cycles, many=True).data, + }, + status=status.HTTP_200_OK, + ) + + except Exception as e: + capture_exception(e) + return Response( + {"error": "Something went wrong please try again later"}, + status=status.HTTP_400_BAD_REQUEST, + ) diff --git a/apiserver/plane/db/models/cycle.py b/apiserver/plane/db/models/cycle.py index c06ea40f2..cb9308c95 100644 --- a/apiserver/plane/db/models/cycle.py +++ b/apiserver/plane/db/models/cycle.py @@ -7,11 +7,7 @@ from . import ProjectBaseModel class Cycle(ProjectBaseModel): - STATUS_CHOICES = ( - ("draft", "Draft"), - ("started", "Started"), - ("completed", "Completed"), - ) + name = models.CharField(max_length=255, verbose_name="Cycle Name") description = models.TextField(verbose_name="Cycle Description", blank=True) start_date = models.DateField(verbose_name="Start Date", blank=True, null=True) @@ -21,12 +17,7 @@ class Cycle(ProjectBaseModel): on_delete=models.CASCADE, related_name="owned_by_cycle", ) - status = models.CharField( - max_length=255, - verbose_name="Cycle Status", - choices=STATUS_CHOICES, - default="draft", - ) + class Meta: verbose_name = "Cycle"