@@ -44,12 +44,6 @@ def published(self):
4444 def upcoming (self ):
4545 return self .filter (events__occurrences__time__gte = timezone .now ()).distinct ()
4646
47- def upcoming_with_leeway (self ):
48- return self .filter (
49- events__occurrences__time__gte = timezone .now ()
50- - timedelta (minutes = settings .KUKKUU_ENROLLED_OCCURRENCE_IN_PAST_LEEWAY )
51- ).distinct ()
52-
5347
5448class EventGroup (TimestampedModel , TranslatableModel ):
5549 translations = TranslatedFields (
@@ -152,12 +146,6 @@ def unpublished(self):
152146 def upcoming (self ):
153147 return self .filter (occurrences__time__gte = timezone .now ()).distinct ()
154148
155- def upcoming_with_leeway (self ):
156- return self .filter (
157- occurrences__time__gte = timezone .now ()
158- - timedelta (minutes = settings .KUKKUU_ENROLLED_OCCURRENCE_IN_PAST_LEEWAY )
159- ).distinct ()
160-
161149 def available (self , child ):
162150 """
163151 A child's available events must match all of the following rules:
@@ -369,11 +357,38 @@ def send_free_spot_notifications_if_needed(self):
369357 obj .send_free_spot_notifications_if_needed ()
370358
371359 def upcoming (self ):
372- return self .filter (time__gt = timezone .now ())
360+ return self .filter (time__gte = timezone .now ())
361+
362+ def upcoming_with_leeway (self ):
363+ return self .filter (
364+ time__gte = timezone .now ()
365+ - timedelta (minutes = settings .KUKKUU_ENROLLED_OCCURRENCE_IN_PAST_LEEWAY )
366+ )
367+
368+ def upcoming_with_ongoing (self ):
369+ """Return occurrences that are upcoming or still ongoing (with added leeway)."""
370+ qs = self .with_end_time ()
371+ return qs .filter (
372+ end_time__gte = timezone .now ()
373+ - timedelta (minutes = settings .KUKKUU_ENROLLED_OCCURRENCE_IN_PAST_LEEWAY )
374+ )
373375
374376 def in_past (self ):
375377 return self .exclude (time__gt = timezone .now ())
376378
379+ def with_end_time (self ):
380+ return self .annotate (
381+ end_time = ExpressionWrapper (
382+ F ("time" )
383+ + Coalesce (
384+ F ("event__duration" ),
385+ settings .KUKKUU_DEFAULT_EVENT_DURATION ,
386+ )
387+ * timedelta (minutes = 1 ),
388+ output_field = models .DateTimeField (),
389+ ),
390+ )
391+
377392
378393class Occurrence (TimestampedModel ):
379394 time = models .DateTimeField (verbose_name = _ ("time" ))
@@ -506,7 +521,20 @@ def delete(self):
506521 enrolment .delete ()
507522
508523 def upcoming (self ):
509- return self .filter (occurrence__time__gt = timezone .now ())
524+ return self .filter (occurrence__time__gte = timezone .now ())
525+
526+ def with_end_time (self ):
527+ return self .annotate (
528+ end_time = ExpressionWrapper (
529+ F ("occurrence__time" )
530+ + Coalesce (
531+ F ("occurrence__event__duration" ),
532+ settings .KUKKUU_DEFAULT_EVENT_DURATION ,
533+ )
534+ * timedelta (minutes = 1 ),
535+ output_field = models .DateTimeField (),
536+ ),
537+ )
510538
511539 def send_reminder_notifications (self ):
512540 today = timezone .localtime ().date ()
@@ -531,15 +559,7 @@ def send_feedback_notifications(self):
531559 delay = timedelta (minutes = settings .KUKKUU_FEEDBACK_NOTIFICATION_DELAY )
532560
533561 enrolments = (
534- self .annotate (
535- end_time = ExpressionWrapper (
536- F ("occurrence__time" )
537- # use 120min as the default value for duration
538- + Coalesce (F ("occurrence__event__duration" ), 120 )
539- * timedelta (minutes = 1 ),
540- output_field = models .DateTimeField (),
541- ),
542- )
562+ self .with_end_time ()
543563 .filter (
544564 feedback_notification_sent_at = None ,
545565 child__guardians__isnull = False ,
0 commit comments