Skip to content

Commit 03ba0ab

Browse files
committed
feat: remove persons with cronjob when retention period has exceeded
PT-1932. The `delete_retention_period_exceeding_contact_info` cronjob has deleted contact info from PalvelutarjotinEvent when the retention period (48h) has exceeded, but the persons have been deleted manually from the enrollee personal data admin view. Since it's been a manual task, it has always needed some one to take care of it. There is no reason why that job could not be done automatically with a cronjob. The `delete_retention_period_exceeding_contact_info` cronjob is now extended with that feature, but there are also new flags that can be used to run only 1 of the tasks (with the management command that the cronjob executes) and tehre is also a flag to make a dry drun, that does not acutally delete anything, but just reports how many instances it would delete if it would be ran.
1 parent b4bfe92 commit 03ba0ab

2 files changed

Lines changed: 593 additions & 253 deletions

File tree

Lines changed: 131 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,144 @@
11
from django.core.management.base import BaseCommand
22

33
from occurrences.models import PalvelutarjotinEvent
4+
from organisations.models import EnrolleePersonalData
45

56

67
class Command(BaseCommand):
7-
help = "Delete retention period exceeding contact info from PalveluTarjotinEvents"
8+
help = (
9+
"Delete retention period exceeding contact info from PalveluTarjotinEvents "
10+
"and EnrolleePersonalData."
11+
)
12+
13+
def add_arguments(self, parser):
14+
"""
15+
Adds arguments to the command to allow selective execution of deletion methods.
16+
"""
17+
parser.add_argument(
18+
"--delete-event-contact-info",
19+
action="store_true",
20+
default=False,
21+
help="Only delete contact info from PalveluTarjotinEvents. "
22+
"(NOTE: This can be stacked with other flags)",
23+
)
24+
parser.add_argument(
25+
"--delete-enrollee-personal-data",
26+
action="store_true",
27+
default=False,
28+
help="Only delete personal data from EnrolleePersonalData. "
29+
"(NOTE: This can be stacked with other flags)",
30+
)
31+
parser.add_argument(
32+
"--dry-run",
33+
action="store_true",
34+
default=False,
35+
help="Perform a dry run without actually deleting any data. "
36+
"Shows what would be deleted.",
37+
)
838

939
def handle(self, *args, **kwargs):
40+
"""
41+
Handles the execution of the command based on the provided arguments.
42+
If no flags are provided, both deletion methods are run.
43+
If at least one flag is provided, only the methods corresponding to the
44+
set flags will be executed.
45+
The --dry-run flag prevents actual deletions.
46+
"""
47+
delete_event_contact_info = kwargs["delete_event_contact_info"]
48+
delete_enrollee_personal_data = kwargs["delete_enrollee_personal_data"]
49+
dry_run = kwargs["dry_run"]
50+
51+
if dry_run:
52+
self.stdout.write(self.style.WARNING("--- DRY RUN MODE ---"))
53+
self.stdout.write(self.style.WARNING("No data will be deleted."))
54+
55+
# Determine which methods to run
56+
if delete_event_contact_info or delete_enrollee_personal_data:
57+
self.stdout.write(
58+
self.style.NOTICE("Running selected deletion methods based on flags.")
59+
)
60+
if delete_event_contact_info:
61+
self.__delete_p_event_contact_info(dry_run=dry_run)
62+
if delete_enrollee_personal_data:
63+
self.__delete_enrollee_personal_data(dry_run=dry_run)
64+
else:
65+
# No flags provided, run both (default behavior)
66+
self.stdout.write(
67+
self.style.NOTICE(
68+
"Running: Both deletion methods "
69+
"(default behavior as no flags were provided)."
70+
)
71+
)
72+
self.__delete_p_event_contact_info(dry_run=dry_run)
73+
self.__delete_enrollee_personal_data(dry_run=dry_run)
74+
75+
def __delete_p_event_contact_info(self, dry_run=False):
76+
"""
77+
Deletes contact information from PalvelutarjotinEvent objects
78+
that have exceeded their retention period.
79+
If dry_run is True, it only reports what would be deleted.
80+
"""
1081
self.stdout.write(
11-
"Deleting contact info from PalveluTarjotinEvents that are exceeding "
82+
"Checking contact info from PalveluTarjotinEvents that are exceeding "
1283
"the retention period..."
1384
)
1485

15-
events = PalvelutarjotinEvent.objects.contact_info_retention_period_exceeded()
16-
num_of_deleted_contact_info = events.delete_contact_info()
86+
try:
87+
events = (
88+
PalvelutarjotinEvent.objects.contact_info_retention_period_exceeded()
89+
)
90+
count_to_delete = events.count()
1791

18-
msg = (
19-
"No events are exceeding the retention period."
20-
if num_of_deleted_contact_info == 0
21-
else f"Deleted contact info from {num_of_deleted_contact_info} event(s)."
22-
)
23-
self.stdout.write(self.style.SUCCESS(msg))
92+
if dry_run:
93+
msg_prefix = "Would delete"
94+
deleted_contact_info_count = 0 # No actual deletion in dry run
95+
else:
96+
msg_prefix = "Deleted"
97+
deleted_contact_info_count = events.delete_contact_info()
98+
99+
if count_to_delete == 0:
100+
msg = "No events are exceeding the retention period."
101+
else:
102+
if dry_run:
103+
msg = f"{msg_prefix} contact info from {count_to_delete} event(s)."
104+
else:
105+
msg = f"{msg_prefix} contact info from {deleted_contact_info_count} event(s)." # noqa: E501
106+
107+
self.stdout.write(self.style.SUCCESS(msg))
108+
except Exception as e:
109+
self.stdout.write(
110+
self.style.ERROR(f"Error checking/deleting event contact info: {e}")
111+
)
112+
113+
def __delete_enrollee_personal_data(self, dry_run=False):
114+
"""
115+
Deletes EnrolleePersonalData objects (persons) that have exceeded
116+
their retention period.
117+
If dry_run is True, it only reports what would be deleted.
118+
"""
119+
self.stdout.write("Checking persons that are exceeding the retention period...")
120+
121+
try:
122+
persons = EnrolleePersonalData.objects.retention_period_exceeded()
123+
count_to_delete = persons.count()
124+
125+
if dry_run:
126+
msg_prefix = "Would delete"
127+
deleted_personal_data_count = 0 # No actual deletion in dry run
128+
else:
129+
msg_prefix = "Deleted"
130+
deleted_personal_data_count, _ = persons.delete()
131+
132+
if count_to_delete == 0:
133+
msg = "No personal data are exceeding the retention period."
134+
else:
135+
if dry_run:
136+
msg = f"{msg_prefix} {count_to_delete} person(s)."
137+
else:
138+
msg = f"{msg_prefix} {deleted_personal_data_count} person(s)."
139+
140+
self.stdout.write(self.style.SUCCESS(msg))
141+
except Exception as e:
142+
self.stdout.write(
143+
self.style.ERROR(f"Error checking/deleting enrollee personal data: {e}")
144+
)

0 commit comments

Comments
 (0)