From c92fe6191e7cbd6101f181d5c893195ea500f8bc Mon Sep 17 00:00:00 2001 From: Bavisetti Narayan <72156168+NarayanBavisetti@users.noreply.github.com> Date: Mon, 7 Oct 2024 17:23:37 +0530 Subject: [PATCH] [WEB-2600] fix: estimate point deletion (#5762) * chore: only delete the cascade fields * chore: logged the issue activity --- apiserver/plane/app/views/estimate/base.py | 64 ++++++++++++++++++- apiserver/plane/app/views/project/base.py | 2 +- apiserver/plane/bgtasks/deletion_task.py | 34 ++++++---- .../plane/bgtasks/issue_activities_task.py | 10 +-- 4 files changed, 87 insertions(+), 23 deletions(-) diff --git a/apiserver/plane/app/views/estimate/base.py b/apiserver/plane/app/views/estimate/base.py index f3848800197..80943c05ebc 100644 --- a/apiserver/plane/app/views/estimate/base.py +++ b/apiserver/plane/app/views/estimate/base.py @@ -1,5 +1,9 @@ import random import string +import json + +# Django imports +from django.utils import timezone # Third party imports from rest_framework.response import Response @@ -19,6 +23,7 @@ EstimateReadSerializer, ) from plane.utils.cache import invalidate_cache +from plane.bgtasks.issue_activities_task import issue_activity def generate_random_name(length=10): @@ -249,11 +254,66 @@ def destroy( ) # update all the issues with the new estimate if new_estimate_id: - _ = Issue.objects.filter( + issues = Issue.objects.filter( + project_id=project_id, + workspace__slug=slug, + estimate_point_id=estimate_point_id, + ) + for issue in issues: + issue_activity.delay( + type="issue.activity.updated", + requested_data=json.dumps( + { + "estimate_point": ( + str(new_estimate_id) + if new_estimate_id + else None + ), + } + ), + actor_id=str(request.user.id), + issue_id=issue.id, + project_id=str(project_id), + current_instance=json.dumps( + { + "estimate_point": ( + str(issue.estimate_point_id) + if issue.estimate_point_id + else None + ), + } + ), + epoch=int(timezone.now().timestamp()), + ) + issues.update(estimate_point_id=new_estimate_id) + else: + issues = Issue.objects.filter( project_id=project_id, workspace__slug=slug, estimate_point_id=estimate_point_id, - ).update(estimate_point_id=new_estimate_id) + ) + for issue in issues: + issue_activity.delay( + type="issue.activity.updated", + requested_data=json.dumps( + { + "estimate_point": None, + } + ), + actor_id=str(request.user.id), + issue_id=issue.id, + project_id=str(project_id), + current_instance=json.dumps( + { + "estimate_point": ( + str(issue.estimate_point_id) + if issue.estimate_point_id + else None + ), + } + ), + epoch=int(timezone.now().timestamp()), + ) # delete the estimate point old_estimate_point = EstimatePoint.objects.filter( diff --git a/apiserver/plane/app/views/project/base.py b/apiserver/plane/app/views/project/base.py index 8bdff03e627..6a9afb65237 100644 --- a/apiserver/plane/app/views/project/base.py +++ b/apiserver/plane/app/views/project/base.py @@ -413,7 +413,7 @@ def create(self, request, slug): status=status.HTTP_410_GONE, ) - @allow_permission([ROLE.ADMIN, ROLE.MEMBER], level="WORKSPACE") + @allow_permission([ROLE.ADMIN]) def partial_update(self, request, slug, pk=None): try: workspace = Workspace.objects.get(slug=slug) diff --git a/apiserver/plane/bgtasks/deletion_task.py b/apiserver/plane/bgtasks/deletion_task.py index d8272591a93..35d72812da6 100644 --- a/apiserver/plane/bgtasks/deletion_task.py +++ b/apiserver/plane/bgtasks/deletion_task.py @@ -2,6 +2,7 @@ from django.utils import timezone from django.apps import apps from django.conf import settings +from django.db import models from django.core.exceptions import ObjectDoesNotExist # Third party imports @@ -18,17 +19,25 @@ def soft_delete_related_objects( for field in related_fields: if field.one_to_many or field.one_to_one: try: - if field.one_to_many: - related_objects = getattr(instance, field.name).all() - elif field.one_to_one: - related_object = getattr(instance, field.name) - related_objects = ( - [related_object] if related_object is not None else [] - ) - for obj in related_objects: - if obj: - obj.deleted_at = timezone.now() - obj.save(using=using) + # Check if the field has CASCADE on delete + if ( + hasattr(field.remote_field, "on_delete") + and field.remote_field.on_delete == models.CASCADE + ): + if field.one_to_many: + related_objects = getattr(instance, field.name).all() + elif field.one_to_one: + related_object = getattr(instance, field.name) + related_objects = ( + [related_object] + if related_object is not None + else [] + ) + + for obj in related_objects: + if obj: + obj.deleted_at = timezone.now() + obj.save(using=using) except ObjectDoesNotExist: pass @@ -154,8 +163,7 @@ def hard_delete(): if hasattr(model, "deleted_at"): # Get all instances where 'deleted_at' is greater than 30 days ago _ = model.all_objects.filter( - deleted_at__lt=timezone.now() - - timezone.timedelta(days=days) + deleted_at__lt=timezone.now() - timezone.timedelta(days=days) ).delete() return diff --git a/apiserver/plane/bgtasks/issue_activities_task.py b/apiserver/plane/bgtasks/issue_activities_task.py index 8ecf7845dba..0cee9baef3f 100644 --- a/apiserver/plane/bgtasks/issue_activities_task.py +++ b/apiserver/plane/bgtasks/issue_activities_task.py @@ -465,7 +465,7 @@ def track_estimate_points( IssueActivity( issue_id=issue_id, actor_id=actor_id, - verb="updated", + verb="removed" if new_estimate is None else "updated", old_identifier=( current_instance.get("estimate_point") if current_instance.get("estimate_point") is not None @@ -1700,16 +1700,12 @@ def issue_activity( event=( "issue_comment" if activity.field == "comment" - else "inbox_issue" - if inbox - else "issue" + else "inbox_issue" if inbox else "issue" ), event_id=( activity.issue_comment_id if activity.field == "comment" - else inbox - if inbox - else activity.issue_id + else inbox if inbox else activity.issue_id ), verb=activity.verb, field=(