Skip to content

Commit 447ace6

Browse files
committed
fix: update person retention period deletion logic
Update person retention period deletion logic to return persons who: 1. Don't have a user account 2. Don't have any valid enrolments 3. Don't have any valid event queue enrolments Add tests. Refs: PT-1946
1 parent c8fffac commit 447ace6

2 files changed

Lines changed: 107 additions & 17 deletions

File tree

organisations/models.py

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from django.contrib.auth.models import UserManager
99
from django.contrib.postgres.fields import ArrayField
1010
from django.db import models, router, transaction
11-
from django.db.models import Max, Q
11+
from django.db.models import Q
1212
from django.db.models.deletion import Collector
1313
from django.utils import timezone
1414
from django.utils.translation import gettext_lazy as _
@@ -37,27 +37,34 @@ def user_can_view(self, user):
3737
return self.none()
3838

3939
def retention_period_exceeded(self):
40+
"""
41+
Return queryset of Person objects whose personal data
42+
retention period has exceeded.
43+
44+
This excludes:
45+
- Persons with a user account
46+
- Persons with any valid (recent) enrolments
47+
"""
4048
earliest_valid_timestamp = timezone.now() - relativedelta(
4149
months=settings.PERSONAL_DATA_RETENTION_PERIOD_MONTHS
4250
)
4351

44-
all_enrolments_too_old = Q(max_enrolment_end_time=None) | Q(
45-
max_enrolment_end_time__lt=earliest_valid_timestamp
46-
)
47-
all_study_groups_too_old = Q(max_studygroup_end_time=None) | Q(
48-
max_studygroup_end_time__lt=earliest_valid_timestamp
49-
)
50-
52+
# Return persons who:
53+
# 1. Don't have a user account
54+
# 2. Don't have any valid enrolments (either as person or study group contact)
55+
# 3. Don't have any valid event queue enrolments
5156
return (
52-
# At least for now returns only unauthenticated Person's
53-
self.filter(user=None)
54-
.annotate(
55-
max_enrolment_end_time=Max("enrolment__occurrence__end_time"),
56-
max_studygroup_end_time=Max(
57-
"studygroup__enrolments__occurrence__end_time"
58-
),
57+
self.exclude(user__isnull=False)
58+
.exclude(enrolment__occurrence__end_time__gt=earliest_valid_timestamp)
59+
.exclude(
60+
studygroup__enrolments__occurrence__end_time__gt=earliest_valid_timestamp
61+
)
62+
.exclude(
63+
studygroup__queued_enrolments__p_event__occurrences__end_time__gt=earliest_valid_timestamp
64+
)
65+
.exclude(
66+
eventqueueenrolment__p_event__occurrences__end_time__gt=earliest_valid_timestamp
5967
)
60-
.filter(all_enrolments_too_old & all_study_groups_too_old)
6168
)
6269

6370
@transaction.atomic

organisations/tests/test_models.py

Lines changed: 84 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,12 @@
44
from django.db import IntegrityError
55
from django.utils import timezone
66

7-
from occurrences.factories import EnrolmentFactory, PalvelutarjotinEventFactory
7+
from occurrences.factories import (
8+
EnrolmentFactory,
9+
EventQueueEnrolmentFactory,
10+
OccurrenceFactory,
11+
PalvelutarjotinEventFactory,
12+
)
813
from organisations.factories import (
914
OrganisationFactory,
1015
OrganisationProposalFactory,
@@ -210,6 +215,84 @@ def test_too_old_personal_data(mock_get_event_data):
210215
assert all(person in results for person in expected_people)
211216

212217

218+
@pytest.mark.django_db
219+
def test_old_personal_data_deletion_with_valid_enrolments(mock_get_event_data):
220+
too_old = timezone.now() - relativedelta(months=24, days=1)
221+
still_valid = timezone.now() - relativedelta(days=1)
222+
223+
(
224+
enrolment_person,
225+
study_group_person,
226+
enrolment_and_study_group_person,
227+
no_enrolment_or_study_group_person,
228+
event_queue_enrolment_person,
229+
event_queue_study_group_person,
230+
) = PersonFactory.create_batch(6, user=None)
231+
232+
# too old enrolment for the enrolment person
233+
EnrolmentFactory(person=enrolment_person, occurrence__end_time=too_old)
234+
235+
# too old enrolment for the study group person
236+
EnrolmentFactory(
237+
study_group__person=study_group_person, occurrence__end_time=too_old
238+
)
239+
240+
# too old enrolment for the enrolment and study group person
241+
EnrolmentFactory(
242+
person=enrolment_and_study_group_person,
243+
study_group__person=enrolment_and_study_group_person,
244+
occurrence__end_time=too_old,
245+
)
246+
247+
too_old_p_event = PalvelutarjotinEventFactory()
248+
OccurrenceFactory(end_time=too_old, p_event=too_old_p_event)
249+
250+
# too old event queue enrolment for the event queue enrolment person
251+
EventQueueEnrolmentFactory(
252+
person=event_queue_enrolment_person, p_event=too_old_p_event
253+
)
254+
# too old event queue enrolment for the event queue study group person
255+
EventQueueEnrolmentFactory(
256+
study_group__person=event_queue_study_group_person,
257+
p_event=too_old_p_event,
258+
)
259+
260+
# valid enrolment for the enrolment person
261+
EnrolmentFactory(person=enrolment_person, occurrence__end_time=still_valid)
262+
# valid enrolment for the study group person
263+
EnrolmentFactory(
264+
study_group__person=study_group_person, occurrence__end_time=still_valid
265+
)
266+
267+
valid_p_event = PalvelutarjotinEventFactory()
268+
OccurrenceFactory(end_time=still_valid, p_event=valid_p_event)
269+
270+
# valid event queue enrolment for the event queue enrolment person
271+
EventQueueEnrolmentFactory(
272+
person=event_queue_enrolment_person, p_event=valid_p_event
273+
)
274+
# valid enrolment for the event queue enrolment person
275+
EventQueueEnrolmentFactory(
276+
person=event_queue_enrolment_person, p_event=valid_p_event
277+
)
278+
# valid enrolment for the event queue study group person
279+
EventQueueEnrolmentFactory(
280+
study_group__person=event_queue_study_group_person, p_event=valid_p_event
281+
)
282+
# person with a user
283+
PersonFactory(user=UserFactory())
284+
285+
expected_people = [
286+
enrolment_and_study_group_person,
287+
no_enrolment_or_study_group_person,
288+
]
289+
290+
# only persons without any valid enrolments should be returned
291+
results = Person.objects.retention_period_exceeded()
292+
assert len(results) == len(expected_people)
293+
assert all(person in results for person in expected_people)
294+
295+
213296
@pytest.mark.django_db
214297
@pytest.mark.parametrize("delete_via_queryset", (False, True))
215298
def test_user_deletion_deletes_palvelutarjotin_event_contact_info(delete_via_queryset):

0 commit comments

Comments
 (0)