Skip to content

Commit

Permalink
feat: delete applications older than 10 years (#3646)
Browse files Browse the repository at this point in the history
  • Loading branch information
rikuke authored Dec 13, 2024
1 parent ad6b330 commit d6cabc4
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 26 deletions.
17 changes: 15 additions & 2 deletions backend/benefit/applications/jobs/daily/daily_application_jobs.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from django.core.management import call_command
from django_extensions.management.jobs import DailyJob

from applications.enums import ApplicationStatus

"""
Daily job to delete cancelled applications.
Expand All @@ -13,8 +15,19 @@ class Job(DailyJob):
help = "Django daily jobs are executed here."

def execute(self):
call_command("delete_applications", keep=30, status="cancelled")
call_command("delete_applications", keep=180, status="draft")
call_command(
"delete_applications", keep=30, status=[ApplicationStatus.CANCELLED]
)
call_command("delete_applications", keep=180, status=[ApplicationStatus.DRAFT])
call_command(
"delete_applications",
keep=3651,
status=[
ApplicationStatus.ARCHIVAL,
ApplicationStatus.ACCEPTED,
ApplicationStatus.REJECTED,
],
)
call_command("check_drafts_to_delete", notify=14, keep=180)
call_command("get_decision_maker")
call_command("get_signer")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from datetime import timedelta
from typing import List

from django.core.management.base import BaseCommand
from django.utils import timezone
Expand All @@ -9,9 +10,15 @@

class Command(BaseCommand):
help = "Delete applications with the given status (draft or cancelled) and older than the given number of days"
allowed_statuses = [ApplicationStatus.DRAFT, ApplicationStatus.CANCELLED]
allowed_statuses = [
ApplicationStatus.DRAFT,
ApplicationStatus.CANCELLED,
ApplicationStatus.ARCHIVAL,
ApplicationStatus.ACCEPTED,
ApplicationStatus.REJECTED,
]

def add_arguments(self, parser):
def add_arguments(self, parser) -> None:
parser.add_argument(
"--keep",
type=int,
Expand All @@ -22,28 +29,37 @@ def add_arguments(self, parser):
parser.add_argument(
"--status",
type=str,
default="cancelled",
help="The status of the applications to delete",
nargs="+", # Allow multiple statuses
help="The statuses of the applications to delete. \
pass multiple statuses separated by spaces.",
)

def handle(self, *args, **options):
if options["status"] not in self.allowed_statuses:
self.stdout.write(f"Status {options['status']} is not allowed")
return
number_of_deleted_applications = _delete_applications(
options["keep"], options["status"]
)
def handle(self, *args, **options) -> None:
keep_days = options["keep"]
statuses = options["status"]
if statuses:
invalid_statuses = [
status for status in statuses if status not in self.allowed_statuses
]
if invalid_statuses:
self.stderr.write(
f"Invalid statuses provided: {', '.join(invalid_statuses)}. \
Allowed statuses are: {', '.join(self.allowed_statuses)}."
)
return

number_of_deleted_applications = _delete_applications(keep_days, statuses)
self.stdout.write(
f"Deleted {number_of_deleted_applications} applications with status {options['status']}"
)


def _delete_applications(days_to_keep: int, status: str) -> int:
def _delete_applications(days_to_keep: int, statuses: List[str]) -> int:
"""Delete applications with the given status and older than the given number of days.
Also delete their attachment files."""

applications_to_delete = Application.objects.filter(
status=status,
status__in=statuses,
modified_at__lte=(timezone.now() - timedelta(days=days_to_keep)),
)
number_of_applications_to_delete = applications_to_delete.count()
Expand Down
15 changes: 4 additions & 11 deletions backend/benefit/applications/tests/test_application_tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ def test_delete_cancelled_applications_older_than_30_days(cancelled_to_delete):
applications = Application.objects.filter(status=status)
total_applications = applications.count()

call_command("delete_applications", status=status, stdout=out)
call_command("delete_applications", status=[status], stdout=out)

remaining_applications = Application.objects.filter(
status=status,
Expand All @@ -87,18 +87,11 @@ def test_delete_cancelled_applications_older_than_30_days(cancelled_to_delete):

# Assert that the correct number of applications were deleted
assert (
f"Deleted {total_applications - remaining_applications.count()} applications with status {status}"
f"Deleted {total_applications - remaining_applications.count()} applications with status {[status]}"
in out.getvalue()
)


@pytest.mark.parametrize("status", ["submitted", "approved", "rejected", "foo"])
def test_delete_applications_allows_only_draft_and_cancelled_statuses(status):
out = StringIO()
call_command("delete_applications", status=status, stdout=out)
assert f"Status {status} is not allowed" in out.getvalue()


def test_delete_draft_applications_older_than_180_days(
drafts_to_delete, drafts_to_keep
):
Expand All @@ -113,7 +106,7 @@ def test_delete_draft_applications_older_than_180_days(
]

total_applications = Application.objects.filter(status=status).count()
call_command("delete_applications", keep=180, status=status, stdout=out)
call_command("delete_applications", keep=180, status=[status], stdout=out)

# Query the remaining applications after the command has been executed
remaining_applications = Application.objects.filter(
Expand All @@ -139,7 +132,7 @@ def test_delete_draft_applications_older_than_180_days(

# Assert that the correct number of applications were deleted
assert (
f"Deleted {total_applications - remaining_applications.count()} applications with status {status}"
f"Deleted {total_applications - remaining_applications.count()} applications with status {[status]}"
in out.getvalue()
)

Expand Down

0 comments on commit d6cabc4

Please sign in to comment.