Skip to content

Commit 8619096

Browse files
committed
feat: event with ongoing occurrences can have space for enrolment
An event with ongoing occurrences can have space for enrolment if the enrolement hasn't been set to end before an occurence starts. Refs: PT-1952
1 parent 7854c2f commit 8619096

3 files changed

Lines changed: 95 additions & 10 deletions

File tree

occurrences/models.py

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -291,35 +291,48 @@ def has_enrolments_system(self) -> bool:
291291

292292
def has_space_for_enrolments(self) -> Optional[bool]:
293293
"""
294-
Determines whether any (upcoming) occurrence has any space left
294+
Determines whether any upcoming or ongoing occurrence has any space left
295295
for enrolments.
296296
297297
Returns:
298-
- True: If at least one upcoming occurrence has space for enrolments.
298+
- True: If at least one upcoming or ongoingoccurrence has space for
299+
enrolments.
299300
- False: If no upcoming occurrences have space for enrolments.
300301
- None: If the event doesn't utilize the enrolments system or
301302
relies on an external enrolments system.
302303
"""
303304
if not self.has_enrolments_system() or self.has_external_enrolments_system():
304305
return None
305306

306-
return any(
307+
has_upcoming_space = any(
307308
occurrence.has_space_left()
308309
for occurrence in self.occurrences.filter_upcoming()
309310
)
310311

312+
if self.enrolment_end_days is None:
313+
# No limit to when enrolments can be made before the occurrence start.
314+
return has_upcoming_space or any(
315+
occurrence.has_space_left()
316+
for occurrence in self.occurrences.filter_ongoing()
317+
)
318+
319+
return has_upcoming_space
320+
311321

312322
class OccurrenceQueryset(models.QuerySet):
313323
def delete(self, *args, **kwargs):
314324
for obj in self:
315325
obj.delete()
316326

317327
def filter_upcoming(self, *args, **kwargs):
318-
"""Filter occurrences that are not not cancelled and
319-
are held in the future.
320-
"""
328+
"""Filter occurrences that are not cancelled and are held in the future."""
321329
return self.filter(cancelled=False, start_time__gte=timezone.now())
322330

331+
def filter_ongoing(self, *args, **kwargs):
332+
"""Filter occurrences that are not cancelled and are ongoing at the moment."""
333+
now = timezone.now()
334+
return self.filter(cancelled=False, start_time__lte=now, end_time__gte=now)
335+
323336

324337
class Occurrence(GDPRModel, SerializableMixin, TimestampedModel):
325338
OCCURRENCE_SEAT_TYPE_CHILDREN_COUNT = "children_count"

occurrences/schema.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,8 @@ def resolve_last_occurrence_datetime(self, info, **kwargs):
219219

220220
def resolve_has_space_for_enrolments(self, info, **kwargs):
221221
"""
222-
Determines whether any upcoming occurrence has any space left for enrolments.
222+
Determines whether any upcoming or ongoing occurrence has any space left for
223+
enrolments.
223224
224225
This method leverages the internal `has_space_for_enrolments` logic to ascertain
225226
if there are any future event occurrences with available spaces for enrollment.
@@ -231,7 +232,8 @@ def resolve_has_space_for_enrolments(self, info, **kwargs):
231232
(may not be used in this specific implementation).
232233
233234
Returns:
234-
- True: If at least one upcoming occurrence has space for enrolments.
235+
- True: If at least one upcoming or ongoing occurrence has space for
236+
enrolments.
235237
- False: If no upcoming occurrences have space for enrolments.
236238
- None: If the event doesn't utilize the enrolments system or
237239
relies on an external enrolments system.

occurrences/tests/test_models.py

Lines changed: 72 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -980,20 +980,90 @@ def test_palvelutarjotin_event_has_space_for_enrolments_returning_boolean(
980980
mock_get_event_data,
981981
):
982982
p_event = PalvelutarjotinEventFactory()
983+
# Past occurrences
984+
OccurrenceFactory.create_batch(
985+
4,
986+
p_event=p_event,
987+
cancelled=False,
988+
start_time=timezone.now() - timedelta(days=2),
989+
end_time=timezone.now() - timedelta(days=1),
990+
)
991+
# Ongoing occurrences
992+
OccurrenceFactory.create_batch(
993+
2,
994+
p_event=p_event,
995+
cancelled=False,
996+
start_time=timezone.now() - timedelta(days=1),
997+
end_time=timezone.now() + timedelta(days=1),
998+
)
999+
# Future occurrences
9831000
OccurrenceFactory.create_batch(
9841001
3,
9851002
p_event=p_event,
9861003
cancelled=False,
9871004
start_time=timezone.now() + timedelta(days=1),
1005+
end_time=timezone.now() + timedelta(days=2),
1006+
)
1007+
assert p_event.occurrences.count() == 9
1008+
assert p_event.occurrences.filter_upcoming().count() == 3
1009+
assert p_event.occurrences.filter_ongoing().count() == 2
1010+
with patch(
1011+
"occurrences.models.PalvelutarjotinEvent.has_external_enrolments_system",
1012+
return_value=False,
1013+
):
1014+
with patch(
1015+
"occurrences.models.PalvelutarjotinEvent.has_internal_enrolments_system",
1016+
return_value=True,
1017+
):
1018+
with patch(
1019+
"occurrences.models.Occurrence.has_space_left"
1020+
) as mock_has_space_left:
1021+
mock_has_space_left.return_value = False
1022+
assert p_event.has_space_for_enrolments() is False
1023+
assert mock_has_space_left.call_count == 3
1024+
with patch(
1025+
"occurrences.models.PalvelutarjotinEvent.has_external_enrolments_system",
1026+
return_value=False,
1027+
):
1028+
with patch(
1029+
"occurrences.models.PalvelutarjotinEvent.has_internal_enrolments_system",
1030+
return_value=True,
1031+
):
1032+
with patch(
1033+
"occurrences.models.Occurrence.has_space_left"
1034+
) as mock_has_space_left:
1035+
# 2nd occurrence returns True, so result is True
1036+
# and any-call returns after 2nd round.
1037+
mock_has_space_left.side_effect = [False, True, False]
1038+
assert p_event.has_space_for_enrolments() is True
1039+
assert mock_has_space_left.call_count == 2
1040+
1041+
1042+
@pytest.mark.django_db
1043+
def test_palvelutarjotin_event_has_space_for_enrolments_ongoing_events(
1044+
mock_get_event_data,
1045+
):
1046+
"""Ongoing events are not considered"""
1047+
p_event = PalvelutarjotinEventFactory(enrolment_end_days=None)
1048+
# Past occurrences
1049+
OccurrenceFactory.create_batch(
1050+
2,
1051+
p_event=p_event,
1052+
cancelled=False,
1053+
start_time=timezone.now() - timedelta(days=2),
1054+
end_time=timezone.now() - timedelta(days=1),
9881055
)
1056+
# Ongoing occurrences
9891057
OccurrenceFactory.create_batch(
9901058
3,
9911059
p_event=p_event,
9921060
cancelled=False,
9931061
start_time=timezone.now() - timedelta(days=1),
1062+
end_time=timezone.now() + timedelta(days=1),
9941063
)
995-
assert p_event.occurrences.count() == 6
996-
assert p_event.occurrences.filter_upcoming().count() == 3
1064+
assert p_event.occurrences.count() == 5
1065+
assert p_event.occurrences.filter_upcoming().count() == 0
1066+
assert p_event.occurrences.filter_ongoing().count() == 3
9971067
with patch(
9981068
"occurrences.models.PalvelutarjotinEvent.has_external_enrolments_system",
9991069
return_value=False,

0 commit comments

Comments
 (0)