Repository: carpentries/amy
Issue: Current events should be built upon published events

Maneesha's dashboard displays 2 events that are in both columns: current (upcoming and ongoing), and in unpublished.

This is because current events are such that:
- have start date bigger than current date
- have URL

This is of course just part of the conditions for published event.


Changed files:
workshops/models.py, workshops/test/test_event.py, workshops/test/base.py

diff --git a/workshops/models.py b/workshops/models.py
index bcb18f24..45ded1fa 100644
--- a/workshops/models.py
+++ b/workshops/models.py
@@ -498,29 +498,29 @@ class EventQuerySet(models.query.QuerySet):
         return queryset
 
     def upcoming_events(self):
-        '''Return published upcoming events.
+        """Return published upcoming events.
 
-        Upcoming events are those which start after today.  Published
-        events are those which have a URL. Events are ordered by date,
-        soonest first.
-        '''
+        Upcoming events are published events (see `published_events` below)
+        that start after today."""
 
-        queryset = self.filter(start__gt=datetime.date.today())\\
-                       .filter(url__isnull=False)\\
+        queryset = self.published_events() \\
+                       .filter(start__gt=datetime.date.today()) \\
                        .order_by('start')
         return queryset
 
     def ongoing_events(self):
-        '''Return ongoing events.
-
-        Ongoing events are those which start after today.
-        '''
+        """Return ongoing events.
 
-        # All events that start before or on today
-        queryset = self.filter(start__lte=datetime.date.today())
+        Ongoing events are published events (see `published_events` below)
+        that are currently taking place (ie. start today or before and end
+        today or later)."""
 
-        # Of those, only the ones that finish after or on today
-        queryset = queryset.filter(end__gte=datetime.date.today())
+        # All events that start before or on today, and finish after or on
+        # today.
+        queryset = self.published_events() \\
+                       .filter(start__lte=datetime.date.today()) \\
+                       .filter(end__gte=datetime.date.today()) \\
+                       .order_by('start')
 
         return queryset
 
diff --git a/workshops/test/base.py b/workshops/test/base.py
index f34f09bf..7daf6a42 100644
--- a/workshops/test/base.py
+++ b/workshops/test/base.py
@@ -210,24 +210,18 @@ class TestBase(TestCase):
         test_host = Host.objects.create(domain='example.com',
                                         fullname='Test Host')
 
-        # Create one new event for each day in the next 10 days,
-        # half with URLs.
-        add_url = True
+        # Create one new published event for each day in the next 10 days.
         for t in range(1, 11):
             event_start = today + datetime.timedelta(days=t)
             date_string = universal_date_format(event_start)
             slug = '{0}-upcoming'.format(date_string)
-            if add_url:
-                url = 'http://' + ('{0}'.format(t) * 20)
-            else:
-                url = None
-            add_url = not add_url
-            e = Event.objects.create(start=event_start,
-                                     slug=slug,
-                                     host=test_host,
-                                     admin_fee=100,
-                                     invoice_status='not-invoiced',
-                                     url=url)
+            url = 'http://example.org/' + ('{0}'.format(t) * 20)
+            e = Event.objects.create(
+                start=event_start, slug=slug,
+                host=test_host, admin_fee=100,
+                url=url, invoice_status='not-invoiced',
+                country='US', venue='School', address='Overthere',
+                latitude=1, longitude=2)
 
         # Create one new event for each day from 10 days ago to
         # 3 days ago, half invoiced
@@ -257,21 +251,23 @@ class TestBase(TestCase):
         # invoiced.
         event_start = today + datetime.timedelta(days=-1)
         event_end = today + datetime.timedelta(days=1)
-        Event.objects.create(start=event_start,
-                             end=event_end,
-                             slug='ends_tomorrow_ongoing',
-                             host=test_host,
-                             admin_fee=0)
+        Event.objects.create(
+            start=event_start, end=event_end, slug='ends-tomorrow-ongoing',
+            host=test_host, admin_fee=0,
+            url='http://example.org/ends-tomorrow-ongoing',
+            country='US', venue='School', address='Overthere',
+            latitude=1, longitude=2)
 
         # Create an event that ends today with no fee, and without
         # specifying whether the fee has been invoiced.
         event_start = today + datetime.timedelta(days=-1)
         event_end = today
-        Event.objects.create(start=event_start,
-                             end=event_end,
-                             slug='ends_today_ongoing',
-                             host=test_host,
-                             admin_fee=0)
+        Event.objects.create(
+            start=event_start, end=event_end, slug='ends-today-ongoing',
+            host=test_host, admin_fee=0,
+            url='http://example.org/ends-today-ongoing',
+            country='US', venue='School', address='Overthere',
+            latitude=1, longitude=2)
 
         # Create an event that starts today with a fee, and without
         # specifying whether the fee has been invoiced.
@@ -279,7 +275,7 @@ class TestBase(TestCase):
         event_end = today + datetime.timedelta(days=1)
         Event.objects.create(start=event_start,
                              end=event_end,
-                             slug='starts_today_ongoing',
+                             slug='starts-today-ongoing',
                              host=test_host,
                              admin_fee=100)
 
diff --git a/workshops/test/test_event.py b/workshops/test/test_event.py
index 3185efc7..64fcbc54 100644
--- a/workshops/test/test_event.py
+++ b/workshops/test/test_event.py
@@ -3,6 +3,7 @@ from urllib.parse import urlencode
 import sys
 
 from django.core.urlresolvers import reverse
+from django.db.models import Q
 from django.db.utils import IntegrityError
 from ..models import (Event, Host, Tag, Role, Task, Award, Badge, TodoItem)
 from ..forms import EventForm, EventsMergeForm
@@ -57,8 +58,8 @@ class TestEvent(TestBase):
         """Test that the events manager can find upcoming events"""
 
         upcoming_events = Event.objects.upcoming_events()
-        assert len(upcoming_events) == self.num_upcoming
-        assert all(['upcoming' in e.slug for e in upcoming_events])
+        expected = Event.objects.filter(slug__endswith='upcoming')
+        self.assertEqual(set(upcoming_events), set(expected))
 
     def test_get_past_events(self):
         """Test that the events manager can find past events"""
@@ -79,20 +80,18 @@ class TestEvent(TestBase):
 
         ongoing_events = Event.objects.ongoing_events()
         event_slugs = [e.slug for e in ongoing_events]
-        correct_slugs = ['starts_today_ongoing',
-                         'ends_tomorrow_ongoing',
-                         'ends_today_ongoing', ]
+        correct_slugs = ['ends-tomorrow-ongoing', 'ends-today-ongoing']
 
-        if sys.version_info >= (3,):
-            self.assertCountEqual(event_slugs, correct_slugs)
-        else:
-            self.assertItemsEqual(event_slugs, correct_slugs)
+        self.assertCountEqual(event_slugs, correct_slugs)
 
     def test_unpublished_events(self):
         """Ensure that events manager finds unpublished events correctly."""
-        all_events = Event.objects.all()
-        self.assertEqual(set(all_events),
-                         set(Event.objects.unpublished_events()))
+        expected = Event.objects.exclude(Q(slug__endswith='upcoming')) \\
+                                .exclude(slug__in=['ends-today-ongoing',
+                                                   'ends-tomorrow-ongoing'])
+        self.assertEqual(set(Event.objects.unpublished_events()),
+                         set(expected))
+
         event_considered_published = Event.objects.create(
             slug='published',
             start=date.today() + timedelta(days=3),
@@ -108,7 +107,7 @@ class TestEvent(TestBase):
 
     def test_delete_event(self):
         """Make sure deleted event and its tasks are no longer accessible."""
-        event = Event.objects.get(slug="starts_today_ongoing")
+        event = Event.objects.get(slug="starts-today-ongoing")
         role1 = Role.objects.create(name='NonInstructor')
         t1 = Task.objects.create(event=event, person=self.spiderman,
                                  role=role1)
@@ -123,7 +122,7 @@ class TestEvent(TestBase):
         assert rv.status_code == 302
 
         with self.assertRaises(Event.DoesNotExist):
-            Event.objects.get(slug="starts_today_ongoing")
+            Event.objects.get(slug="starts-today-ongoing")
 
         for t in [t1, t2, t3]:
             with self.assertRaises(Task.DoesNotExist):
@@ -133,7 +132,7 @@ class TestEvent(TestBase):
         """Ensure we cannot delete an event with related tasks and awards.
 
         Deletion is prevented via Award.event's on_delete=PROTECT."""
-        event = Event.objects.get(slug="starts_today_ongoing")
+        event = Event.objects.get(slug="starts-today-ongoing")
         role = Role.objects.create(name='NonInstructor')
         badge = Badge.objects.create(name='noninstructor',
                                      title='Non-instructor',