Repository: carpentries/amy

Issue:
Add country, workshop type to instructors_num_taught
We have [this report](https://amy.software-carpentry.org/api/v1/reports/instructor_num_taught/) that shows how often each instructor has taught.  I'd like this to include the country and subtotals for the workshop type.   For example a row that currently looks like this:

```
    {
        "person": "https://amy.software-carpentry.org/api/v1/persons/9999/",
        "name": "Harry Potter",
        "num_taught": 9
    }
```

should look like this: 

```
    {
        "person": "https://amy.software-carpentry.org/api/v1/persons/9999/",
        "name": "Harry Potter",
        "country": "GB",
        "num_taught_SWC": 0,
        "num_taught_DC": 1,
        "num_taught_LC": 2,
        "num_taught_TTT": 0,
        "num_taught_total": 3
    }
```


Discussion:

Resolving patch:
diff --git a/amy/api/serializers.py b/amy/api/serializers.py
--- a/amy/api/serializers.py
+++ b/amy/api/serializers.py
@@ -120,7 +120,12 @@ class InstructorNumTaughtSerializer(serializers.Serializer):
         read_only=True, view_name='api:person-detail', lookup_field='pk',
         source='*')
     name = serializers.CharField(source='full_name')
-    num_taught = serializers.IntegerField()
+    country = serializers.CharField()
+    num_taught_SWC = serializers.IntegerField()
+    num_taught_DC = serializers.IntegerField()
+    num_taught_LC = serializers.IntegerField()
+    num_taught_TTT = serializers.IntegerField()
+    num_taught_total = serializers.IntegerField()
 
 
 class InstructorsByTimePeriodSerializer(serializers.ModelSerializer):
diff --git a/amy/api/views.py b/amy/api/views.py
--- a/amy/api/views.py
+++ b/amy/api/views.py
@@ -445,16 +445,56 @@ def instructors_over_time(self, request, format=None):
     def instructor_num_taught(self, request, format=None):
         badges = Badge.objects.instructor_badges()
         persons = Person.objects.filter(badges__in=badges).annotate(
-            num_taught=Count(
+            num_taught_SWC=Count(
                 Case(
                     When(
                         task__role__name='instructor',
+                        task__event__tags__name='SWC',
                         then=F('task'),
                     ),
                 ),
                 distinct=True
-            )
-        ).order_by('-num_taught')
+            ),
+            num_taught_DC=Count(
+                Case(
+                    When(
+                        task__role__name='instructor',
+                        task__event__tags__name='DC',
+                        then=F('task'),
+                    ),
+                ),
+                distinct=True
+            ),
+            num_taught_LC=Count(
+                Case(
+                    When(
+                        task__role__name='instructor',
+                        task__event__tags__name='LC',
+                        then=F('task'),
+                    ),
+                ),
+                distinct=True
+            ),
+            num_taught_TTT=Count(
+                Case(
+                    When(
+                        task__role__name='instructor',
+                        task__event__tags__name='TTT',
+                        then=F('task'),
+                    ),
+                ),
+                distinct=True
+            ),
+            num_taught_total=Count(
+                Case(
+                    When(
+                        task__role__name='instructor',
+                        then=F('task'),
+                    ),
+                ),
+                distinct=True
+            ),
+        ).order_by('-num_taught_total')
         serializer = InstructorNumTaughtSerializer(
             persons, many=True, context=dict(request=request))
         return Response(serializer.data)


Test patch:
diff --git a/amy/api/tests/test_reports.py b/amy/api/tests/test_reports.py
--- a/amy/api/tests/test_reports.py
+++ b/amy/api/tests/test_reports.py
@@ -18,6 +18,7 @@
     Organization,
     Task,
     Event,
+    Tag,
 )
 from workshops.tests.base import TestBase
 
@@ -47,23 +48,52 @@ def setUp(self):
         dc_instructor, _ = Badge.objects.get_or_create(
             name='dc-instructor'
         )
-        # set up an event
-        host = Organization.objects.create(domain='host.edu', fullname='Organization EDU')
-        event = Event.objects.create(slug='event1', host=host)
+        lc_instructor, _ = Badge.objects.get_or_create(
+            name='lc-instructor'
+        )
+
+        # prepare tags
+        Tag.objects.bulk_create([
+            Tag(name='TTT', details=''),
+            Tag(name='LC', details=''),
+            Tag(name='DC', details=''),
+            Tag(name='SWC', details=''),
+        ])
+
+        # prepare an instructor
         instructor = Person.objects.create(
             username='harrypotter', personal='Harry', family='Potter',
-            email='user1@name.org',
+            email='user1@name.org', country='GB',
         )
+
+        # prepare instructor role
         instructor_role, _ = Role.objects.get_or_create(name='instructor')
+
+        # create an organization host
+        host = Organization.objects.create(domain='host.edu',
+                                           fullname='Organization EDU')
+
+        # set up events
+        event1 = Event.objects.create(slug='event1', host=host)
+        event2 = Event.objects.create(slug='event2', host=host)
+        event2.tags.set(
+            Tag.objects.filter(name__in=['SWC', 'DC', 'LC', 'TTT']))
+
         Task.objects.create(
-            event=event,
+            event=event1,
             person=instructor,
             role=instructor_role
         )
-        # Award a SWC Badge
+        Task.objects.create(
+            event=event2,
+            person=instructor,
+            role=instructor_role
+        )
+
+        # Award a SWC, DC and LC badges
         Award.objects.create(person=instructor, badge=swc_instructor)
-        # Award a DC Badge
         Award.objects.create(person=instructor, badge=dc_instructor)
+        Award.objects.create(person=instructor, badge=lc_instructor)
 
         # make sure we *do not* get twice the number expected
         self.expecting = [
@@ -72,7 +102,12 @@ def setUp(self):
                     instructor.pk,
                 ),
                 'name': 'Harry Potter',
-                'num_taught': 1,
+                'country': 'GB',
+                'num_taught_SWC': 1,
+                'num_taught_DC': 1,
+                'num_taught_LC': 1,
+                'num_taught_TTT': 1,
+                'num_taught_total': 2,
             },
         ]