Repository: kartoza/prj.app

Issue:
We should not show 'future' sponsors
See https://github.com/qgis/QGIS-Website/issues/550#issuecomment-405466754

Sometimes there are sponsor records in future, we should create a  query to NOT have those in results


Discussion:
I guess this is just for the feed right?
@andreasneumann @timlinux  if I understand Andrea's comment on  qgis/QGIS-Website#550 right, it should just not show up in generated html lists too?

But this kind of list, well, depending on the function of it:
http://changelog.qgis.org/en/qgis/sponsors/list/
should show it (if it is used by Andreas to edit items), or NOT show it if it is to be viewed by 'normal' users.

But to fix THIS issue now, I would only do it for the feed for now (Andreas?).
I think the full information (including upcoming sponsorships) should only be availabel to admin. Everyone else should just see the currently active sponsors.

Resolving patch:
diff --git a/django_project/changes/models/sponsorship_period.py b/django_project/changes/models/sponsorship_period.py
--- a/django_project/changes/models/sponsorship_period.py
+++ b/django_project/changes/models/sponsorship_period.py
@@ -156,15 +156,18 @@ def get_absolute_url(self):
     def current_sponsor(self):
         today = datetime.datetime.now().date()
         end = self.end_date
-        if not end:
-            if self.recurring:
-                return True
+        start = self.start_date
+        if end < today or start > today:
+            return False
+        else:
+            return True
+
+    def future_sponsor(self):
+        today = datetime.datetime.now().date()
+        end = self.end_date
+        start = self.start_date
+        if end < today or start < today:
             return False
-        if end < today:
-            if self.recurring:
-                return True
-            else:
-                return False
         else:
             return True
 
diff --git a/django_project/changes/urls.py b/django_project/changes/urls.py
--- a/django_project/changes/urls.py
+++ b/django_project/changes/urls.py
@@ -59,6 +59,7 @@
     ApproveSponsorView,
     RejectSponsorView,
     GenerateSponsorPDFView,
+    FutureSponsorListView,
     SustainingMembership,
     SustainingMemberUpdateView,
     SustainingMemberPeriodCreateView,
@@ -265,6 +266,9 @@
     url(regex='^(?P<project_slug>[\w-]+)/members/list/$',
         view=SponsorListView.as_view(),
         name='sponsor-list'),
+    url(regex='^(?P<project_slug>[\w-]+)/future-members/list/$',
+        view=FutureSponsorListView.as_view(),
+        name='future-sponsor-list'),
     url(regex='^(?P<project_slug>[\w-]+)/members/world-map/$',
         view=SponsorWorldMapView.as_view(),
         name='sponsor-world-map'),
diff --git a/django_project/changes/views/sponsor.py b/django_project/changes/views/sponsor.py
--- a/django_project/changes/views/sponsor.py
+++ b/django_project/changes/views/sponsor.py
@@ -192,6 +192,66 @@ def get_queryset(self, queryset=None):
         return self.queryset
 
 
+class FutureSponsorListView(
+    LoginRequiredMixin, SponsorMixin, PaginationMixin, ListView):
+    """List view for Sponsor."""
+    context_object_name = 'sponsors'
+    template_name = 'sponsor/future-list.html'
+    paginate_by = 1000
+
+    def get_context_data(self, **kwargs):
+        """Get the context data which is passed to a template.
+
+        :param kwargs: Any arguments to pass to the superclass.
+        :type kwargs: dict
+
+        :returns: Context data which will be passed to the template.
+        :rtype: dict
+        """
+
+        context = super(FutureSponsorListView, self).get_context_data(**kwargs)
+        context['num_sponsors'] = context['sponsors'].count()
+        context['unapproved'] = False
+        project_slug = self.kwargs.get('project_slug', None)
+        context['project_slug'] = project_slug
+        if project_slug:
+            project = Project.objects.get(slug=project_slug)
+            # Checking user permissions.
+            if self.request.user.is_staff or \
+                    self.request.user == project.owner or \
+                    self.request.user in project.sponsorship_managers.all()\
+                    or self.request.user == project.project_representative:
+                pass
+            else:
+                raise Http404
+
+            context['project'] = Project.objects.get(slug=project_slug)
+            context['levels'] = SponsorshipLevel.objects.filter(
+                project=project)
+        return context
+
+    def get_queryset(self, queryset=None):
+        """Get the queryset for this view.
+
+        :param queryset: A query set
+        :type queryset: QuerySet
+
+        :returns: Sponsor Queryset which is filtered by project
+        :rtype: QuerySet
+        :raises: Http404
+        """
+        if self.queryset is None:
+            project_slug = self.kwargs.get('project_slug', None)
+            if project_slug:
+                project = Project.objects.get(slug=project_slug)
+                queryset = SponsorshipPeriod.approved_objects.filter(
+                    project=project).order_by('-sponsorship_level__value')
+                return queryset
+            else:
+                raise Http404('Sorry! We could not find your Sponsor!')
+        return self.queryset
+
+
 class SponsorWorldMapView(SponsorMixin, ListView):
     """World map view for Sponsors."""
     context_object_name = 'sponsors'


Test patch:
diff --git a/django_project/changes/tests/test_views.py b/django_project/changes/tests/test_views.py
--- a/django_project/changes/tests/test_views.py
+++ b/django_project/changes/tests/test_views.py
@@ -1,7 +1,9 @@
 # coding=utf-8
 # flake8: noqa
 
+import datetime
 import json
+from datetime import timedelta
 from mock import mock
 from django.urls import reverse
 from django.http import HttpResponse
@@ -1308,6 +1310,8 @@ def setUp(self):
         logging.disable(logging.CRITICAL)
         self.project = ProjectF.create()
         self.sponsor = SponsorF.create(project=self.project)
+        self.current_sponsor = SponsorF.create(project=self.project)
+        self.future_sponsor = SponsorF.create(project=self.project)
         self.user = UserF.create(**{
             'username': 'timlinux',
             'password': 'password',
@@ -1321,6 +1325,40 @@ def setUp(self):
         self.user.set_password('password')
         self.user.save()
 
+        self.non_staff_user = UserF.create(**{
+            'username': 'non-staff',
+            'password': 'password',
+            'is_staff': False
+        })
+        self.non_staff_user.set_password('password')
+        self.non_staff_user.save()
+
+        self.sponsorship_level = SponsorshipLevelF.create(
+            project=self.project,
+            name='Gold')
+        self.today = datetime.date.today()
+        self.past_sponsorship_period = SponsorshipPeriodF.create(
+            project=self.project,
+            sponsor=self.sponsor,
+            sponsorship_level=self.sponsorship_level,
+            start_date=self.today - timedelta(days=200),
+            end_date=self.today - timedelta(days=100),
+            approved=True)
+        self.current_sponsorship_period = SponsorshipPeriodF.create(
+            project=self.project,
+            sponsor=self.current_sponsor,
+            sponsorship_level=self.sponsorship_level,
+            start_date=self.today,
+            end_date=self.today + timedelta(days=700),
+            approved=True)
+        self.future_sponsorship_period = SponsorshipPeriodF.create(
+            project=self.project,
+            sponsor=self.future_sponsor,
+            sponsorship_level=self.sponsorship_level,
+            start_date=self.today + timedelta(days=200),
+            end_date=self.today + timedelta(days=700),
+            approved=True)
+
     @override_settings(VALID_DOMAIN=['testserver', ])
     def tearDown(self):
         """
@@ -1340,6 +1378,29 @@ def test_SponsorListView(self):
         }))
         self.assertEqual(response.status_code, 200)
 
+    @override_settings(VALID_DOMAIN=['testserver', ])
+    def test_FutureSponsorListView_no_login(self):
+        response = self.client.get(reverse('future-sponsor-list', kwargs={
+            'project_slug': self.project.slug
+        }))
+        self.assertEqual(response.status_code, 302)
+
+    @override_settings(VALID_DOMAIN=['testserver', ])
+    def test_FutureSponsorListView_with_staff_login(self):
+        self.client.login(username='timlinux', password='password')
+        response = self.client.get(reverse('future-sponsor-list', kwargs={
+            'project_slug': self.project.slug
+        }))
+        self.assertEqual(response.status_code, 200)
+
+    @override_settings(VALID_DOMAIN=['testserver', ])
+    def test_FutureSponsorListView_with_non_staff_login(self):
+        self.client.login(username='non-staff', password='password')
+        response = self.client.get(reverse('future-sponsor-list', kwargs={
+            'project_slug': self.project.slug
+        }))
+        self.assertEqual(response.status_code, 404)
+
     @override_settings(VALID_DOMAIN=['testserver', ])
     def test_SponsorWorldMapView(self):