From 1153cd3a2f6f0e6aeb9403a6f8263db6f1565456 Mon Sep 17 00:00:00 2001 From: NarayanBavisetti Date: Mon, 21 Oct 2024 18:50:13 +0530 Subject: [PATCH 1/6] chore: soft deletion of cycle and module --- apiserver/plane/api/views/cycle.py | 2 +- apiserver/plane/api/views/issue.py | 2 +- apiserver/plane/api/views/module.py | 2 +- apiserver/plane/app/serializers/draft.py | 6 +++--- apiserver/plane/app/views/cycle/issue.py | 4 ++-- apiserver/plane/app/views/dashboard/base.py | 4 ++-- apiserver/plane/app/views/inbox/base.py | 8 +++++--- apiserver/plane/app/views/issue/archive.py | 2 +- apiserver/plane/app/views/issue/base.py | 12 ++++++------ apiserver/plane/app/views/issue/relation.py | 2 +- apiserver/plane/app/views/issue/sub_issue.py | 4 ++-- apiserver/plane/app/views/module/issue.py | 6 +++--- apiserver/plane/app/views/view/base.py | 10 ++++++---- apiserver/plane/app/views/workspace/draft.py | 6 ++---- apiserver/plane/app/views/workspace/user.py | 2 +- apiserver/plane/db/models/issue.py | 1 + apiserver/plane/space/views/issue.py | 6 +++--- apiserver/plane/utils/grouper.py | 2 +- 18 files changed, 42 insertions(+), 39 deletions(-) diff --git a/apiserver/plane/api/views/cycle.py b/apiserver/plane/api/views/cycle.py index 882692dac04..a9a2af4f7af 100644 --- a/apiserver/plane/api/views/cycle.py +++ b/apiserver/plane/api/views/cycle.py @@ -761,7 +761,7 @@ def delete(self, request, slug, project_id, cycle_id, issue_id): cycle_id=cycle_id, ) issue_id = cycle_issue.issue_id - cycle_issue.delete() + cycle_issue.delete(soft=False) issue_activity.delay( type="cycle.activity.deleted", requested_data=json.dumps( diff --git a/apiserver/plane/api/views/issue.py b/apiserver/plane/api/views/issue.py index 27c7042b49b..2590532abf1 100644 --- a/apiserver/plane/api/views/issue.py +++ b/apiserver/plane/api/views/issue.py @@ -205,7 +205,7 @@ def get(self, request, slug, project_id, pk=None): .annotate( cycle_id=Case( When( - Q(issue_cycle__cycle__deleted_at__isnull=True), + Q(issue_cycle__deleted_at__isnull=True), then=F("issue_cycle__cycle_id"), ), default=None, diff --git a/apiserver/plane/api/views/module.py b/apiserver/plane/api/views/module.py index 45407df80fe..e99ee668857 100644 --- a/apiserver/plane/api/views/module.py +++ b/apiserver/plane/api/views/module.py @@ -506,7 +506,7 @@ def delete(self, request, slug, project_id, module_id, issue_id): module_id=module_id, issue_id=issue_id, ) - module_issue.delete() + module_issue.delete(soft=False) issue_activity.delay( type="module.activity.deleted", requested_data=json.dumps( diff --git a/apiserver/plane/app/serializers/draft.py b/apiserver/plane/app/serializers/draft.py index fca695c9872..b7f7d2e7eba 100644 --- a/apiserver/plane/app/serializers/draft.py +++ b/apiserver/plane/app/serializers/draft.py @@ -207,8 +207,8 @@ def update(self, instance, validated_data): ) if cycle_id != "not_provided": - DraftIssueCycle.objects.filter(draft_issue=instance).delete() - if cycle_id is not None: + DraftIssueCycle.objects.filter(draft_issue=instance).delete(soft=False) + if cycle_id: DraftIssueCycle.objects.create( cycle_id=cycle_id, draft_issue=instance, @@ -219,7 +219,7 @@ def update(self, instance, validated_data): ) if modules is not None: - DraftIssueModule.objects.filter(draft_issue=instance).delete() + DraftIssueModule.objects.filter(draft_issue=instance).delete(soft=False) DraftIssueModule.objects.bulk_create( [ DraftIssueModule( diff --git a/apiserver/plane/app/views/cycle/issue.py b/apiserver/plane/app/views/cycle/issue.py index a9a33059900..4774155cb0f 100644 --- a/apiserver/plane/app/views/cycle/issue.py +++ b/apiserver/plane/app/views/cycle/issue.py @@ -105,7 +105,7 @@ def list(self, request, slug, project_id, cycle_id): .annotate( cycle_id=Case( When( - issue_cycle__cycle__deleted_at__isnull=True, + issue_cycle__deleted_at__isnull=True, then=F("issue_cycle__cycle_id"), ), default=None, @@ -358,5 +358,5 @@ def destroy(self, request, slug, project_id, cycle_id, issue_id): notification=True, origin=request.META.get("HTTP_ORIGIN"), ) - cycle_issue.delete() + cycle_issue.delete(soft=False) return Response(status=status.HTTP_204_NO_CONTENT) diff --git a/apiserver/plane/app/views/dashboard/base.py b/apiserver/plane/app/views/dashboard/base.py index 1cb446abb12..1cc2d3b717d 100644 --- a/apiserver/plane/app/views/dashboard/base.py +++ b/apiserver/plane/app/views/dashboard/base.py @@ -240,7 +240,7 @@ def dashboard_assigned_issues(self, request, slug): distinct=True, filter=~Q(issue_module__module_id__isnull=True) & Q(issue_module__module__archived_at__isnull=True) - & Q(issue_module__module__deleted_at__isnull=True), + & Q(issue_module__deleted_at__isnull=True), ), Value([], output_field=ArrayField(UUIDField())), ), @@ -409,7 +409,7 @@ def dashboard_created_issues(self, request, slug): distinct=True, filter=~Q(issue_module__module_id__isnull=True) & Q(issue_module__module__archived_at__isnull=True) - & Q(issue_module__module__deleted_at__isnull=True), + & Q(issue_module__deleted_at__isnull=True), ), Value([], output_field=ArrayField(UUIDField())), ), diff --git a/apiserver/plane/app/views/inbox/base.py b/apiserver/plane/app/views/inbox/base.py index dcae298d662..03d08573dc8 100644 --- a/apiserver/plane/app/views/inbox/base.py +++ b/apiserver/plane/app/views/inbox/base.py @@ -115,7 +115,7 @@ def get_queryset(self): .annotate( cycle_id=Case( When( - issue_cycle__cycle__deleted_at__isnull=True, + issue_cycle__deleted_at__isnull=True, then=F("issue_cycle__cycle_id"), ), default=None, @@ -171,7 +171,7 @@ def get_queryset(self): distinct=True, filter=~Q(issue_module__module_id__isnull=True) & Q(issue_module__module__archived_at__isnull=True) - & Q(issue_module__module__deleted_at__isnull=True), + & Q(issue_module__deleted_at__isnull=True), ), Value([], output_field=ArrayField(UUIDField())), ), @@ -323,7 +323,9 @@ def create(self, request, slug, project_id): "issue__assignees__id", distinct=True, filter=~Q(issue__assignees__id__isnull=True) - & Q(issue__assignees__member_project__is_active=True), + & Q( + issue__assignees__member_project__is_active=True + ), ), Value([], output_field=ArrayField(UUIDField())), ), diff --git a/apiserver/plane/app/views/issue/archive.py b/apiserver/plane/app/views/issue/archive.py index 283f1ad99a8..46815296dbf 100644 --- a/apiserver/plane/app/views/issue/archive.py +++ b/apiserver/plane/app/views/issue/archive.py @@ -67,7 +67,7 @@ def get_queryset(self): .annotate( cycle_id=Case( When( - issue_cycle__cycle__deleted_at__isnull=True, + issue_cycle__deleted_at__isnull=True, then=F("issue_cycle__cycle_id"), ), default=None, diff --git a/apiserver/plane/app/views/issue/base.py b/apiserver/plane/app/views/issue/base.py index 0488a5471d8..f0555f477b1 100644 --- a/apiserver/plane/app/views/issue/base.py +++ b/apiserver/plane/app/views/issue/base.py @@ -88,7 +88,7 @@ def get(self, request, slug, project_id): .annotate( cycle_id=Case( When( - issue_cycle__cycle__deleted_at__isnull=True, + issue_cycle__deleted_at__isnull=True, then=F("issue_cycle__cycle_id"), ), default=None, @@ -220,7 +220,7 @@ def get_queryset(self): .annotate( cycle_id=Case( When( - issue_cycle__cycle__deleted_at__isnull=True, + issue_cycle__deleted_at__isnull=True, then=F("issue_cycle__cycle_id"), ), default=None, @@ -511,7 +511,7 @@ def retrieve(self, request, slug, project_id, pk=None): distinct=True, filter=~Q(issue_module__module_id__isnull=True) & Q(issue_module__module__archived_at__isnull=True) - & Q(issue_module__module__deleted_at__isnull=True), + & Q(issue_module__deleted_at__isnull=True), ), Value([], output_field=ArrayField(UUIDField())), ), @@ -612,7 +612,7 @@ def partial_update(self, request, slug, project_id, pk=None): distinct=True, filter=~Q(issue_module__module_id__isnull=True) & Q(issue_module__module__archived_at__isnull=True) - & Q(issue_module__module__deleted_at__isnull=True), + & Q(issue_module__deleted_at__isnull=True), ), Value([], output_field=ArrayField(UUIDField())), ), @@ -778,7 +778,7 @@ def get_queryset(self): .annotate( cycle_id=Case( When( - issue_cycle__cycle__deleted_at__isnull=True, + issue_cycle__deleted_at__isnull=True, then=F("issue_cycle__cycle_id"), ), default=None, @@ -912,7 +912,7 @@ def list(self, request, slug, project_id): distinct=True, filter=~Q(issue_module__module_id__isnull=True) & Q(issue_module__module__archived_at__isnull=True) - & Q(issue_module__module__deleted_at__isnull=True), + & Q(issue_module__deleted_at__isnull=True), ), Value([], output_field=ArrayField(UUIDField())), ), diff --git a/apiserver/plane/app/views/issue/relation.py b/apiserver/plane/app/views/issue/relation.py index 83385d83d72..0b532ddfda0 100644 --- a/apiserver/plane/app/views/issue/relation.py +++ b/apiserver/plane/app/views/issue/relation.py @@ -96,7 +96,7 @@ def list(self, request, slug, project_id, issue_id): .annotate( cycle_id=Case( When( - issue_cycle__cycle__deleted_at__isnull=True, + issue_cycle__deleted_at__isnull=True, then=F("issue_cycle__cycle_id"), ), default=None, diff --git a/apiserver/plane/app/views/issue/sub_issue.py b/apiserver/plane/app/views/issue/sub_issue.py index 700d6db5b39..445ea6df476 100644 --- a/apiserver/plane/app/views/issue/sub_issue.py +++ b/apiserver/plane/app/views/issue/sub_issue.py @@ -53,7 +53,7 @@ def get(self, request, slug, project_id, issue_id): .annotate( cycle_id=Case( When( - issue_cycle__cycle__deleted_at__isnull=True, + issue_cycle__deleted_at__isnull=True, then=F("issue_cycle__cycle_id"), ), default=None, @@ -109,7 +109,7 @@ def get(self, request, slug, project_id, issue_id): distinct=True, filter=~Q(issue_module__module_id__isnull=True) & Q(issue_module__module__archived_at__isnull=True) - & Q(issue_module__module__deleted_at__isnull=True), + & Q(issue_module__deleted_at__isnull=True), ), Value([], output_field=ArrayField(UUIDField())), ), diff --git a/apiserver/plane/app/views/module/issue.py b/apiserver/plane/app/views/module/issue.py index f58e477567a..6c0633e2bb0 100644 --- a/apiserver/plane/app/views/module/issue.py +++ b/apiserver/plane/app/views/module/issue.py @@ -70,7 +70,7 @@ def get_queryset(self): .annotate( cycle_id=Case( When( - issue_cycle__cycle__deleted_at__isnull=True, + issue_cycle__deleted_at__isnull=True, then=F("issue_cycle__cycle_id"), ), default=None, @@ -316,7 +316,7 @@ def create_issue_modules(self, request, slug, project_id, issue_id): notification=True, origin=request.META.get("HTTP_ORIGIN"), ) - module_issue.delete() + module_issue.delete(soft=False) return Response({"message": "success"}, status=status.HTTP_201_CREATED) @@ -341,5 +341,5 @@ def destroy(self, request, slug, project_id, module_id, issue_id): notification=True, origin=request.META.get("HTTP_ORIGIN"), ) - module_issue.delete() + module_issue.delete(soft=False) return Response(status=status.HTTP_204_NO_CONTENT) diff --git a/apiserver/plane/app/views/view/base.py b/apiserver/plane/app/views/view/base.py index 59cfcecd57a..1b708ae2631 100644 --- a/apiserver/plane/app/views/view/base.py +++ b/apiserver/plane/app/views/view/base.py @@ -210,7 +210,7 @@ def get_queryset(self): .annotate( cycle_id=Case( When( - issue_cycle__cycle__deleted_at__isnull=True, + issue_cycle__deleted_at__isnull=True, then=F("issue_cycle__cycle_id"), ), default=None, @@ -266,7 +266,7 @@ def get_queryset(self): distinct=True, filter=~Q(issue_module__module_id__isnull=True) & Q(issue_module__module__archived_at__isnull=True) - & Q(issue_module__module__deleted_at__isnull=True), + & Q(issue_module__deleted_at__isnull=True), ), Value([], output_field=ArrayField(UUIDField())), ), @@ -288,7 +288,7 @@ def list(self, request, slug): .annotate( cycle_id=Case( When( - issue_cycle__cycle__deleted_at__isnull=True, + issue_cycle__deleted_at__isnull=True, then=F("issue_cycle__cycle_id"), ), default=None, @@ -552,7 +552,9 @@ def partial_update(self, request, slug, project_id, pk): serializer.errors, status=status.HTTP_400_BAD_REQUEST ) - @allow_permission(allowed_roles=[ROLE.ADMIN], creator=True, model=IssueView) + @allow_permission( + allowed_roles=[ROLE.ADMIN], creator=True, model=IssueView + ) def destroy(self, request, slug, project_id, pk): project_view = IssueView.objects.get( pk=pk, diff --git a/apiserver/plane/app/views/workspace/draft.py b/apiserver/plane/app/views/workspace/draft.py index ae7db2a4012..e1d3c086dd8 100644 --- a/apiserver/plane/app/views/workspace/draft.py +++ b/apiserver/plane/app/views/workspace/draft.py @@ -60,7 +60,7 @@ def get_queryset(self): .annotate( cycle_id=Case( When( - draft_issue_cycle__cycle__deleted_at__isnull=True, + draft_issue_cycle__deleted_at__isnull=True, then=F("draft_issue_cycle__cycle_id"), ), default=None, @@ -95,9 +95,7 @@ def get_queryset(self): & Q( draft_issue_module__module__archived_at__isnull=True ) - & Q( - draft_issue_module__module__deleted_at__isnull=True - ), + & Q(draft_issue_module__deleted_at__isnull=True), ), Value([], output_field=ArrayField(UUIDField())), ), diff --git a/apiserver/plane/app/views/workspace/user.py b/apiserver/plane/app/views/workspace/user.py index fae917af295..a69f18e19f0 100644 --- a/apiserver/plane/app/views/workspace/user.py +++ b/apiserver/plane/app/views/workspace/user.py @@ -123,7 +123,7 @@ def get(self, request, slug, user_id): .annotate( cycle_id=Case( When( - issue_cycle__cycle__deleted_at__isnull=True, + issue_cycle__deleted_at__isnull=True, then=F("issue_cycle__cycle_id"), ), default=None, diff --git a/apiserver/plane/db/models/issue.py b/apiserver/plane/db/models/issue.py index 7ff9af46e9b..4bc529f55f8 100644 --- a/apiserver/plane/db/models/issue.py +++ b/apiserver/plane/db/models/issue.py @@ -91,6 +91,7 @@ def get_queryset(self): | models.Q(issue_inbox__status=2) | models.Q(issue_inbox__isnull=True) ) + .filter(deleted_at__isnull=True) .filter(state__is_triage=False) .exclude(archived_at__isnull=False) .exclude(project__archived_at__isnull=False) diff --git a/apiserver/plane/space/views/issue.py b/apiserver/plane/space/views/issue.py index bd9d499d60b..c6993c17e51 100644 --- a/apiserver/plane/space/views/issue.py +++ b/apiserver/plane/space/views/issue.py @@ -109,7 +109,7 @@ def get(self, request, anchor): .annotate( cycle_id=Case( When( - issue_cycle__cycle__deleted_at__isnull=True, + issue_cycle__deleted_at__isnull=True, then=F("issue_cycle__cycle_id"), ), default=None, @@ -706,7 +706,7 @@ def get(self, request, anchor, issue_id): .annotate( cycle_id=Case( When( - issue_cycle__cycle__deleted_at__isnull=True, + issue_cycle__deleted_at__isnull=True, then=F("issue_cycle__cycle_id"), ), default=None, @@ -739,7 +739,7 @@ def get(self, request, anchor, issue_id): distinct=True, filter=~Q(issue_module__module_id__isnull=True) & Q(issue_module__module__archived_at__isnull=True) - & Q(issue_module__module__deleted_at__isnull=True), + & Q(issue_module__deleted_at__isnull=True), ), Value([], output_field=ArrayField(UUIDField())), ), diff --git a/apiserver/plane/utils/grouper.py b/apiserver/plane/utils/grouper.py index fef47e0b085..4fb532a253e 100644 --- a/apiserver/plane/utils/grouper.py +++ b/apiserver/plane/utils/grouper.py @@ -35,7 +35,7 @@ def issue_queryset_grouper(queryset, group_by, sub_group_by): ( ~Q(issue_module__module_id__isnull=True) & Q(issue_module__module__archived_at__isnull=True) - & Q(issue_module__module__deleted_at__isnull=True) + & Q(issue_module__deleted_at__isnull=True) ), ), } From e744a63ba3cd9111b2f4ce18ffb3d817879146fc Mon Sep 17 00:00:00 2001 From: NarayanBavisetti Date: Mon, 21 Oct 2024 21:41:32 +0530 Subject: [PATCH 2/6] chore: cycle module soft delete --- apiserver/.env.example | 3 -- apiserver/plane/api/serializers/issue.py | 4 +- apiserver/plane/api/views/cycle.py | 4 +- apiserver/plane/api/views/inbox.py | 8 +++- apiserver/plane/api/views/module.py | 2 +- apiserver/plane/app/serializers/draft.py | 12 ++---- apiserver/plane/app/serializers/issue.py | 4 +- apiserver/plane/app/views/analytic/base.py | 5 ++- apiserver/plane/app/views/cycle/base.py | 7 +++- apiserver/plane/app/views/cycle/issue.py | 2 +- apiserver/plane/app/views/dashboard/base.py | 10 +++-- apiserver/plane/app/views/inbox/base.py | 31 ++++++++++----- apiserver/plane/app/views/issue/base.py | 15 ++++--- apiserver/plane/app/views/issue/relation.py | 7 ++-- apiserver/plane/app/views/issue/sub_issue.py | 3 +- apiserver/plane/app/views/module/issue.py | 4 +- apiserver/plane/app/views/view/base.py | 5 ++- apiserver/plane/app/views/workspace/draft.py | 5 ++- .../plane/bgtasks/analytic_plot_export.py | 4 +- apiserver/plane/bgtasks/deletion_task.py | 2 +- apiserver/plane/celery.py | 4 -- ...anagers_alter_cycleissue_issue_and_more.py | 39 +++++++++++++++++++ apiserver/plane/db/models/cycle.py | 3 +- apiserver/plane/db/models/draft.py | 3 +- apiserver/plane/settings/common.py | 2 - apiserver/plane/space/serializer/issue.py | 4 +- apiserver/plane/space/utils/grouper.py | 12 +++++- apiserver/plane/space/views/issue.py | 5 ++- apiserver/plane/utils/grouper.py | 9 ++++- apiserver/plane/utils/issue_filters.py | 30 ++++++++++---- 30 files changed, 169 insertions(+), 79 deletions(-) create mode 100644 apiserver/plane/db/migrations/0082_alter_issue_managers_alter_cycleissue_issue_and_more.py diff --git a/apiserver/.env.example b/apiserver/.env.example index 733e448d60b..9d25523c5b9 100644 --- a/apiserver/.env.example +++ b/apiserver/.env.example @@ -56,6 +56,3 @@ GUNICORN_WORKERS=2 ADMIN_BASE_URL= SPACE_BASE_URL= APP_BASE_URL= - -# Hard delete files after days -HARD_DELETE_AFTER_DAYS=60 diff --git a/apiserver/plane/api/serializers/issue.py b/apiserver/plane/api/serializers/issue.py index c4a131fd746..90515733954 100644 --- a/apiserver/plane/api/serializers/issue.py +++ b/apiserver/plane/api/serializers/issue.py @@ -212,7 +212,7 @@ def update(self, instance, validated_data): updated_by_id = instance.updated_by_id if assignees is not None: - IssueAssignee.objects.filter(issue=instance).delete(soft=False) + IssueAssignee.objects.filter(issue=instance).delete() IssueAssignee.objects.bulk_create( [ IssueAssignee( @@ -229,7 +229,7 @@ def update(self, instance, validated_data): ) if labels is not None: - IssueLabel.objects.filter(issue=instance).delete(soft=False) + IssueLabel.objects.filter(issue=instance).delete() IssueLabel.objects.bulk_create( [ IssueLabel( diff --git a/apiserver/plane/api/views/cycle.py b/apiserver/plane/api/views/cycle.py index a9a2af4f7af..12e4a1b3c3c 100644 --- a/apiserver/plane/api/views/cycle.py +++ b/apiserver/plane/api/views/cycle.py @@ -404,7 +404,7 @@ def delete(self, request, slug, project_id, pk): epoch=int(timezone.now().timestamp()), ) # Delete the cycle - cycle.delete(soft=False) + cycle.delete() # Delete the user favorite cycle UserFavorite.objects.filter( entity_type="cycle", @@ -761,7 +761,7 @@ def delete(self, request, slug, project_id, cycle_id, issue_id): cycle_id=cycle_id, ) issue_id = cycle_issue.issue_id - cycle_issue.delete(soft=False) + cycle_issue.delete() issue_activity.delay( type="cycle.activity.deleted", requested_data=json.dumps( diff --git a/apiserver/plane/api/views/inbox.py b/apiserver/plane/api/views/inbox.py index f7e18dd76ff..216105fe693 100644 --- a/apiserver/plane/api/views/inbox.py +++ b/apiserver/plane/api/views/inbox.py @@ -227,7 +227,8 @@ def patch(self, request, slug, project_id, issue_id): ArrayAgg( "labels__id", distinct=True, - filter=~Q(labels__id__isnull=True), + filter=~Q(labels__id__isnull=True) + & Q(label_issue__deleted_at__isnull=True), ), Value([], output_field=ArrayField(UUIDField())), ), @@ -235,7 +236,10 @@ def patch(self, request, slug, project_id, issue_id): ArrayAgg( "assignees__id", distinct=True, - filter=~Q(assignees__id__isnull=True), + filter=( + ~Q(assignees__id__isnull=True) + & Q(issue_assignee__deleted_at__isnull=True) + ), ), Value([], output_field=ArrayField(UUIDField())), ), diff --git a/apiserver/plane/api/views/module.py b/apiserver/plane/api/views/module.py index e99ee668857..45407df80fe 100644 --- a/apiserver/plane/api/views/module.py +++ b/apiserver/plane/api/views/module.py @@ -506,7 +506,7 @@ def delete(self, request, slug, project_id, module_id, issue_id): module_id=module_id, issue_id=issue_id, ) - module_issue.delete(soft=False) + module_issue.delete() issue_activity.delay( type="module.activity.deleted", requested_data=json.dumps( diff --git a/apiserver/plane/app/serializers/draft.py b/apiserver/plane/app/serializers/draft.py index b7f7d2e7eba..e07e416a75d 100644 --- a/apiserver/plane/app/serializers/draft.py +++ b/apiserver/plane/app/serializers/draft.py @@ -169,9 +169,7 @@ def update(self, instance, validated_data): updated_by_id = instance.updated_by_id if assignees is not None: - DraftIssueAssignee.objects.filter(draft_issue=instance).delete( - soft=False - ) + DraftIssueAssignee.objects.filter(draft_issue=instance).delete() DraftIssueAssignee.objects.bulk_create( [ DraftIssueAssignee( @@ -188,9 +186,7 @@ def update(self, instance, validated_data): ) if labels is not None: - DraftIssueLabel.objects.filter(draft_issue=instance).delete( - soft=False - ) + DraftIssueLabel.objects.filter(draft_issue=instance).delete() DraftIssueLabel.objects.bulk_create( [ DraftIssueLabel( @@ -207,7 +203,7 @@ def update(self, instance, validated_data): ) if cycle_id != "not_provided": - DraftIssueCycle.objects.filter(draft_issue=instance).delete(soft=False) + DraftIssueCycle.objects.filter(draft_issue=instance).delete() if cycle_id: DraftIssueCycle.objects.create( cycle_id=cycle_id, @@ -219,7 +215,7 @@ def update(self, instance, validated_data): ) if modules is not None: - DraftIssueModule.objects.filter(draft_issue=instance).delete(soft=False) + DraftIssueModule.objects.filter(draft_issue=instance).delete() DraftIssueModule.objects.bulk_create( [ DraftIssueModule( diff --git a/apiserver/plane/app/serializers/issue.py b/apiserver/plane/app/serializers/issue.py index 22d9dc483df..2323c248a86 100644 --- a/apiserver/plane/app/serializers/issue.py +++ b/apiserver/plane/app/serializers/issue.py @@ -201,7 +201,7 @@ def update(self, instance, validated_data): updated_by_id = instance.updated_by_id if assignees is not None: - IssueAssignee.objects.filter(issue=instance).delete(soft=False) + IssueAssignee.objects.filter(issue=instance).delete() IssueAssignee.objects.bulk_create( [ IssueAssignee( @@ -218,7 +218,7 @@ def update(self, instance, validated_data): ) if labels is not None: - IssueLabel.objects.filter(issue=instance).delete(soft=False) + IssueLabel.objects.filter(issue=instance).delete() IssueLabel.objects.bulk_create( [ IssueLabel( diff --git a/apiserver/plane/app/views/analytic/base.py b/apiserver/plane/app/views/analytic/base.py index ddbde02692e..47b4c1c7007 100644 --- a/apiserver/plane/app/views/analytic/base.py +++ b/apiserver/plane/app/views/analytic/base.py @@ -110,7 +110,10 @@ def get(self, request, slug): if x_axis in ["labels__id"] or segment in ["labels__id"]: label_details = ( Issue.objects.filter( - workspace__slug=slug, **filters, labels__id__isnull=False + workspace__slug=slug, + **filters, + labels__id__isnull=False + & Q(label_issue__deleted_at__isnull=True), ) .distinct("labels__id") .order_by("labels__id") diff --git a/apiserver/plane/app/views/cycle/base.py b/apiserver/plane/app/views/cycle/base.py index e021c4ba1ab..a6199476604 100644 --- a/apiserver/plane/app/views/cycle/base.py +++ b/apiserver/plane/app/views/cycle/base.py @@ -144,6 +144,11 @@ def get_queryset(self): distinct=True, filter=~Q( issue_cycle__issue__assignees__id__isnull=True + ) + & ( + Q( + issue_cycle__issue__issue_assignee__deleted_at__isnull=True + ) ), ), Value([], output_field=ArrayField(UUIDField())), @@ -491,7 +496,7 @@ def destroy(self, request, slug, project_id, pk): origin=request.META.get("HTTP_ORIGIN"), ) # TODO: Soft delete the cycle break the onetoone relationship with cycle issue - cycle.delete(soft=False) + cycle.delete() # Delete the user favorite cycle UserFavorite.objects.filter( diff --git a/apiserver/plane/app/views/cycle/issue.py b/apiserver/plane/app/views/cycle/issue.py index 4774155cb0f..c744897a163 100644 --- a/apiserver/plane/app/views/cycle/issue.py +++ b/apiserver/plane/app/views/cycle/issue.py @@ -358,5 +358,5 @@ def destroy(self, request, slug, project_id, cycle_id, issue_id): notification=True, origin=request.META.get("HTTP_ORIGIN"), ) - cycle_issue.delete(soft=False) + cycle_issue.delete() return Response(status=status.HTTP_204_NO_CONTENT) diff --git a/apiserver/plane/app/views/dashboard/base.py b/apiserver/plane/app/views/dashboard/base.py index 1cc2d3b717d..b65ff0262b2 100644 --- a/apiserver/plane/app/views/dashboard/base.py +++ b/apiserver/plane/app/views/dashboard/base.py @@ -220,7 +220,7 @@ def dashboard_assigned_issues(self, request, slug): distinct=True, filter=( ~Q(labels__id__isnull=True) - & Q(labels__deleted_at__isnull=True) + & Q(label_issue__deleted_at__isnull=True), ), ), Value([], output_field=ArrayField(UUIDField())), @@ -230,7 +230,8 @@ def dashboard_assigned_issues(self, request, slug): "assignees__id", distinct=True, filter=~Q(assignees__id__isnull=True) - & Q(assignees__member_project__is_active=True), + & Q(assignees__member_project__is_active=True) + & Q(issue_assignee__deleted_at__isnull=True) ), Value([], output_field=ArrayField(UUIDField())), ), @@ -389,7 +390,7 @@ def dashboard_created_issues(self, request, slug): distinct=True, filter=( ~Q(labels__id__isnull=True) - & Q(labels__deleted_at__isnull=True) + & Q(label_issue__deleted_at__isnull=True), ), ), Value([], output_field=ArrayField(UUIDField())), @@ -399,7 +400,8 @@ def dashboard_created_issues(self, request, slug): "assignees__id", distinct=True, filter=~Q(assignees__id__isnull=True) - & Q(assignees__member_project__is_active=True), + & Q(assignees__member_project__is_active=True) + & Q(issue_assignee__deleted_at__isnull=True), ), Value([], output_field=ArrayField(UUIDField())), ), diff --git a/apiserver/plane/app/views/inbox/base.py b/apiserver/plane/app/views/inbox/base.py index 03d08573dc8..e72e9da808a 100644 --- a/apiserver/plane/app/views/inbox/base.py +++ b/apiserver/plane/app/views/inbox/base.py @@ -151,7 +151,7 @@ def get_queryset(self): distinct=True, filter=( ~Q(labels__id__isnull=True) - & Q(labels__deleted_at__isnull=True) + & Q(label_issue__deleted_at__isnull=True), ), ), Value([], output_field=ArrayField(UUIDField())), @@ -161,7 +161,8 @@ def get_queryset(self): "assignees__id", distinct=True, filter=~Q(assignees__id__isnull=True) - & Q(assignees__member_project__is_active=True), + & Q(assignees__member_project__is_active=True) + & Q(issue_assignee__deleted_at__isnull=True) ), Value([], output_field=ArrayField(UUIDField())), ), @@ -199,7 +200,7 @@ def list(self, request, slug, project_id): "issue__labels__id", distinct=True, filter=~Q(issue__labels__id__isnull=True) - & Q(issue__labels__deleted_at__isnull=True), + & Q(issue__label_issue__deleted_at__isnull=True), ), Value([], output_field=ArrayField(UUIDField())), ) @@ -313,7 +314,9 @@ def create(self, request, slug, project_id): distinct=True, filter=( ~Q(issue__labels__id__isnull=True) - & Q(issue__labels__deleted_at__isnull=True) + & Q( + issue__label_issue__deleted_at__isnull=True + ) ), ), Value([], output_field=ArrayField(UUIDField())), @@ -378,7 +381,8 @@ def partial_update(self, request, slug, project_id, pk): ArrayAgg( "labels__id", distinct=True, - filter=~Q(labels__id__isnull=True), + filter=~Q(labels__id__isnull=True) + & Q(label_issue__deleted_at__isnull=True), ), Value([], output_field=ArrayField(UUIDField())), ), @@ -386,7 +390,8 @@ def partial_update(self, request, slug, project_id, pk): ArrayAgg( "assignees__id", distinct=True, - filter=~Q(assignees__id__isnull=True), + filter=~Q(assignees__id__isnull=True) + & Q(issue_assignee__deleted_at__isnull=True), ), Value([], output_field=ArrayField(UUIDField())), ), @@ -509,7 +514,10 @@ def partial_update(self, request, slug, project_id, pk): ArrayAgg( "issue__labels__id", distinct=True, - filter=~Q(issue__labels__id__isnull=True), + filter=~Q(issue__labels__id__isnull=True) + & Q( + issue__label_issue__deleted_at__isnull=True + ), ), Value([], output_field=ArrayField(UUIDField())), ), @@ -517,7 +525,8 @@ def partial_update(self, request, slug, project_id, pk): ArrayAgg( "issue__assignees__id", distinct=True, - filter=~Q(issue__assignees__id__isnull=True), + filter=~Q(issue__assignees__id__isnull=True) + & Q(issue__issue_assignee__deleted_at__isnull=True), ), Value([], output_field=ArrayField(UUIDField())), ), @@ -562,7 +571,8 @@ def retrieve(self, request, slug, project_id, pk): ArrayAgg( "issue__labels__id", distinct=True, - filter=~Q(issue__labels__id__isnull=True), + filter=~Q(issue__labels__id__isnull=True) + & Q(issue__label_issue__deleted_at__isnull=True), ), Value([], output_field=ArrayField(UUIDField())), ), @@ -570,7 +580,8 @@ def retrieve(self, request, slug, project_id, pk): ArrayAgg( "issue__assignees__id", distinct=True, - filter=~Q(issue__assignees__id__isnull=True), + filter=~Q(issue__assignees__id__isnull=True) + & Q(issue__issue_assignee__deleted_at__isnull=True), ), Value([], output_field=ArrayField(UUIDField())), ), diff --git a/apiserver/plane/app/views/issue/base.py b/apiserver/plane/app/views/issue/base.py index f0555f477b1..1ee81e1d7c2 100644 --- a/apiserver/plane/app/views/issue/base.py +++ b/apiserver/plane/app/views/issue/base.py @@ -491,7 +491,7 @@ def retrieve(self, request, slug, project_id, pk=None): distinct=True, filter=( ~Q(labels__id__isnull=True) - & Q(labels__deleted_at__isnull=True) + & Q(label_issue__deleted_at__isnull=True) ), ), Value([], output_field=ArrayField(UUIDField())), @@ -501,7 +501,8 @@ def retrieve(self, request, slug, project_id, pk=None): "assignees__id", distinct=True, filter=~Q(assignees__id__isnull=True) - & Q(assignees__member_project__is_active=True), + & Q(assignees__member_project__is_active=True) + & Q(issue_assignee__deleted_at__isnull=True), ), Value([], output_field=ArrayField(UUIDField())), ), @@ -592,7 +593,7 @@ def partial_update(self, request, slug, project_id, pk=None): distinct=True, filter=( ~Q(labels__id__isnull=True) - & Q(labels__deleted_at__isnull=True) + & (Q(label_issue__deleted_at__isnull=True)) ), ), Value([], output_field=ArrayField(UUIDField())), @@ -602,7 +603,8 @@ def partial_update(self, request, slug, project_id, pk=None): "assignees__id", distinct=True, filter=~Q(assignees__id__isnull=True) - & Q(assignees__member_project__is_active=True), + & Q(assignees__member_project__is_active=True) + # & Q(issue_assignee__deleted_at__isnull=True) ), Value([], output_field=ArrayField(UUIDField())), ), @@ -892,7 +894,7 @@ def list(self, request, slug, project_id): distinct=True, filter=( ~Q(labels__id__isnull=True) - & Q(labels__deleted_at__isnull=True) + & Q(label_issue__deleted_at__isnull=True), ), ), Value([], output_field=ArrayField(UUIDField())), @@ -902,7 +904,8 @@ def list(self, request, slug, project_id): "assignees__id", distinct=True, filter=~Q(assignees__id__isnull=True) - & Q(assignees__member_project__is_active=True), + & Q(assignees__member_project__is_active=True) + & Q(issue_assignee__deleted_at__isnull=True), ), Value([], output_field=ArrayField(UUIDField())), ), diff --git a/apiserver/plane/app/views/issue/relation.py b/apiserver/plane/app/views/issue/relation.py index 0b532ddfda0..b3a0b7b4efa 100644 --- a/apiserver/plane/app/views/issue/relation.py +++ b/apiserver/plane/app/views/issue/relation.py @@ -132,7 +132,7 @@ def list(self, request, slug, project_id, issue_id): distinct=True, filter=( ~Q(labels__id__isnull=True) - & Q(labels__deleted_at__isnull=True) + & (Q(label_issue__deleted_at__isnull=True)) ), ), Value([], output_field=ArrayField(UUIDField())), @@ -142,7 +142,8 @@ def list(self, request, slug, project_id, issue_id): "assignees__id", distinct=True, filter=~Q(assignees__id__isnull=True) - & Q(assignees__member_project__is_active=True), + & Q(assignees__member_project__is_active=True) + & Q(issue_assignee__deleted_at__isnull=True), ), Value([], output_field=ArrayField(UUIDField())), ), @@ -289,7 +290,7 @@ def remove_relation(self, request, slug, project_id, issue_id): IssueRelationSerializer(issue_relation).data, cls=DjangoJSONEncoder, ) - issue_relation.delete(soft=False) + issue_relation.delete() issue_activity.delay( type="issue_relation.activity.deleted", requested_data=json.dumps(request.data, cls=DjangoJSONEncoder), diff --git a/apiserver/plane/app/views/issue/sub_issue.py b/apiserver/plane/app/views/issue/sub_issue.py index 445ea6df476..a5b089f6a72 100644 --- a/apiserver/plane/app/views/issue/sub_issue.py +++ b/apiserver/plane/app/views/issue/sub_issue.py @@ -89,7 +89,7 @@ def get(self, request, slug, project_id, issue_id): distinct=True, filter=( ~Q(labels__id__isnull=True) - & Q(labels__deleted_at__isnull=True) + & (Q(label_issue__deleted_at__isnull=True)) ), ), Value([], output_field=ArrayField(UUIDField())), @@ -100,6 +100,7 @@ def get(self, request, slug, project_id, issue_id): distinct=True, filter=~Q(assignees__id__isnull=True) & Q(assignees__member_project__is_active=True), + # & Q(issue_assignee__deleted_at__isnull=True), ), Value([], output_field=ArrayField(UUIDField())), ), diff --git a/apiserver/plane/app/views/module/issue.py b/apiserver/plane/app/views/module/issue.py index 6c0633e2bb0..ae59efbca43 100644 --- a/apiserver/plane/app/views/module/issue.py +++ b/apiserver/plane/app/views/module/issue.py @@ -316,7 +316,7 @@ def create_issue_modules(self, request, slug, project_id, issue_id): notification=True, origin=request.META.get("HTTP_ORIGIN"), ) - module_issue.delete(soft=False) + module_issue.delete() return Response({"message": "success"}, status=status.HTTP_201_CREATED) @@ -341,5 +341,5 @@ def destroy(self, request, slug, project_id, module_id, issue_id): notification=True, origin=request.META.get("HTTP_ORIGIN"), ) - module_issue.delete(soft=False) + module_issue.delete() return Response(status=status.HTTP_204_NO_CONTENT) diff --git a/apiserver/plane/app/views/view/base.py b/apiserver/plane/app/views/view/base.py index 1b708ae2631..65925b29980 100644 --- a/apiserver/plane/app/views/view/base.py +++ b/apiserver/plane/app/views/view/base.py @@ -246,7 +246,7 @@ def get_queryset(self): distinct=True, filter=( ~Q(labels__id__isnull=True) - & Q(labels__deleted_at__isnull=True) + & Q(label_issue__deleted_at__isnull=True), ), ), Value([], output_field=ArrayField(UUIDField())), @@ -256,7 +256,8 @@ def get_queryset(self): "assignees__id", distinct=True, filter=~Q(assignees__id__isnull=True) - & Q(assignees__member_project__is_active=True), + & Q(assignees__member_project__is_active=True) + & Q(issue_assignee__deleted_at__isnull=True) ), Value([], output_field=ArrayField(UUIDField())), ), diff --git a/apiserver/plane/app/views/workspace/draft.py b/apiserver/plane/app/views/workspace/draft.py index e1d3c086dd8..971605d299d 100644 --- a/apiserver/plane/app/views/workspace/draft.py +++ b/apiserver/plane/app/views/workspace/draft.py @@ -73,7 +73,7 @@ def get_queryset(self): distinct=True, filter=( ~Q(labels__id__isnull=True) - & Q(labels__deleted_at__isnull=True) + & (Q(draft_label_issue__deleted_at__isnull=True)) ), ), Value([], output_field=ArrayField(UUIDField())), @@ -83,7 +83,8 @@ def get_queryset(self): "assignees__id", distinct=True, filter=~Q(assignees__id__isnull=True) - & Q(assignees__member_project__is_active=True), + & Q(assignees__member_project__is_active=True) + & Q(draft_issue_assignee__deleted_at__isnull=True), ), Value([], output_field=ArrayField(UUIDField())), ), diff --git a/apiserver/plane/bgtasks/analytic_plot_export.py b/apiserver/plane/bgtasks/analytic_plot_export.py index 7d78b89d06b..a4341841e1c 100644 --- a/apiserver/plane/bgtasks/analytic_plot_export.py +++ b/apiserver/plane/bgtasks/analytic_plot_export.py @@ -130,7 +130,9 @@ def get_label_details(slug, filters): """Fetch label details if required""" return ( Issue.objects.filter( - workspace__slug=slug, **filters, labels__id__isnull=False + workspace__slug=slug, + **filters, + labels__id__isnull=False & Q(label_issue__deleted_at__isnull=True), ) .distinct("labels__id") .order_by("labels__id") diff --git a/apiserver/plane/bgtasks/deletion_task.py b/apiserver/plane/bgtasks/deletion_task.py index b0b2a6eb263..5fea5806bf5 100644 --- a/apiserver/plane/bgtasks/deletion_task.py +++ b/apiserver/plane/bgtasks/deletion_task.py @@ -71,7 +71,7 @@ def hard_delete(): EstimatePoint, ) - days = settings.HARD_DELETE_AFTER_DAYS + days = 60 # check delete workspace _ = Workspace.all_objects.filter( deleted_at__lt=timezone.now() - timezone.timedelta(days=days) diff --git a/apiserver/plane/celery.py b/apiserver/plane/celery.py index 865ef95fae5..b8706a01ac1 100644 --- a/apiserver/plane/celery.py +++ b/apiserver/plane/celery.py @@ -36,10 +36,6 @@ "task": "plane.bgtasks.api_logs_task.delete_api_logs", "schedule": crontab(hour=0, minute=0), }, - "check-every-day-to-delete-hard-delete": { - "task": "plane.bgtasks.deletion_task.hard_delete", - "schedule": crontab(hour=0, minute=0), - }, "run-every-6-hours-for-instance-trace": { "task": "plane.license.bgtasks.tracer.instance_traces", "schedule": crontab(hour="*/6"), diff --git a/apiserver/plane/db/migrations/0082_alter_issue_managers_alter_cycleissue_issue_and_more.py b/apiserver/plane/db/migrations/0082_alter_issue_managers_alter_cycleissue_issue_and_more.py new file mode 100644 index 00000000000..1682b22b55e --- /dev/null +++ b/apiserver/plane/db/migrations/0082_alter_issue_managers_alter_cycleissue_issue_and_more.py @@ -0,0 +1,39 @@ +# Generated by Django 4.2.15 on 2024-10-21 13:59 + +from django.db import migrations, models +import django.db.models.deletion +import django.db.models.manager + + +class Migration(migrations.Migration): + + dependencies = [ + ('db', '0081_remove_globalview_created_by_and_more'), + ] + + operations = [ + migrations.AlterModelManagers( + name='issue', + managers=[ + ('issue_objects', django.db.models.manager.Manager()), + ], + ), + migrations.AlterField( + model_name='cycleissue', + name='issue', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='issue_cycle', to='db.issue'), + ), + migrations.AlterField( + model_name='draftissuecycle', + name='draft_issue', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='draft_issue_cycle', to='db.draftissue'), + ), + migrations.AlterUniqueTogether( + name='cycleissue', + unique_together={('issue', 'cycle', 'deleted_at')}, + ), + migrations.AlterUniqueTogether( + name='draftissuecycle', + unique_together={('draft_issue', 'cycle', 'deleted_at')}, + ), + ] diff --git a/apiserver/plane/db/models/cycle.py b/apiserver/plane/db/models/cycle.py index f9f9eece966..70edaf3df0f 100644 --- a/apiserver/plane/db/models/cycle.py +++ b/apiserver/plane/db/models/cycle.py @@ -110,7 +110,7 @@ class CycleIssue(ProjectBaseModel): Cycle Issues """ - issue = models.OneToOneField( + issue = models.ForeignKey( "db.Issue", on_delete=models.CASCADE, related_name="issue_cycle" ) cycle = models.ForeignKey( @@ -118,6 +118,7 @@ class CycleIssue(ProjectBaseModel): ) class Meta: + unique_together = ["issue", "cycle", "deleted_at"] verbose_name = "Cycle Issue" verbose_name_plural = "Cycle Issues" db_table = "cycle_issues" diff --git a/apiserver/plane/db/models/draft.py b/apiserver/plane/db/models/draft.py index 671b89ff1fa..c0055df06bc 100644 --- a/apiserver/plane/db/models/draft.py +++ b/apiserver/plane/db/models/draft.py @@ -234,7 +234,7 @@ class DraftIssueCycle(WorkspaceBaseModel): Draft Issue Cycles """ - draft_issue = models.OneToOneField( + draft_issue = models.ForeignKey( "db.DraftIssue", on_delete=models.CASCADE, related_name="draft_issue_cycle", @@ -244,6 +244,7 @@ class DraftIssueCycle(WorkspaceBaseModel): ) class Meta: + unique_together = ["draft_issue", "cycle", "deleted_at"] verbose_name = "Draft Issue Cycle" verbose_name_plural = "Draft Issue Cycles" db_table = "draft_issue_cycles" diff --git a/apiserver/plane/settings/common.py b/apiserver/plane/settings/common.py index 6e9c98ce1e7..764f49d5f79 100644 --- a/apiserver/plane/settings/common.py +++ b/apiserver/plane/settings/common.py @@ -382,8 +382,6 @@ SPACE_BASE_URL = os.environ.get("SPACE_BASE_URL", None) APP_BASE_URL = os.environ.get("APP_BASE_URL") -HARD_DELETE_AFTER_DAYS = int(os.environ.get("HARD_DELETE_AFTER_DAYS", 60)) - ATTACHMENT_MIME_TYPES = [ # Images "image/jpeg", diff --git a/apiserver/plane/space/serializer/issue.py b/apiserver/plane/space/serializer/issue.py index cf628e85035..d7447681f60 100644 --- a/apiserver/plane/space/serializer/issue.py +++ b/apiserver/plane/space/serializer/issue.py @@ -421,7 +421,7 @@ def update(self, instance, validated_data): updated_by_id = instance.updated_by_id if assignees is not None: - IssueAssignee.objects.filter(issue=instance).delete(soft=False) + IssueAssignee.objects.filter(issue=instance).delete() IssueAssignee.objects.bulk_create( [ IssueAssignee( @@ -438,7 +438,7 @@ def update(self, instance, validated_data): ) if labels is not None: - IssueLabel.objects.filter(issue=instance).delete(soft=False) + IssueLabel.objects.filter(issue=instance).delete() IssueLabel.objects.bulk_create( [ IssueLabel( diff --git a/apiserver/plane/space/utils/grouper.py b/apiserver/plane/space/utils/grouper.py index a1eb16b9c82..68035979081 100644 --- a/apiserver/plane/space/utils/grouper.py +++ b/apiserver/plane/space/utils/grouper.py @@ -35,8 +35,16 @@ def issue_queryset_grouper(queryset, group_by, sub_group_by): } annotations_map = { - "assignee_ids": ("assignees__id", ~Q(assignees__id__isnull=True)), - "label_ids": ("labels__id", ~Q(labels__id__isnull=True)), + "assignee_ids": ( + "assignees__id", + ~Q(assignees__id__isnull=True) + & Q(issue_assignee__deleted_at__isnull=True), + ), + "label_ids": ( + "labels__id", + ~Q(labels__id__isnull=True) + & Q(label_issue__deleted_at__isnull=True), + ), "module_ids": ( "issue_module__module_id", ~Q(issue_module__module_id__isnull=True), diff --git a/apiserver/plane/space/views/issue.py b/apiserver/plane/space/views/issue.py index c6993c17e51..d8ad55ce22a 100644 --- a/apiserver/plane/space/views/issue.py +++ b/apiserver/plane/space/views/issue.py @@ -719,7 +719,7 @@ def get(self, request, anchor, issue_id): distinct=True, filter=( ~Q(labels__id__isnull=True) - & Q(labels__deleted_at__isnull=True) + & Q(label_issue__deleted_at__isnull=True), ), ), Value([], output_field=ArrayField(UUIDField())), @@ -729,7 +729,8 @@ def get(self, request, anchor, issue_id): "assignees__id", distinct=True, filter=~Q(assignees__id__isnull=True) - & Q(assignees__member_project__is_active=True), + & Q(assignees__member_project__is_active=True) + & Q(issue_assignee__deleted_at__isnull=True), ), Value([], output_field=ArrayField(UUIDField())), ), diff --git a/apiserver/plane/utils/grouper.py b/apiserver/plane/utils/grouper.py index 4fb532a253e..38ac74a1647 100644 --- a/apiserver/plane/utils/grouper.py +++ b/apiserver/plane/utils/grouper.py @@ -25,10 +25,15 @@ def issue_queryset_grouper(queryset, group_by, sub_group_by): } annotations_map = { - "assignee_ids": ("assignees__id", ~Q(assignees__id__isnull=True)), + "assignee_ids": ( + "assignees__id", + ~Q(assignees__id__isnull=True) + & Q(issue_assignee__deleted_at__isnull=True), + ), "label_ids": ( "labels__id", - ~Q(labels__id__isnull=True) & (Q(labels__deleted_at__isnull=True)), + ~Q(labels__id__isnull=True) + & Q(label_issue__deleted_at__isnull=True), ), "module_ids": ( "issue_module__module_id", diff --git a/apiserver/plane/utils/issue_filters.py b/apiserver/plane/utils/issue_filters.py index 713276d0cdb..b82ba1e8c75 100644 --- a/apiserver/plane/utils/issue_filters.py +++ b/apiserver/plane/utils/issue_filters.py @@ -48,14 +48,22 @@ def string_date_filter( if term == "weeks": if subsequent == "after": if offset == "fromnow": - issue_filter[f"{date_filter}__gte"] = now + timedelta(weeks=duration) + issue_filter[f"{date_filter}__gte"] = now + timedelta( + weeks=duration + ) else: - issue_filter[f"{date_filter}__gte"] = now - timedelta(weeks=duration) + issue_filter[f"{date_filter}__gte"] = now - timedelta( + weeks=duration + ) else: if offset == "fromnow": - issue_filter[f"{date_filter}__lte"] = now + timedelta(weeks=duration) + issue_filter[f"{date_filter}__lte"] = now + timedelta( + weeks=duration + ) else: - issue_filter[f"{date_filter}__lte"] = now - timedelta(weeks=duration) + issue_filter[f"{date_filter}__lte"] = now - timedelta( + weeks=duration + ) def date_filter(issue_filter, date_term, queries): @@ -120,7 +128,9 @@ def filter_state_group(params, issue_filter, method, prefix=""): and len(params.get("state_group")) and params.get("state_group") != "null" ): - issue_filter[f"{prefix}state__group__in"] = params.get("state_group") + issue_filter[f"{prefix}state__group__in"] = params.get( + "state_group" + ) return issue_filter @@ -242,8 +252,8 @@ def filter_mentions(params, issue_filter, method, prefix=""): and len(params.get("mentions")) and params.get("mentions") != "null" ): - issue_filter[f"{prefix}issue_mention__mention__id__in"] = params.get( - "mentions" + issue_filter[f"{prefix}issue_mention__mention__id__in"] = ( + params.get("mentions") ) return issue_filter @@ -411,7 +421,10 @@ def filter_cycle(params, issue_filter, method, prefix=""): and len(params.get("cycle")) and params.get("cycle") != "null" ): - issue_filter[f"{prefix}issue_cycle__cycle_id__in"] = params.get("cycle") + issue_filter[f"{prefix}issue_cycle__cycle_id__in"] = params.get( + "cycle" + ) + issue_filter[f"{prefix}issue_cycle__deleted_at__isnull"] = True return issue_filter @@ -434,6 +447,7 @@ def filter_module(params, issue_filter, method, prefix=""): issue_filter[f"{prefix}issue_module__module_id__in"] = params.get( "module" ) + issue_filter[f"{prefix}issue_module__deleted_at__isnull"] = True return issue_filter From 1f3c287c8bfa5ae692b2581f6a78ffbfbf49c1b5 Mon Sep 17 00:00:00 2001 From: NarayanBavisetti Date: Tue, 22 Oct 2024 13:19:42 +0530 Subject: [PATCH 3/6] chore: added the deletion task --- apiserver/plane/bgtasks/deletion_task.py | 2 +- apiserver/plane/celery.py | 4 ++++ apiserver/plane/settings/common.py | 2 ++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/apiserver/plane/bgtasks/deletion_task.py b/apiserver/plane/bgtasks/deletion_task.py index 5fea5806bf5..b0b2a6eb263 100644 --- a/apiserver/plane/bgtasks/deletion_task.py +++ b/apiserver/plane/bgtasks/deletion_task.py @@ -71,7 +71,7 @@ def hard_delete(): EstimatePoint, ) - days = 60 + days = settings.HARD_DELETE_AFTER_DAYS # check delete workspace _ = Workspace.all_objects.filter( deleted_at__lt=timezone.now() - timezone.timedelta(days=days) diff --git a/apiserver/plane/celery.py b/apiserver/plane/celery.py index b8706a01ac1..c58844de33a 100644 --- a/apiserver/plane/celery.py +++ b/apiserver/plane/celery.py @@ -32,6 +32,10 @@ "task": "plane.bgtasks.email_notification_task.stack_email_notification", "schedule": crontab(minute="*/5"), }, + "check-every-day-to-delete-hard-delete": { + "task": "plane.bgtasks.deletion_task.hard_delete", + "schedule": crontab(hour=0, minute=0), + }, "check-every-day-to-delete-api-logs": { "task": "plane.bgtasks.api_logs_task.delete_api_logs", "schedule": crontab(hour=0, minute=0), diff --git a/apiserver/plane/settings/common.py b/apiserver/plane/settings/common.py index 764f49d5f79..6e9c98ce1e7 100644 --- a/apiserver/plane/settings/common.py +++ b/apiserver/plane/settings/common.py @@ -382,6 +382,8 @@ SPACE_BASE_URL = os.environ.get("SPACE_BASE_URL", None) APP_BASE_URL = os.environ.get("APP_BASE_URL") +HARD_DELETE_AFTER_DAYS = int(os.environ.get("HARD_DELETE_AFTER_DAYS", 60)) + ATTACHMENT_MIME_TYPES = [ # Images "image/jpeg", From 757219da98bd60b4700e7c538cd2a3ca1d5beb37 Mon Sep 17 00:00:00 2001 From: NarayanBavisetti Date: Tue, 22 Oct 2024 13:20:51 +0530 Subject: [PATCH 4/6] chore: updated the env example --- apiserver/.env.example | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apiserver/.env.example b/apiserver/.env.example index 9d25523c5b9..33ef5c4cdf6 100644 --- a/apiserver/.env.example +++ b/apiserver/.env.example @@ -56,3 +56,7 @@ GUNICORN_WORKERS=2 ADMIN_BASE_URL= SPACE_BASE_URL= APP_BASE_URL= + + +# Hard delete files after days +HARD_DELETE_AFTER_DAYS=60 \ No newline at end of file From a3c4e7e6f59bc62a9d7b5a1ace01607b488d5d90 Mon Sep 17 00:00:00 2001 From: NarayanBavisetti Date: Tue, 22 Oct 2024 13:27:57 +0530 Subject: [PATCH 5/6] chore: cycle issue unique constraints --- ...anagers_alter_cycleissue_issue_and_more.py | 50 ++++++++++++++----- apiserver/plane/db/models/cycle.py | 7 +++ apiserver/plane/db/models/draft.py | 7 +++ 3 files changed, 51 insertions(+), 13 deletions(-) diff --git a/apiserver/plane/db/migrations/0082_alter_issue_managers_alter_cycleissue_issue_and_more.py b/apiserver/plane/db/migrations/0082_alter_issue_managers_alter_cycleissue_issue_and_more.py index 1682b22b55e..e26ed9052f4 100644 --- a/apiserver/plane/db/migrations/0082_alter_issue_managers_alter_cycleissue_issue_and_more.py +++ b/apiserver/plane/db/migrations/0082_alter_issue_managers_alter_cycleissue_issue_and_more.py @@ -8,32 +8,56 @@ class Migration(migrations.Migration): dependencies = [ - ('db', '0081_remove_globalview_created_by_and_more'), + ("db", "0081_remove_globalview_created_by_and_more"), ] operations = [ migrations.AlterModelManagers( - name='issue', + name="issue", managers=[ - ('issue_objects', django.db.models.manager.Manager()), + ("issue_objects", django.db.models.manager.Manager()), ], ), migrations.AlterField( - model_name='cycleissue', - name='issue', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='issue_cycle', to='db.issue'), + model_name="cycleissue", + name="issue", + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="issue_cycle", + to="db.issue", + ), ), migrations.AlterField( - model_name='draftissuecycle', - name='draft_issue', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='draft_issue_cycle', to='db.draftissue'), + model_name="draftissuecycle", + name="draft_issue", + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="draft_issue_cycle", + to="db.draftissue", + ), ), migrations.AlterUniqueTogether( - name='cycleissue', - unique_together={('issue', 'cycle', 'deleted_at')}, + name="cycleissue", + unique_together={("issue", "cycle", "deleted_at")}, ), migrations.AlterUniqueTogether( - name='draftissuecycle', - unique_together={('draft_issue', 'cycle', 'deleted_at')}, + name="draftissuecycle", + unique_together={("draft_issue", "cycle", "deleted_at")}, + ), + migrations.AddConstraint( + model_name="cycleissue", + constraint=models.UniqueConstraint( + condition=models.Q(("deleted_at__isnull", True)), + fields=("cycle", "issue"), + name="cycle_issue_when_deleted_at_null", + ), + ), + migrations.AddConstraint( + model_name="draftissuecycle", + constraint=models.UniqueConstraint( + condition=models.Q(("deleted_at__isnull", True)), + fields=("draft_issue", "cycle"), + name="draft_issue_cycle_when_deleted_at_null", + ), ), ] diff --git a/apiserver/plane/db/models/cycle.py b/apiserver/plane/db/models/cycle.py index 70edaf3df0f..c3dccb0c8b4 100644 --- a/apiserver/plane/db/models/cycle.py +++ b/apiserver/plane/db/models/cycle.py @@ -119,6 +119,13 @@ class CycleIssue(ProjectBaseModel): class Meta: unique_together = ["issue", "cycle", "deleted_at"] + constraints = [ + models.UniqueConstraint( + fields=["cycle", "issue"], + condition=models.Q(deleted_at__isnull=True), + name="cycle_issue_when_deleted_at_null", + ) + ] verbose_name = "Cycle Issue" verbose_name_plural = "Cycle Issues" db_table = "cycle_issues" diff --git a/apiserver/plane/db/models/draft.py b/apiserver/plane/db/models/draft.py index c0055df06bc..e80ccdaafb2 100644 --- a/apiserver/plane/db/models/draft.py +++ b/apiserver/plane/db/models/draft.py @@ -245,6 +245,13 @@ class DraftIssueCycle(WorkspaceBaseModel): class Meta: unique_together = ["draft_issue", "cycle", "deleted_at"] + constraints = [ + models.UniqueConstraint( + fields=["draft_issue", "cycle"], + condition=models.Q(deleted_at__isnull=True), + name="draft_issue_cycle_when_deleted_at_null", + ) + ] verbose_name = "Draft Issue Cycle" verbose_name_plural = "Draft Issue Cycles" db_table = "draft_issue_cycles" From 59a3580174e71a15a13320fea874c4389e9a0e46 Mon Sep 17 00:00:00 2001 From: NarayanBavisetti Date: Tue, 22 Oct 2024 14:14:26 +0530 Subject: [PATCH 6/6] chore: udpated the Q operator --- apiserver/plane/api/views/inbox.py | 9 ++- apiserver/plane/app/views/dashboard/base.py | 36 +++++++----- apiserver/plane/app/views/inbox/base.py | 48 ++++++++------- apiserver/plane/app/views/issue/base.py | 58 +++++++++++-------- apiserver/plane/app/views/issue/relation.py | 6 +- apiserver/plane/app/views/issue/sub_issue.py | 20 ++++--- apiserver/plane/app/views/view/base.py | 18 +++--- apiserver/plane/app/views/workspace/draft.py | 10 ++-- ...anagers_alter_cycleissue_issue_and_more.py | 2 +- apiserver/plane/space/views/issue.py | 6 +- 10 files changed, 124 insertions(+), 89 deletions(-) diff --git a/apiserver/plane/api/views/inbox.py b/apiserver/plane/api/views/inbox.py index 216105fe693..381e12aab07 100644 --- a/apiserver/plane/api/views/inbox.py +++ b/apiserver/plane/api/views/inbox.py @@ -227,8 +227,10 @@ def patch(self, request, slug, project_id, issue_id): ArrayAgg( "labels__id", distinct=True, - filter=~Q(labels__id__isnull=True) - & Q(label_issue__deleted_at__isnull=True), + filter=Q( + ~Q(labels__id__isnull=True) + & Q(label_issue__deleted_at__isnull=True), + ), ), Value([], output_field=ArrayField(UUIDField())), ), @@ -236,8 +238,9 @@ def patch(self, request, slug, project_id, issue_id): ArrayAgg( "assignees__id", distinct=True, - filter=( + filter=Q( ~Q(assignees__id__isnull=True) + & Q(assignees__member_project__is_active=True) & Q(issue_assignee__deleted_at__isnull=True) ), ), diff --git a/apiserver/plane/app/views/dashboard/base.py b/apiserver/plane/app/views/dashboard/base.py index b65ff0262b2..3bfa0fe56e8 100644 --- a/apiserver/plane/app/views/dashboard/base.py +++ b/apiserver/plane/app/views/dashboard/base.py @@ -218,7 +218,7 @@ def dashboard_assigned_issues(self, request, slug): ArrayAgg( "labels__id", distinct=True, - filter=( + filter=Q( ~Q(labels__id__isnull=True) & Q(label_issue__deleted_at__isnull=True), ), @@ -229,9 +229,11 @@ def dashboard_assigned_issues(self, request, slug): ArrayAgg( "assignees__id", distinct=True, - filter=~Q(assignees__id__isnull=True) - & Q(assignees__member_project__is_active=True) - & Q(issue_assignee__deleted_at__isnull=True) + filter=Q( + ~Q(assignees__id__isnull=True) + & Q(assignees__member_project__is_active=True) + & Q(issue_assignee__deleted_at__isnull=True) + ), ), Value([], output_field=ArrayField(UUIDField())), ), @@ -239,9 +241,11 @@ def dashboard_assigned_issues(self, request, slug): ArrayAgg( "issue_module__module_id", distinct=True, - filter=~Q(issue_module__module_id__isnull=True) - & Q(issue_module__module__archived_at__isnull=True) - & Q(issue_module__deleted_at__isnull=True), + filter=Q( + ~Q(issue_module__module_id__isnull=True) + & Q(issue_module__module__archived_at__isnull=True) + & Q(issue_module__deleted_at__isnull=True) + ), ), Value([], output_field=ArrayField(UUIDField())), ), @@ -388,7 +392,7 @@ def dashboard_created_issues(self, request, slug): ArrayAgg( "labels__id", distinct=True, - filter=( + filter=Q( ~Q(labels__id__isnull=True) & Q(label_issue__deleted_at__isnull=True), ), @@ -399,9 +403,11 @@ def dashboard_created_issues(self, request, slug): ArrayAgg( "assignees__id", distinct=True, - filter=~Q(assignees__id__isnull=True) - & Q(assignees__member_project__is_active=True) - & Q(issue_assignee__deleted_at__isnull=True), + filter=Q( + ~Q(assignees__id__isnull=True) + & Q(assignees__member_project__is_active=True) + & Q(issue_assignee__deleted_at__isnull=True) + ), ), Value([], output_field=ArrayField(UUIDField())), ), @@ -409,9 +415,11 @@ def dashboard_created_issues(self, request, slug): ArrayAgg( "issue_module__module_id", distinct=True, - filter=~Q(issue_module__module_id__isnull=True) - & Q(issue_module__module__archived_at__isnull=True) - & Q(issue_module__deleted_at__isnull=True), + filter=Q( + ~Q(issue_module__module_id__isnull=True) + & Q(issue_module__module__archived_at__isnull=True) + & Q(issue_module__deleted_at__isnull=True) + ), ), Value([], output_field=ArrayField(UUIDField())), ), diff --git a/apiserver/plane/app/views/inbox/base.py b/apiserver/plane/app/views/inbox/base.py index e72e9da808a..62da2b25152 100644 --- a/apiserver/plane/app/views/inbox/base.py +++ b/apiserver/plane/app/views/inbox/base.py @@ -149,7 +149,7 @@ def get_queryset(self): ArrayAgg( "labels__id", distinct=True, - filter=( + filter=Q( ~Q(labels__id__isnull=True) & Q(label_issue__deleted_at__isnull=True), ), @@ -160,9 +160,11 @@ def get_queryset(self): ArrayAgg( "assignees__id", distinct=True, - filter=~Q(assignees__id__isnull=True) - & Q(assignees__member_project__is_active=True) - & Q(issue_assignee__deleted_at__isnull=True) + filter=Q( + ~Q(assignees__id__isnull=True) + & Q(assignees__member_project__is_active=True) + & Q(issue_assignee__deleted_at__isnull=True) + ), ), Value([], output_field=ArrayField(UUIDField())), ), @@ -170,9 +172,11 @@ def get_queryset(self): ArrayAgg( "issue_module__module_id", distinct=True, - filter=~Q(issue_module__module_id__isnull=True) - & Q(issue_module__module__archived_at__isnull=True) - & Q(issue_module__deleted_at__isnull=True), + filter=Q( + ~Q(issue_module__module_id__isnull=True) + & Q(issue_module__module__archived_at__isnull=True) + & Q(issue_module__deleted_at__isnull=True) + ), ), Value([], output_field=ArrayField(UUIDField())), ), @@ -199,8 +203,8 @@ def list(self, request, slug, project_id): ArrayAgg( "issue__labels__id", distinct=True, - filter=~Q(issue__labels__id__isnull=True) - & Q(issue__label_issue__deleted_at__isnull=True), + filter=Q(~Q(issue__labels__id__isnull=True) + & Q(issue__label_issue__deleted_at__isnull=True)), ), Value([], output_field=ArrayField(UUIDField())), ) @@ -312,7 +316,7 @@ def create(self, request, slug, project_id): ArrayAgg( "issue__labels__id", distinct=True, - filter=( + filter=Q( ~Q(issue__labels__id__isnull=True) & Q( issue__label_issue__deleted_at__isnull=True @@ -381,8 +385,8 @@ def partial_update(self, request, slug, project_id, pk): ArrayAgg( "labels__id", distinct=True, - filter=~Q(labels__id__isnull=True) - & Q(label_issue__deleted_at__isnull=True), + filter=Q(~Q(labels__id__isnull=True) + & Q(label_issue__deleted_at__isnull=True)), ), Value([], output_field=ArrayField(UUIDField())), ), @@ -390,8 +394,8 @@ def partial_update(self, request, slug, project_id, pk): ArrayAgg( "assignees__id", distinct=True, - filter=~Q(assignees__id__isnull=True) - & Q(issue_assignee__deleted_at__isnull=True), + filter=Q(~Q(assignees__id__isnull=True) + & Q(issue_assignee__deleted_at__isnull=True)), ), Value([], output_field=ArrayField(UUIDField())), ), @@ -514,10 +518,10 @@ def partial_update(self, request, slug, project_id, pk): ArrayAgg( "issue__labels__id", distinct=True, - filter=~Q(issue__labels__id__isnull=True) + filter=Q(~Q(issue__labels__id__isnull=True) & Q( issue__label_issue__deleted_at__isnull=True - ), + )), ), Value([], output_field=ArrayField(UUIDField())), ), @@ -525,8 +529,8 @@ def partial_update(self, request, slug, project_id, pk): ArrayAgg( "issue__assignees__id", distinct=True, - filter=~Q(issue__assignees__id__isnull=True) - & Q(issue__issue_assignee__deleted_at__isnull=True), + filter=Q(~Q(issue__assignees__id__isnull=True) + & Q(issue__issue_assignee__deleted_at__isnull=True)), ), Value([], output_field=ArrayField(UUIDField())), ), @@ -571,8 +575,8 @@ def retrieve(self, request, slug, project_id, pk): ArrayAgg( "issue__labels__id", distinct=True, - filter=~Q(issue__labels__id__isnull=True) - & Q(issue__label_issue__deleted_at__isnull=True), + filter=Q(~Q(issue__labels__id__isnull=True) + & Q(issue__label_issue__deleted_at__isnull=True)), ), Value([], output_field=ArrayField(UUIDField())), ), @@ -580,8 +584,8 @@ def retrieve(self, request, slug, project_id, pk): ArrayAgg( "issue__assignees__id", distinct=True, - filter=~Q(issue__assignees__id__isnull=True) - & Q(issue__issue_assignee__deleted_at__isnull=True), + filter=Q(~Q(issue__assignees__id__isnull=True) + & Q(issue__issue_assignee__deleted_at__isnull=True)), ), Value([], output_field=ArrayField(UUIDField())), ), diff --git a/apiserver/plane/app/views/issue/base.py b/apiserver/plane/app/views/issue/base.py index 1ee81e1d7c2..7bc3dd10e14 100644 --- a/apiserver/plane/app/views/issue/base.py +++ b/apiserver/plane/app/views/issue/base.py @@ -489,9 +489,9 @@ def retrieve(self, request, slug, project_id, pk=None): ArrayAgg( "labels__id", distinct=True, - filter=( + filter=Q( ~Q(labels__id__isnull=True) - & Q(label_issue__deleted_at__isnull=True) + & Q(label_issue__deleted_at__isnull=True), ), ), Value([], output_field=ArrayField(UUIDField())), @@ -500,9 +500,11 @@ def retrieve(self, request, slug, project_id, pk=None): ArrayAgg( "assignees__id", distinct=True, - filter=~Q(assignees__id__isnull=True) - & Q(assignees__member_project__is_active=True) - & Q(issue_assignee__deleted_at__isnull=True), + filter=Q( + ~Q(assignees__id__isnull=True) + & Q(assignees__member_project__is_active=True) + & Q(issue_assignee__deleted_at__isnull=True) + ), ), Value([], output_field=ArrayField(UUIDField())), ), @@ -510,9 +512,11 @@ def retrieve(self, request, slug, project_id, pk=None): ArrayAgg( "issue_module__module_id", distinct=True, - filter=~Q(issue_module__module_id__isnull=True) - & Q(issue_module__module__archived_at__isnull=True) - & Q(issue_module__deleted_at__isnull=True), + filter=Q( + ~Q(issue_module__module_id__isnull=True) + & Q(issue_module__module__archived_at__isnull=True) + & Q(issue_module__deleted_at__isnull=True) + ), ), Value([], output_field=ArrayField(UUIDField())), ), @@ -591,9 +595,9 @@ def partial_update(self, request, slug, project_id, pk=None): ArrayAgg( "labels__id", distinct=True, - filter=( + filter=Q( ~Q(labels__id__isnull=True) - & (Q(label_issue__deleted_at__isnull=True)) + & Q(label_issue__deleted_at__isnull=True), ), ), Value([], output_field=ArrayField(UUIDField())), @@ -602,9 +606,11 @@ def partial_update(self, request, slug, project_id, pk=None): ArrayAgg( "assignees__id", distinct=True, - filter=~Q(assignees__id__isnull=True) - & Q(assignees__member_project__is_active=True) - # & Q(issue_assignee__deleted_at__isnull=True) + filter=Q( + ~Q(assignees__id__isnull=True) + & Q(assignees__member_project__is_active=True) + & Q(issue_assignee__deleted_at__isnull=True) + ), ), Value([], output_field=ArrayField(UUIDField())), ), @@ -612,9 +618,11 @@ def partial_update(self, request, slug, project_id, pk=None): ArrayAgg( "issue_module__module_id", distinct=True, - filter=~Q(issue_module__module_id__isnull=True) - & Q(issue_module__module__archived_at__isnull=True) - & Q(issue_module__deleted_at__isnull=True), + filter=Q( + ~Q(issue_module__module_id__isnull=True) + & Q(issue_module__module__archived_at__isnull=True) + & Q(issue_module__deleted_at__isnull=True) + ), ), Value([], output_field=ArrayField(UUIDField())), ), @@ -892,7 +900,7 @@ def list(self, request, slug, project_id): ArrayAgg( "labels__id", distinct=True, - filter=( + filter=Q( ~Q(labels__id__isnull=True) & Q(label_issue__deleted_at__isnull=True), ), @@ -903,9 +911,11 @@ def list(self, request, slug, project_id): ArrayAgg( "assignees__id", distinct=True, - filter=~Q(assignees__id__isnull=True) - & Q(assignees__member_project__is_active=True) - & Q(issue_assignee__deleted_at__isnull=True), + filter=Q( + ~Q(assignees__id__isnull=True) + & Q(assignees__member_project__is_active=True) + & Q(issue_assignee__deleted_at__isnull=True) + ), ), Value([], output_field=ArrayField(UUIDField())), ), @@ -913,9 +923,11 @@ def list(self, request, slug, project_id): ArrayAgg( "issue_module__module_id", distinct=True, - filter=~Q(issue_module__module_id__isnull=True) - & Q(issue_module__module__archived_at__isnull=True) - & Q(issue_module__deleted_at__isnull=True), + filter=Q( + ~Q(issue_module__module_id__isnull=True) + & Q(issue_module__module__archived_at__isnull=True) + & Q(issue_module__deleted_at__isnull=True) + ), ), Value([], output_field=ArrayField(UUIDField())), ), diff --git a/apiserver/plane/app/views/issue/relation.py b/apiserver/plane/app/views/issue/relation.py index b3a0b7b4efa..20243a11ce2 100644 --- a/apiserver/plane/app/views/issue/relation.py +++ b/apiserver/plane/app/views/issue/relation.py @@ -130,7 +130,7 @@ def list(self, request, slug, project_id, issue_id): ArrayAgg( "labels__id", distinct=True, - filter=( + filter=Q( ~Q(labels__id__isnull=True) & (Q(label_issue__deleted_at__isnull=True)) ), @@ -141,9 +141,9 @@ def list(self, request, slug, project_id, issue_id): ArrayAgg( "assignees__id", distinct=True, - filter=~Q(assignees__id__isnull=True) + filter=Q(~Q(assignees__id__isnull=True) & Q(assignees__member_project__is_active=True) - & Q(issue_assignee__deleted_at__isnull=True), + & Q(issue_assignee__deleted_at__isnull=True)), ), Value([], output_field=ArrayField(UUIDField())), ), diff --git a/apiserver/plane/app/views/issue/sub_issue.py b/apiserver/plane/app/views/issue/sub_issue.py index a5b089f6a72..02f3b6147b4 100644 --- a/apiserver/plane/app/views/issue/sub_issue.py +++ b/apiserver/plane/app/views/issue/sub_issue.py @@ -87,9 +87,9 @@ def get(self, request, slug, project_id, issue_id): ArrayAgg( "labels__id", distinct=True, - filter=( + filter=Q( ~Q(labels__id__isnull=True) - & (Q(label_issue__deleted_at__isnull=True)) + & Q(label_issue__deleted_at__isnull=True), ), ), Value([], output_field=ArrayField(UUIDField())), @@ -98,9 +98,11 @@ def get(self, request, slug, project_id, issue_id): ArrayAgg( "assignees__id", distinct=True, - filter=~Q(assignees__id__isnull=True) - & Q(assignees__member_project__is_active=True), - # & Q(issue_assignee__deleted_at__isnull=True), + filter=Q( + ~Q(assignees__id__isnull=True) + & Q(assignees__member_project__is_active=True) + & Q(issue_assignee__deleted_at__isnull=True) + ), ), Value([], output_field=ArrayField(UUIDField())), ), @@ -108,9 +110,11 @@ def get(self, request, slug, project_id, issue_id): ArrayAgg( "issue_module__module_id", distinct=True, - filter=~Q(issue_module__module_id__isnull=True) - & Q(issue_module__module__archived_at__isnull=True) - & Q(issue_module__deleted_at__isnull=True), + filter=Q( + ~Q(issue_module__module_id__isnull=True) + & Q(issue_module__module__archived_at__isnull=True) + & Q(issue_module__deleted_at__isnull=True) + ), ), Value([], output_field=ArrayField(UUIDField())), ), diff --git a/apiserver/plane/app/views/view/base.py b/apiserver/plane/app/views/view/base.py index 65925b29980..a14e761a552 100644 --- a/apiserver/plane/app/views/view/base.py +++ b/apiserver/plane/app/views/view/base.py @@ -244,7 +244,7 @@ def get_queryset(self): ArrayAgg( "labels__id", distinct=True, - filter=( + filter=Q( ~Q(labels__id__isnull=True) & Q(label_issue__deleted_at__isnull=True), ), @@ -255,9 +255,11 @@ def get_queryset(self): ArrayAgg( "assignees__id", distinct=True, - filter=~Q(assignees__id__isnull=True) - & Q(assignees__member_project__is_active=True) - & Q(issue_assignee__deleted_at__isnull=True) + filter=Q( + ~Q(assignees__id__isnull=True) + & Q(assignees__member_project__is_active=True) + & Q(issue_assignee__deleted_at__isnull=True) + ), ), Value([], output_field=ArrayField(UUIDField())), ), @@ -265,9 +267,11 @@ def get_queryset(self): ArrayAgg( "issue_module__module_id", distinct=True, - filter=~Q(issue_module__module_id__isnull=True) - & Q(issue_module__module__archived_at__isnull=True) - & Q(issue_module__deleted_at__isnull=True), + filter=Q( + ~Q(issue_module__module_id__isnull=True) + & Q(issue_module__module__archived_at__isnull=True) + & Q(issue_module__deleted_at__isnull=True) + ), ), Value([], output_field=ArrayField(UUIDField())), ), diff --git a/apiserver/plane/app/views/workspace/draft.py b/apiserver/plane/app/views/workspace/draft.py index 971605d299d..265ef111ce2 100644 --- a/apiserver/plane/app/views/workspace/draft.py +++ b/apiserver/plane/app/views/workspace/draft.py @@ -71,7 +71,7 @@ def get_queryset(self): ArrayAgg( "labels__id", distinct=True, - filter=( + filter=Q( ~Q(labels__id__isnull=True) & (Q(draft_label_issue__deleted_at__isnull=True)) ), @@ -82,9 +82,9 @@ def get_queryset(self): ArrayAgg( "assignees__id", distinct=True, - filter=~Q(assignees__id__isnull=True) + filter=Q(~Q(assignees__id__isnull=True) & Q(assignees__member_project__is_active=True) - & Q(draft_issue_assignee__deleted_at__isnull=True), + & Q(draft_issue_assignee__deleted_at__isnull=True)), ), Value([], output_field=ArrayField(UUIDField())), ), @@ -92,11 +92,11 @@ def get_queryset(self): ArrayAgg( "draft_issue_module__module_id", distinct=True, - filter=~Q(draft_issue_module__module_id__isnull=True) + filter=Q(~Q(draft_issue_module__module_id__isnull=True) & Q( draft_issue_module__module__archived_at__isnull=True ) - & Q(draft_issue_module__deleted_at__isnull=True), + & Q(draft_issue_module__deleted_at__isnull=True)), ), Value([], output_field=ArrayField(UUIDField())), ), diff --git a/apiserver/plane/db/migrations/0082_alter_issue_managers_alter_cycleissue_issue_and_more.py b/apiserver/plane/db/migrations/0082_alter_issue_managers_alter_cycleissue_issue_and_more.py index e26ed9052f4..9d0279eb45c 100644 --- a/apiserver/plane/db/migrations/0082_alter_issue_managers_alter_cycleissue_issue_and_more.py +++ b/apiserver/plane/db/migrations/0082_alter_issue_managers_alter_cycleissue_issue_and_more.py @@ -1,4 +1,4 @@ -# Generated by Django 4.2.15 on 2024-10-21 13:59 +# Generated by Django 4.2.15 on 2024-10-22 08:00 from django.db import migrations, models import django.db.models.deletion diff --git a/apiserver/plane/space/views/issue.py b/apiserver/plane/space/views/issue.py index d8ad55ce22a..606664b01e1 100644 --- a/apiserver/plane/space/views/issue.py +++ b/apiserver/plane/space/views/issue.py @@ -717,7 +717,7 @@ def get(self, request, anchor, issue_id): ArrayAgg( "labels__id", distinct=True, - filter=( + filter=Q( ~Q(labels__id__isnull=True) & Q(label_issue__deleted_at__isnull=True), ), @@ -728,9 +728,9 @@ def get(self, request, anchor, issue_id): ArrayAgg( "assignees__id", distinct=True, - filter=~Q(assignees__id__isnull=True) + filter=Q(~Q(assignees__id__isnull=True) & Q(assignees__member_project__is_active=True) - & Q(issue_assignee__deleted_at__isnull=True), + & Q(issue_assignee__deleted_at__isnull=True)), ), Value([], output_field=ArrayField(UUIDField())), ),