[WEB-3044] fix: Correct handling of equal start and end dates in cycle create and update (#6328)

* chore: handled start and end date issue when user send the start and end date equal

* chore: updated variable name and comment

* chore: typo
This commit is contained in:
guru_sainath 2025-01-06 20:31:31 +05:30 committed by GitHub
parent d3d3bf79f9
commit 0cabde03f0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 47 additions and 14 deletions

View file

@ -6,6 +6,7 @@ from .base import BaseSerializer
from plane.db.models import Cycle, CycleIssue from plane.db.models import Cycle, CycleIssue
from plane.utils.timezone_converter import convert_to_utc from plane.utils.timezone_converter import convert_to_utc
class CycleSerializer(BaseSerializer): class CycleSerializer(BaseSerializer):
total_issues = serializers.IntegerField(read_only=True) total_issues = serializers.IntegerField(read_only=True)
cancelled_issues = serializers.IntegerField(read_only=True) cancelled_issues = serializers.IntegerField(read_only=True)
@ -30,11 +31,18 @@ class CycleSerializer(BaseSerializer):
and data.get("end_date", None) is not None and data.get("end_date", None) is not None
): ):
project_id = self.initial_data.get("project_id") or self.instance.project_id project_id = self.initial_data.get("project_id") or self.instance.project_id
is_start_date_end_date_equal = (
True if data.get("start_date") == data.get("end_date") else False
)
data["start_date"] = convert_to_utc( data["start_date"] = convert_to_utc(
str(data.get("start_date").date()), project_id, is_start_date=True date=str(data.get("start_date").date()),
project_id=project_id,
is_start_date=True,
) )
data["end_date"] = convert_to_utc( data["end_date"] = convert_to_utc(
str(data.get("end_date", None).date()), project_id date=str(data.get("end_date", None).date()),
project_id=project_id,
is_start_date_end_date_equal=is_start_date_end_date_equal,
) )
return data return data

View file

@ -21,11 +21,18 @@ class CycleWriteSerializer(BaseSerializer):
and data.get("end_date", None) is not None and data.get("end_date", None) is not None
): ):
project_id = self.initial_data.get("project_id") or self.instance.project_id project_id = self.initial_data.get("project_id") or self.instance.project_id
is_start_date_end_date_equal = (
True if data.get("start_date") == data.get("end_date") else False
)
data["start_date"] = convert_to_utc( data["start_date"] = convert_to_utc(
str(data.get("start_date").date()), project_id, is_start_date=True date=str(data.get("start_date").date()),
project_id=project_id,
is_start_date=True,
) )
data["end_date"] = convert_to_utc( data["end_date"] = convert_to_utc(
str(data.get("end_date", None).date()), project_id date=str(data.get("end_date", None).date()),
project_id=project_id,
is_start_date_end_date_equal=is_start_date_end_date_equal,
) )
return data return data

View file

@ -143,10 +143,7 @@ class CycleViewSet(BaseViewSet):
& Q(end_date__gte=current_time_in_utc), & Q(end_date__gte=current_time_in_utc),
then=Value("CURRENT"), then=Value("CURRENT"),
), ),
When( When(start_date__gt=current_time_in_utc, then=Value("UPCOMING")),
start_date__gt=current_time_in_utc,
then=Value("UPCOMING"),
),
When(end_date__lt=current_time_in_utc, then=Value("COMPLETED")), When(end_date__lt=current_time_in_utc, then=Value("COMPLETED")),
When( When(
Q(start_date__isnull=True) & Q(end_date__isnull=True), Q(start_date__isnull=True) & Q(end_date__isnull=True),
@ -259,7 +256,9 @@ class CycleViewSet(BaseViewSet):
"created_by", "created_by",
) )
datetime_fields = ["start_date", "end_date"] datetime_fields = ["start_date", "end_date"]
data = user_timezone_converter(data, datetime_fields, request.user.user_timezone) data = user_timezone_converter(
data, datetime_fields, request.user.user_timezone
)
return Response(data, status=status.HTTP_200_OK) return Response(data, status=status.HTTP_200_OK)
@allow_permission([ROLE.ADMIN, ROLE.MEMBER]) @allow_permission([ROLE.ADMIN, ROLE.MEMBER])
@ -457,7 +456,9 @@ class CycleViewSet(BaseViewSet):
queryset = queryset.first() queryset = queryset.first()
datetime_fields = ["start_date", "end_date"] datetime_fields = ["start_date", "end_date"]
data = user_timezone_converter(data, datetime_fields, request.user.user_timezone) data = user_timezone_converter(
data, datetime_fields, request.user.user_timezone
)
recent_visited_task.delay( recent_visited_task.delay(
slug=slug, slug=slug,
@ -533,8 +534,17 @@ class CycleDateCheckEndpoint(BaseAPIView):
status=status.HTTP_400_BAD_REQUEST, status=status.HTTP_400_BAD_REQUEST,
) )
start_date = convert_to_utc(str(start_date), project_id, is_start_date=True) is_start_date_end_date_equal = (
end_date = convert_to_utc(str(end_date), project_id) True if str("start_date") == str("end_date") else False
)
start_date = convert_to_utc(
date=str(start_date), project_id=project_id, is_start_date=True
)
end_date = convert_to_utc(
date=str(end_date),
project_id=project_id,
is_start_date_end_date_equal=is_start_date_end_date_equal,
)
# Check if any cycle intersects in the given interval # Check if any cycle intersects in the given interval
cycles = Cycle.objects.filter( cycles = Cycle.objects.filter(

View file

@ -3,6 +3,7 @@ from plane.db.models import Project
from datetime import datetime, time from datetime import datetime, time
from datetime import timedelta from datetime import timedelta
def user_timezone_converter(queryset, datetime_fields, user_timezone): def user_timezone_converter(queryset, datetime_fields, user_timezone):
# Create a timezone object for the user's timezone # Create a timezone object for the user's timezone
user_tz = pytz.timezone(user_timezone) user_tz = pytz.timezone(user_timezone)
@ -28,7 +29,9 @@ def user_timezone_converter(queryset, datetime_fields, user_timezone):
return queryset_values return queryset_values
def convert_to_utc(date, project_id, is_start_date=False): def convert_to_utc(
date, project_id, is_start_date=False, is_start_date_end_date_equal=False
):
""" """
Converts a start date string to the project's local timezone at 12:00 AM Converts a start date string to the project's local timezone at 12:00 AM
and then converts it to UTC for storage. and then converts it to UTC for storage.
@ -60,7 +63,12 @@ def convert_to_utc(date, project_id, is_start_date=False):
# If it's an start date, add one minute # If it's an start date, add one minute
if is_start_date: if is_start_date:
localized_datetime += timedelta(minutes=1) localized_datetime += timedelta(minutes=0, seconds=1)
# If it's start an end date are equal, add 23 hours, 59 minutes, and 59 seconds
# to make it the end of the day
if is_start_date_end_date_equal:
localized_datetime += timedelta(hours=23, minutes=59, seconds=59)
# Convert the localized datetime to UTC # Convert the localized datetime to UTC
utc_datetime = localized_datetime.astimezone(pytz.utc) utc_datetime = localized_datetime.astimezone(pytz.utc)