-
Notifications
You must be signed in to change notification settings - Fork 3.6k
[WEB-2600] fix: estimate point deletion #5762
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consistent Issue Updates Ensure that the Add the following after line 316: issues.update(estimate_point_id=None)This ensures that all issues have their Also applies to: 317-317 |
||
| 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()), | ||
| ) | ||
|
Comment on lines
+257
to
+316
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Refactor Repetitive Code in The code inside the You can refactor the code to eliminate duplication: issues = Issue.objects.filter(
project_id=project_id,
workspace__slug=slug,
estimate_point_id=estimate_point_id,
)
new_estimate_point = str(new_estimate_id) if new_estimate_id else None
for issue in issues:
issue_activity.delay(
type="issue.activity.updated",
requested_data=json.dumps({"estimate_point": new_estimate_point}),
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()),
)
if new_estimate_id:
issues.update(estimate_point_id=new_estimate_id)
else:
issues.update(estimate_point_id=None)This refactoring reduces code duplication and makes the logic clearer. |
||
|
|
||
| # delete the estimate point | ||
| old_estimate_point = EstimatePoint.objects.filter( | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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]) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Restricted access to ADMIN role only The Please ensure this change aligns with your project's access control requirements and update any related documentation or user guides accordingly. |
||
| def partial_update(self, request, slug, pk=None): | ||
| try: | ||
| workspace = Workspace.objects.get(slug=slug) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Consider Consolidating Hard Deletion Logic In the Suggestion: Evaluate whether the individual deletions of specific models are necessary if the final loop sufficiently handles the hard deletion of all models with a |
||
| ).delete() | ||
|
|
||
| return | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -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 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+1703
to
+1708
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Refactor nested ternary operators for improved readability The nested ternary operators in the assignments of Apply this diff to improve readability: if len(issue_activities_created):
for activity in issue_activities_created:
+ if activity.field == "comment":
+ event = "issue_comment"
+ event_id = activity.issue_comment_id
+ elif inbox:
+ event = "inbox_issue"
+ event_id = inbox
+ else:
+ event = "issue"
+ event_id = activity.issue_id
webhook_activity.delay(
- event=(
- "issue_comment"
- if activity.field == "comment"
- 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
- ),
+ event=event,
+ event_id=event_id,
verb=activity.verb,
field=(
"description"
if activity.field == "comment"
else activity.field
),
old_value=(
activity.old_value
if activity.old_value != ""
else None
),
new_value=(
activity.new_value
if activity.new_value != ""
else None
),
actor_id=activity.actor_id,
current_site=origin,
slug=activity.workspace.slug,
old_identifier=activity.old_identifier,
new_identifier=activity.new_identifier,
)This refactoring assigns 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| verb=activity.verb, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| field=( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ensure Issues are Updated to Remove Deleted Estimate Point
In the
elseblock wherenew_estimate_idis not provided, theissuesare not updated to remove the reference to the deletedestimate_point_id. This means the issues will still reference an estimate point that no longer exists, which could lead to integrity issues.To fix this, add an
issues.update(estimate_point_id=None)after the loop in theelseblock to set theestimate_point_idtoNonefor all affected issues:This ensures that all issues previously associated with the deleted estimate point no longer hold invalid references.