Fix gen_cert_report to use CourseKeys.
This commit is contained in:
@@ -1,9 +1,16 @@
|
||||
from django.core.management.base import BaseCommand
|
||||
"""
|
||||
Generate a report of certificate statuses
|
||||
"""
|
||||
|
||||
from django.core.management.base import BaseCommand, CommandError
|
||||
from certificates.models import GeneratedCertificate
|
||||
from django.contrib.auth.models import User
|
||||
from optparse import make_option
|
||||
from django.conf import settings
|
||||
from opaque_keys import InvalidKeyError
|
||||
from xmodule.course_module import CourseDescriptor
|
||||
from xmodule.modulestore.keys import CourseKey
|
||||
from xmodule.modulestore.locations import SlashSeparatedCourseKey
|
||||
from xmodule.modulestore.django import modulestore
|
||||
from django.db.models import Count
|
||||
|
||||
@@ -12,7 +19,7 @@ class Command(BaseCommand):
|
||||
|
||||
help = """
|
||||
|
||||
Generate a certificate status report for all courses that have ended.
|
||||
Generate a certificate status report for a given course.
|
||||
This command does not do anything other than report the current
|
||||
certificate status.
|
||||
|
||||
@@ -34,81 +41,89 @@ class Command(BaseCommand):
|
||||
dest='course',
|
||||
default=None,
|
||||
help='Only generate for COURSE_ID'),
|
||||
)
|
||||
|
||||
def _ended_courses(self):
|
||||
for course_id in [course # all courses in COURSE_LISTINGS
|
||||
for sub in settings.COURSE_LISTINGS
|
||||
for course in settings.COURSE_LISTINGS[sub]]:
|
||||
course = modulestore().get_course(course_id)
|
||||
if course.has_ended():
|
||||
yield course_id
|
||||
)
|
||||
|
||||
def handle(self, *args, **options):
|
||||
|
||||
# Find all courses that have ended
|
||||
|
||||
if options['course']:
|
||||
ended_courses = [options['course']]
|
||||
try:
|
||||
course_id = CourseKey.from_string(options['course'])
|
||||
except InvalidKeyError:
|
||||
print("Course id {} could not be parsed as a CourseKey; falling back to SSCK.from_dep_str".format(options['course']))
|
||||
course_id = SlashSeparatedCourseKey.from_deprecated_string(options['course'])
|
||||
else:
|
||||
ended_courses = self._ended_courses()
|
||||
raise CommandError("You must specify a course")
|
||||
|
||||
cert_data = {}
|
||||
|
||||
for course_id in ended_courses:
|
||||
# find students who are active
|
||||
# number of enrolled students = downloadable + notpassing
|
||||
print "Looking up certificate states for {0}".format(options['course'])
|
||||
enrolled_current = User.objects.filter(
|
||||
courseenrollment__course_id=course_id,
|
||||
courseenrollment__is_active=True
|
||||
)
|
||||
enrolled_total = User.objects.filter(
|
||||
courseenrollment__course_id=course_id
|
||||
)
|
||||
verified_enrolled = GeneratedCertificate.objects.filter(
|
||||
course_id__exact=course_id, mode__exact='verified'
|
||||
)
|
||||
honor_enrolled = GeneratedCertificate.objects.filter(
|
||||
course_id__exact=course_id, mode__exact='honor'
|
||||
)
|
||||
audit_enrolled = GeneratedCertificate.objects.filter(
|
||||
course_id__exact=course_id, mode__exact='audit'
|
||||
)
|
||||
|
||||
# find students who are active
|
||||
# enrolled students are always downloable + notpassing
|
||||
print "Looking up certificate states for {0}".format(course_id)
|
||||
enrolled_current = User.objects.filter(
|
||||
courseenrollment__course_id=course_id,
|
||||
courseenrollment__is_active=True)
|
||||
enrolled_total = User.objects.filter(
|
||||
courseenrollment__course_id=course_id)
|
||||
verified_enrolled = GeneratedCertificate.objects.filter(
|
||||
course_id__exact=course_id, mode__exact='verified')
|
||||
honor_enrolled = GeneratedCertificate.objects.filter(
|
||||
course_id__exact=course_id, mode__exact='honor')
|
||||
audit_enrolled = GeneratedCertificate.objects.filter(
|
||||
course_id__exact=course_id, mode__exact='audit')
|
||||
cert_data[course_id] = {
|
||||
'enrolled_current': enrolled_current.count(),
|
||||
'enrolled_total': enrolled_total.count(),
|
||||
'verified_enrolled': verified_enrolled.count(),
|
||||
'honor_enrolled': honor_enrolled.count(),
|
||||
'audit_enrolled': audit_enrolled.count()
|
||||
}
|
||||
|
||||
cert_data[course_id] = {'enrolled_current': enrolled_current.count(),
|
||||
'enrolled_total': enrolled_total.count(),
|
||||
'verified_enrolled': verified_enrolled.count(),
|
||||
'honor_enrolled': honor_enrolled.count(),
|
||||
'audit_enrolled': audit_enrolled.count()}
|
||||
status_tally = GeneratedCertificate.objects.filter(
|
||||
course_id__exact=course_id
|
||||
).values('status').annotate(
|
||||
dcount=Count('status')
|
||||
)
|
||||
|
||||
status_tally = GeneratedCertificate.objects.filter(
|
||||
course_id__exact=course_id).values('status').annotate(
|
||||
dcount=Count('status'))
|
||||
cert_data[course_id].update(
|
||||
{status['status']: status['dcount']
|
||||
for status in status_tally})
|
||||
cert_data[course_id].update(
|
||||
{status['status']: status['dcount']
|
||||
for status in status_tally})
|
||||
|
||||
mode_tally = GeneratedCertificate.objects.filter(
|
||||
course_id__exact=course_id,
|
||||
status__exact='downloadable').values('mode').annotate(
|
||||
dcount=Count('mode'))
|
||||
cert_data[course_id].update(
|
||||
{mode['mode']: mode['dcount']
|
||||
for mode in mode_tally})
|
||||
mode_tally = GeneratedCertificate.objects.filter(
|
||||
course_id__exact=course_id,
|
||||
status__exact='downloadable'
|
||||
).values('mode').annotate(
|
||||
dcount=Count('mode')
|
||||
)
|
||||
cert_data[course_id].update(
|
||||
{mode['mode']: mode['dcount']
|
||||
for mode in mode_tally}
|
||||
)
|
||||
|
||||
# all states we have seen far all courses
|
||||
status_headings = sorted(set(
|
||||
[status for course in cert_data
|
||||
for status in cert_data[course]]))
|
||||
for status in cert_data[course]])
|
||||
)
|
||||
|
||||
# print the heading for the report
|
||||
print "{:>26}".format("course ID"),
|
||||
print ' '.join(["{:>16}".format(heading)
|
||||
for heading in status_headings])
|
||||
for heading in status_headings]
|
||||
)
|
||||
|
||||
# print the report
|
||||
for course_id in cert_data:
|
||||
print "{0:>26}".format(course_id[0:24]),
|
||||
for heading in status_headings:
|
||||
if heading in cert_data[course_id]:
|
||||
print "{:>16}".format(cert_data[course_id][heading]),
|
||||
else:
|
||||
print " " * 16,
|
||||
print
|
||||
print "{0:>26}".format(course_id.to_deprecated_string()),
|
||||
for heading in status_headings:
|
||||
if heading in cert_data[course_id]:
|
||||
print "{:>16}".format(cert_data[course_id][heading]),
|
||||
else:
|
||||
print " " * 16,
|
||||
print
|
||||
|
||||
Reference in New Issue
Block a user