Repository: carpentries/amy

Issue:
Frequency of teaching report is wrong
https://amy.software-carpentry.org/workshops/reports/instructor_num_taught reports that Jonah Duckles has taught 26 times - I don't believe that's correct given our current database.



Discussion:
It seems to be doubling everything, I've taught 13 times, or will after the June workshop I'm scheduled to teach.

Some of the records are okay, ie. I taught 4 times according to my profile and that report reports 4 for me.

![image](https://cloud.githubusercontent.com/assets/119403/15410088/880a2bdc-1ddd-11e6-89dc-36cf77642eff.png)

I've taught 13 time, the report double counts. 

![image](https://cloud.githubusercontent.com/assets/119403/15410118/ab3338b0-1ddd-11e6-9db1-6b9cf8f98024.png)

My unfounded hypothesis is it has to do with having both DC and SWC instructor badges and the way you're joining things.

@jduckles you're definitely right. I gave myself a DC badge and my count jumped from 4 to 8.

@narayanaditya95 will tackle this


Resolving patch:
diff --git a/api/views.py b/api/views.py
--- a/api/views.py
+++ b/api/views.py
@@ -1,7 +1,7 @@
 import datetime
 from itertools import accumulate
 
-from django.db.models import Count, Sum, Case, When, Value, IntegerField
+from django.db.models import Count, Sum, Case, F, When, Value, IntegerField
 from rest_framework import viewsets
 from rest_framework.decorators import list_route
 from rest_framework.filters import DjangoFilterBackend
@@ -329,12 +329,12 @@ def instructor_num_taught(self, request, format=None):
                 Case(
                     When(
                         task__role__name='instructor',
-                        then=Value(1)
+                        then=F('task'),
                     ),
-                    output_field=IntegerField()
-                )
+                ),
+                distinct=True
             )
-        ).filter(may_contact=True).order_by('-num_taught')
+        ).order_by('-num_taught')
         serializer = InstructorNumTaughtSerializer(
             persons, many=True, context=dict(request=request))
         return Response(serializer.data)


Test patch:
diff --git a/api/test/test_reports.py b/api/test/test_reports.py
new file mode 100644
--- /dev/null
+++ b/api/test/test_reports.py
@@ -0,0 +1,83 @@
+import datetime
+import json
+
+from django.core.urlresolvers import reverse
+from rest_framework import status
+from rest_framework.test import APITestCase
+
+from api.views import (
+    ReportsViewSet,
+)
+from api.serializers import InstructorNumTaughtSerializer
+from workshops.models import (
+    Badge,
+    Award,
+    Person,
+    Role,
+    Host,
+    Task,
+    Event,
+)
+
+
+class BaseReportingTest(APITestCase):
+
+    def setUp(self):
+        self.login()
+
+    def login(self):
+        self.admin = Person.objects.create_superuser(
+                username="admin", personal="Super", family="User",
+                email="sudo@example.org", password='admin')
+        self.client.login(username='admin', password='admin')
+
+
+class TestReportingInstructorNumTaught(BaseReportingTest):
+    def setUp(self):
+        super().setUp()
+
+        # get instructor badges
+        swc_instructor, _ = Badge.objects.get_or_create(
+            name='swc-instructor'
+        )
+        dc_instructor, _ = Badge.objects.get_or_create(
+            name='dc-instructor'
+        )
+        # set up an event
+        host = Host.objects.create(domain='host.edu', fullname='Host EDU')
+        event = Event.objects.create(slug='event1', host=host)
+        instructor = Person.objects.create(
+            username='harrypotter', personal='Harry', family='Potter',
+            email='user1@name.org',
+        )
+        instructor_role, _ = Role.objects.get_or_create(name='instructor')
+        Task.objects.create(
+            event=event,
+            person=instructor,
+            role=instructor_role
+        )
+        # Award a SWC Badge
+        Award.objects.create(person=instructor, badge=swc_instructor,
+                             awarded=datetime.date.today())
+        # Award a DC Badge
+        Award.objects.create(person=instructor, badge=dc_instructor,
+                             awarded=datetime.date.today())
+
+        # make sure we *do not* get twice the number expected
+        self.expecting = [
+            {
+                'person': 'http://testserver/api/v1/persons/{}/?format=json'.format(
+                    instructor.pk,
+                ),
+                'name': 'Harry Potter',
+                'num_taught': 1,
+            },
+        ]
+
+    def test_view(self):
+        # test only JSON output
+        url = reverse('api:reports-instructor-num-taught')
+        response = self.client.get(url, {'format': 'json'})
+        content = response.content.decode('utf-8')
+        self.assertEqual(response.status_code, status.HTTP_200_OK)
+        self.assertEqual(json.loads(content), self.expecting)