docs: def getClassTypeMonthlyData(year=None, series=None, typeLimit=None):
      '''
      To break out by class type and month simultaneously, get data for each
      series and aggregate by class type.
      '''
  
      # If no year specified, report current year to date.
      if not year:
          year = timezone.now().year
  
      role_list = DanceRole.objects.distinct()
  
      # Report data on all students registered unless otherwise specified
      if series not in ['registrations','studenthours'] and series not in [x.pluralName for x in role_list]:
          series = 'registrations'
  
      when_all = {
          'eventregistration__dropIn': False,
          'eventregistration__cancelled': False,
      }
  
      annotations = {'registrations': Sum(Case(When(Q(**when_all),then=1),output_field=FloatField()))}
  
      for this_role in role_list:
          annotations[this_role.pluralName] = Sum(Case(When(Q(Q(**when_all) & Q(eventregistration__role=this_role)),then=1),output_field=FloatField()))
  
      series_counts = Series.objects.filter(year=year).annotate(**annotations).annotate(studenthours=F('duration') * F('registrations')).select_related('classDescription__danceTypeLevel__danceType','classDescription__danceTypeLevel')
  
      # If no limit specified on number of types, then do not aggregate dance types.
      # Otherwise, report the typeLimit most common types individually, and report all
      # others as other.  This gets tuples of names and counts
      dance_type_counts = [(dance_type,count) for dance_type,count in Counter([x.classDescription.danceTypeLevel for x in series_counts]).items()]
      dance_type_counts.sort(key=lambda k: k[1],reverse=True)
  
      if typeLimit:
          dance_types = [x[0] for x in dance_type_counts[:typeLimit]]
      else:
          dance_types = [x[0] for x in dance_type_counts]
  
      results = []
  
      # Month by month, calculate the result data
      for month in range(1,13):
          this_month_result = {
              'month': month,
              'month_name': month_name[month],
          }
          for dance_type in dance_types:
              this_month_result[dance_type.__str__()] = \
                  series_counts.filter(classDescription__danceTypeLevel=dance_type,month=month).aggregate(Sum(series))['%s__sum' % series]
  
          if typeLimit:
              this_month_result['Other'] = \
                  series_counts.filter(month=month).exclude(classDescription__danceTypeLevel__in=dance_types).aggregate(Sum(series))['%s__sum' % series]
  
          results.append(this_month_result)
  
      # Now get totals
      totals_result = {
          'month': 'Totals',
          'month_name': 'totals',
      }
  
      for dance_type in dance_types:
          totals_result[dance_type.__str__()] = \
              series_counts.filter(classDescription__danceTypeLevel=dance_type).aggregate(Sum(series))['%s__sum' % series]
  
      if typeLimit:
          totals_result['Other'] = \
              series_counts.exclude(classDescription__danceTypeLevel__in=dance_types).aggregate(Sum(series))['%s__sum' % series]
  
      results.append(totals_result)
  
      return results