chore: soft deletion of cycle and module (#5884)

* chore: soft deletion of cycle and module

* chore: cycle module soft delete

* chore: added the deletion task

* chore: updated the env example

* chore: cycle issue unique constraints

* chore: udpated the Q operator
This commit is contained in:
Bavisetti Narayan 2024-10-22 14:21:26 +05:30 committed by GitHub
parent 00eff43f4d
commit 7bf4620bc1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
31 changed files with 317 additions and 141 deletions

View file

@ -57,5 +57,6 @@ ADMIN_BASE_URL=
SPACE_BASE_URL=
APP_BASE_URL=
# Hard delete files after days
HARD_DELETE_AFTER_DAYS=60
HARD_DELETE_AFTER_DAYS=60

View file

@ -212,7 +212,7 @@ class IssueSerializer(BaseSerializer):
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 @@ class IssueSerializer(BaseSerializer):
)
if labels is not None:
IssueLabel.objects.filter(issue=instance).delete(soft=False)
IssueLabel.objects.filter(issue=instance).delete()
IssueLabel.objects.bulk_create(
[
IssueLabel(

View file

@ -404,7 +404,7 @@ class CycleAPIEndpoint(BaseAPIView):
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",

View file

@ -227,7 +227,10 @@ class InboxIssueAPIEndpoint(BaseAPIView):
ArrayAgg(
"labels__id",
distinct=True,
filter=~Q(labels__id__isnull=True),
filter=Q(
~Q(labels__id__isnull=True)
& Q(label_issue__deleted_at__isnull=True),
),
),
Value([], output_field=ArrayField(UUIDField())),
),
@ -235,7 +238,11 @@ class InboxIssueAPIEndpoint(BaseAPIView):
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)
),
),
Value([], output_field=ArrayField(UUIDField())),
),

View file

@ -205,7 +205,7 @@ class IssueAPIEndpoint(BaseAPIView):
.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,

View file

@ -169,9 +169,7 @@ class DraftIssueCreateSerializer(BaseSerializer):
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 @@ class DraftIssueCreateSerializer(BaseSerializer):
)
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(
@ -208,7 +204,7 @@ class DraftIssueCreateSerializer(BaseSerializer):
if cycle_id != "not_provided":
DraftIssueCycle.objects.filter(draft_issue=instance).delete()
if cycle_id is not None:
if cycle_id:
DraftIssueCycle.objects.create(
cycle_id=cycle_id,
draft_issue=instance,

View file

@ -201,7 +201,7 @@ class IssueCreateSerializer(BaseSerializer):
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 @@ class IssueCreateSerializer(BaseSerializer):
)
if labels is not None:
IssueLabel.objects.filter(issue=instance).delete(soft=False)
IssueLabel.objects.filter(issue=instance).delete()
IssueLabel.objects.bulk_create(
[
IssueLabel(

View file

@ -110,7 +110,10 @@ class AnalyticsEndpoint(BaseAPIView):
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")

View file

@ -144,6 +144,11 @@ class CycleViewSet(BaseViewSet):
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 @@ class CycleViewSet(BaseViewSet):
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(

View file

@ -105,7 +105,7 @@ class CycleIssueViewSet(BaseViewSet):
.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,

View file

@ -218,9 +218,9 @@ def dashboard_assigned_issues(self, request, slug):
ArrayAgg(
"labels__id",
distinct=True,
filter=(
filter=Q(
~Q(labels__id__isnull=True)
& Q(labels__deleted_at__isnull=True)
& Q(label_issue__deleted_at__isnull=True),
),
),
Value([], output_field=ArrayField(UUIDField())),
@ -229,8 +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),
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())),
),
@ -238,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__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())),
),
@ -387,9 +392,9 @@ def dashboard_created_issues(self, request, slug):
ArrayAgg(
"labels__id",
distinct=True,
filter=(
filter=Q(
~Q(labels__id__isnull=True)
& Q(labels__deleted_at__isnull=True)
& Q(label_issue__deleted_at__isnull=True),
),
),
Value([], output_field=ArrayField(UUIDField())),
@ -398,8 +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),
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())),
),
@ -407,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__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())),
),

View file

@ -115,7 +115,7 @@ class InboxIssueViewSet(BaseViewSet):
.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,
@ -149,9 +149,9 @@ class InboxIssueViewSet(BaseViewSet):
ArrayAgg(
"labels__id",
distinct=True,
filter=(
filter=Q(
~Q(labels__id__isnull=True)
& Q(labels__deleted_at__isnull=True)
& Q(label_issue__deleted_at__isnull=True),
),
),
Value([], output_field=ArrayField(UUIDField())),
@ -160,8 +160,11 @@ class InboxIssueViewSet(BaseViewSet):
ArrayAgg(
"assignees__id",
distinct=True,
filter=~Q(assignees__id__isnull=True)
& Q(assignees__member_project__is_active=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())),
),
@ -169,9 +172,11 @@ class InboxIssueViewSet(BaseViewSet):
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__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())),
),
@ -198,8 +203,8 @@ class InboxIssueViewSet(BaseViewSet):
ArrayAgg(
"issue__labels__id",
distinct=True,
filter=~Q(issue__labels__id__isnull=True)
& Q(issue__labels__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())),
)
@ -311,9 +316,11 @@ class InboxIssueViewSet(BaseViewSet):
ArrayAgg(
"issue__labels__id",
distinct=True,
filter=(
filter=Q(
~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())),
@ -323,7 +330,9 @@ class InboxIssueViewSet(BaseViewSet):
"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())),
),
@ -376,7 +385,8 @@ class InboxIssueViewSet(BaseViewSet):
ArrayAgg(
"labels__id",
distinct=True,
filter=~Q(labels__id__isnull=True),
filter=Q(~Q(labels__id__isnull=True)
& Q(label_issue__deleted_at__isnull=True)),
),
Value([], output_field=ArrayField(UUIDField())),
),
@ -384,7 +394,8 @@ class InboxIssueViewSet(BaseViewSet):
ArrayAgg(
"assignees__id",
distinct=True,
filter=~Q(assignees__id__isnull=True),
filter=Q(~Q(assignees__id__isnull=True)
& Q(issue_assignee__deleted_at__isnull=True)),
),
Value([], output_field=ArrayField(UUIDField())),
),
@ -507,7 +518,10 @@ class InboxIssueViewSet(BaseViewSet):
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())),
),
@ -515,7 +529,8 @@ class InboxIssueViewSet(BaseViewSet):
ArrayAgg(
"issue__assignees__id",
distinct=True,
filter=~Q(issue__assignees__id__isnull=True),
filter=Q(~Q(issue__assignees__id__isnull=True)
& Q(issue__issue_assignee__deleted_at__isnull=True)),
),
Value([], output_field=ArrayField(UUIDField())),
),
@ -560,7 +575,8 @@ class InboxIssueViewSet(BaseViewSet):
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())),
),
@ -568,7 +584,8 @@ class InboxIssueViewSet(BaseViewSet):
ArrayAgg(
"issue__assignees__id",
distinct=True,
filter=~Q(issue__assignees__id__isnull=True),
filter=Q(~Q(issue__assignees__id__isnull=True)
& Q(issue__issue_assignee__deleted_at__isnull=True)),
),
Value([], output_field=ArrayField(UUIDField())),
),

View file

@ -67,7 +67,7 @@ class IssueArchiveViewSet(BaseViewSet):
.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,

View file

@ -88,7 +88,7 @@ class IssueListEndpoint(BaseAPIView):
.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 @@ class IssueViewSet(BaseViewSet):
.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,
@ -489,9 +489,9 @@ class IssueViewSet(BaseViewSet):
ArrayAgg(
"labels__id",
distinct=True,
filter=(
filter=Q(
~Q(labels__id__isnull=True)
& Q(labels__deleted_at__isnull=True)
& Q(label_issue__deleted_at__isnull=True),
),
),
Value([], output_field=ArrayField(UUIDField())),
@ -500,8 +500,11 @@ class IssueViewSet(BaseViewSet):
ArrayAgg(
"assignees__id",
distinct=True,
filter=~Q(assignees__id__isnull=True)
& Q(assignees__member_project__is_active=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())),
),
@ -509,9 +512,11 @@ class IssueViewSet(BaseViewSet):
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__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())),
),
@ -590,9 +595,9 @@ class IssueViewSet(BaseViewSet):
ArrayAgg(
"labels__id",
distinct=True,
filter=(
filter=Q(
~Q(labels__id__isnull=True)
& Q(labels__deleted_at__isnull=True)
& Q(label_issue__deleted_at__isnull=True),
),
),
Value([], output_field=ArrayField(UUIDField())),
@ -601,8 +606,11 @@ class IssueViewSet(BaseViewSet):
ArrayAgg(
"assignees__id",
distinct=True,
filter=~Q(assignees__id__isnull=True)
& Q(assignees__member_project__is_active=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())),
),
@ -610,9 +618,11 @@ class IssueViewSet(BaseViewSet):
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__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())),
),
@ -778,7 +788,7 @@ class IssuePaginatedViewSet(BaseViewSet):
.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,
@ -890,9 +900,9 @@ class IssuePaginatedViewSet(BaseViewSet):
ArrayAgg(
"labels__id",
distinct=True,
filter=(
filter=Q(
~Q(labels__id__isnull=True)
& Q(labels__deleted_at__isnull=True)
& Q(label_issue__deleted_at__isnull=True),
),
),
Value([], output_field=ArrayField(UUIDField())),
@ -901,8 +911,11 @@ class IssuePaginatedViewSet(BaseViewSet):
ArrayAgg(
"assignees__id",
distinct=True,
filter=~Q(assignees__id__isnull=True)
& Q(assignees__member_project__is_active=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())),
),
@ -910,9 +923,11 @@ class IssuePaginatedViewSet(BaseViewSet):
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__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())),
),

View file

@ -96,7 +96,7 @@ class IssueRelationViewSet(BaseViewSet):
.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,
@ -130,9 +130,9 @@ class IssueRelationViewSet(BaseViewSet):
ArrayAgg(
"labels__id",
distinct=True,
filter=(
filter=Q(
~Q(labels__id__isnull=True)
& Q(labels__deleted_at__isnull=True)
& (Q(label_issue__deleted_at__isnull=True))
),
),
Value([], output_field=ArrayField(UUIDField())),
@ -141,8 +141,9 @@ class IssueRelationViewSet(BaseViewSet):
ArrayAgg(
"assignees__id",
distinct=True,
filter=~Q(assignees__id__isnull=True)
& Q(assignees__member_project__is_active=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())),
),
@ -289,7 +290,7 @@ class IssueRelationViewSet(BaseViewSet):
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),

View file

@ -53,7 +53,7 @@ class SubIssuesEndpoint(BaseAPIView):
.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,
@ -87,9 +87,9 @@ class SubIssuesEndpoint(BaseAPIView):
ArrayAgg(
"labels__id",
distinct=True,
filter=(
filter=Q(
~Q(labels__id__isnull=True)
& Q(labels__deleted_at__isnull=True)
& Q(label_issue__deleted_at__isnull=True),
),
),
Value([], output_field=ArrayField(UUIDField())),
@ -98,8 +98,11 @@ class SubIssuesEndpoint(BaseAPIView):
ArrayAgg(
"assignees__id",
distinct=True,
filter=~Q(assignees__id__isnull=True)
& Q(assignees__member_project__is_active=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())),
),
@ -107,9 +110,11 @@ class SubIssuesEndpoint(BaseAPIView):
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__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())),
),

View file

@ -70,7 +70,7 @@ class ModuleIssueViewSet(BaseViewSet):
.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,

View file

@ -210,7 +210,7 @@ class WorkspaceViewIssuesViewSet(BaseViewSet):
.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,
@ -244,9 +244,9 @@ class WorkspaceViewIssuesViewSet(BaseViewSet):
ArrayAgg(
"labels__id",
distinct=True,
filter=(
filter=Q(
~Q(labels__id__isnull=True)
& Q(labels__deleted_at__isnull=True)
& Q(label_issue__deleted_at__isnull=True),
),
),
Value([], output_field=ArrayField(UUIDField())),
@ -255,8 +255,11 @@ class WorkspaceViewIssuesViewSet(BaseViewSet):
ArrayAgg(
"assignees__id",
distinct=True,
filter=~Q(assignees__id__isnull=True)
& Q(assignees__member_project__is_active=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())),
),
@ -264,9 +267,11 @@ class WorkspaceViewIssuesViewSet(BaseViewSet):
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__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())),
),
@ -288,7 +293,7 @@ class WorkspaceViewIssuesViewSet(BaseViewSet):
.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 +557,9 @@ class IssueViewViewSet(BaseViewSet):
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,

View file

@ -60,7 +60,7 @@ class WorkspaceDraftIssueViewSet(BaseViewSet):
.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,
@ -71,9 +71,9 @@ class WorkspaceDraftIssueViewSet(BaseViewSet):
ArrayAgg(
"labels__id",
distinct=True,
filter=(
filter=Q(
~Q(labels__id__isnull=True)
& Q(labels__deleted_at__isnull=True)
& (Q(draft_label_issue__deleted_at__isnull=True))
),
),
Value([], output_field=ArrayField(UUIDField())),
@ -82,8 +82,9 @@ class WorkspaceDraftIssueViewSet(BaseViewSet):
ArrayAgg(
"assignees__id",
distinct=True,
filter=~Q(assignees__id__isnull=True)
& Q(assignees__member_project__is_active=True),
filter=Q(~Q(assignees__id__isnull=True)
& Q(assignees__member_project__is_active=True)
& Q(draft_issue_assignee__deleted_at__isnull=True)),
),
Value([], output_field=ArrayField(UUIDField())),
),
@ -91,13 +92,11 @@ class WorkspaceDraftIssueViewSet(BaseViewSet):
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__module__deleted_at__isnull=True
),
& Q(draft_issue_module__deleted_at__isnull=True)),
),
Value([], output_field=ArrayField(UUIDField())),
),

View file

@ -123,7 +123,7 @@ class WorkspaceUserProfileIssuesEndpoint(BaseAPIView):
.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,

View file

@ -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")

View file

@ -32,14 +32,14 @@ app.conf.beat_schedule = {
"task": "plane.bgtasks.email_notification_task.stack_email_notification",
"schedule": crontab(minute="*/5"),
},
"check-every-day-to-delete-api-logs": {
"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),
},
"check-every-day-to-delete-api-logs": {
"task": "plane.bgtasks.api_logs_task.delete_api_logs",
"schedule": crontab(hour=0, minute=0),
},
"run-every-6-hours-for-instance-trace": {
"task": "plane.license.bgtasks.tracer.instance_traces",
"schedule": crontab(hour="*/6"),

View file

@ -0,0 +1,63 @@
# Generated by Django 4.2.15 on 2024-10-22 08:00
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")},
),
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",
),
),
]

View file

@ -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,14 @@ 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"

View file

@ -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,14 @@ 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"

View file

@ -91,6 +91,7 @@ class IssueManager(SoftDeletionManager):
| 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)

View file

@ -421,7 +421,7 @@ class IssueCreateSerializer(BaseSerializer):
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 @@ class IssueCreateSerializer(BaseSerializer):
)
if labels is not None:
IssueLabel.objects.filter(issue=instance).delete(soft=False)
IssueLabel.objects.filter(issue=instance).delete()
IssueLabel.objects.bulk_create(
[
IssueLabel(

View file

@ -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),

View file

@ -109,7 +109,7 @@ class ProjectIssuesPublicEndpoint(BaseAPIView):
.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 @@ class IssueRetrievePublicEndpoint(BaseAPIView):
.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,
@ -717,9 +717,9 @@ class IssueRetrievePublicEndpoint(BaseAPIView):
ArrayAgg(
"labels__id",
distinct=True,
filter=(
filter=Q(
~Q(labels__id__isnull=True)
& Q(labels__deleted_at__isnull=True)
& Q(label_issue__deleted_at__isnull=True),
),
),
Value([], output_field=ArrayField(UUIDField())),
@ -728,8 +728,9 @@ class IssueRetrievePublicEndpoint(BaseAPIView):
ArrayAgg(
"assignees__id",
distinct=True,
filter=~Q(assignees__id__isnull=True)
& Q(assignees__member_project__is_active=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())),
),
@ -739,7 +740,7 @@ class IssueRetrievePublicEndpoint(BaseAPIView):
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())),
),

View file

@ -25,17 +25,22 @@ 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",
(
~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)
),
),
}

View file

@ -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