145 lines
5.6 KiB
Python
145 lines
5.6 KiB
Python
from django.contrib.auth.models import User
|
|
from django.db import models
|
|
from datetime import datetime
|
|
from model_utils import Choices
|
|
|
|
"""
|
|
Certificates are created for a student and an offering of a course.
|
|
|
|
When a certificate is generated, a unique ID is generated so that
|
|
the certificate can be verified later. The ID is a UUID4, so that
|
|
it can't be easily guessed and so that it is unique.
|
|
|
|
Certificates are generated in batches by a cron job, when a
|
|
certificate is available for download the GeneratedCertificate
|
|
table is updated with information that will be displayed
|
|
on the course overview page.
|
|
|
|
|
|
State diagram:
|
|
|
|
[deleted,error,unavailable] [error,downloadable]
|
|
+ + +
|
|
| | |
|
|
| | |
|
|
add_cert regen_cert del_cert
|
|
| | |
|
|
v v v
|
|
[generating] [regenerating] [deleting]
|
|
+ + +
|
|
| | |
|
|
certificate certificate certificate
|
|
created removed,created deleted
|
|
+----------------+-------------+------->[error]
|
|
| | |
|
|
| | |
|
|
v v v
|
|
[downloadable] [downloadable] [deleted]
|
|
|
|
|
|
Eligibility:
|
|
|
|
Students are eligible for a certificate if they pass the course
|
|
with the following exceptions:
|
|
|
|
If the student has allow_certificate set to False in the student profile
|
|
he will never be issued a certificate.
|
|
|
|
If the user and course is present in the certificate whitelist table
|
|
then the student will be issued a certificate regardless of his grade,
|
|
unless he has allow_certificate set to False.
|
|
|
|
"""
|
|
|
|
|
|
class CertificateStatuses(object):
|
|
deleted = 'deleted'
|
|
deleting = 'deleting'
|
|
downloadable = 'downloadable'
|
|
error = 'error'
|
|
generating = 'generating'
|
|
notpassing = 'notpassing'
|
|
regenerating = 'regenerating'
|
|
restricted = 'restricted'
|
|
unavailable = 'unavailable'
|
|
|
|
class CertificateWhitelist(models.Model):
|
|
"""
|
|
Tracks students who are whitelisted, all users
|
|
in this table will always qualify for a certificate
|
|
regardless of their grade unless they are on the
|
|
embargoed country restriction list
|
|
(allow_certificate set to False in userprofile).
|
|
"""
|
|
user = models.ForeignKey(User)
|
|
course_id = models.CharField(max_length=255, blank=True, default='')
|
|
whitelist = models.BooleanField(default=0)
|
|
|
|
|
|
class GeneratedCertificate(models.Model):
|
|
user = models.ForeignKey(User)
|
|
course_id = models.CharField(max_length=255, blank=True, default='')
|
|
verify_uuid = models.CharField(max_length=32, blank=True, default='')
|
|
download_uuid = models.CharField(max_length=32, blank=True, default='')
|
|
download_url = models.CharField(max_length=128, blank=True, default='')
|
|
grade = models.CharField(max_length=5, blank=True, default='')
|
|
key = models.CharField(max_length=32, blank=True, default='')
|
|
distinction = models.BooleanField(default=False)
|
|
status = models.CharField(max_length=32, default='unavailable')
|
|
MODES = Choices('verified', 'honor', 'audit')
|
|
mode = models.CharField(max_length=32, choices=MODES, default=MODES.honor)
|
|
name = models.CharField(blank=True, max_length=255)
|
|
created_date = models.DateTimeField(
|
|
auto_now_add=True, default=datetime.now)
|
|
modified_date = models.DateTimeField(
|
|
auto_now=True, default=datetime.now)
|
|
error_reason = models.CharField(max_length=512, blank=True, default='')
|
|
|
|
class Meta:
|
|
unique_together = (('user', 'course_id'),)
|
|
|
|
|
|
def certificate_status_for_student(student, course_id):
|
|
'''
|
|
This returns a dictionary with a key for status, and other information.
|
|
The status is one of the following:
|
|
|
|
unavailable - No entry for this student--if they are actually in
|
|
the course, they probably have not been graded for
|
|
certificate generation yet.
|
|
generating - A request has been made to generate a certificate,
|
|
but it has not been generated yet.
|
|
regenerating - A request has been made to regenerate a certificate,
|
|
but it has not been generated yet.
|
|
deleting - A request has been made to delete a certificate.
|
|
|
|
deleted - The certificate has been deleted.
|
|
downloadable - The certificate is available for download.
|
|
notpassing - The student was graded but is not passing
|
|
restricted - The student is on the restricted embargo list and
|
|
should not be issued a certificate. This will
|
|
be set if allow_certificate is set to False in
|
|
the userprofile table
|
|
|
|
If the status is "downloadable", the dictionary also contains
|
|
"download_url".
|
|
|
|
If the student has been graded, the dictionary also contains their
|
|
grade for the course with the key "grade".
|
|
'''
|
|
|
|
try:
|
|
generated_certificate = GeneratedCertificate.objects.get(
|
|
user=student, course_id=course_id)
|
|
d = {'status': generated_certificate.status,
|
|
'mode': generated_certificate.mode}
|
|
if generated_certificate.grade:
|
|
d['grade'] = generated_certificate.grade
|
|
if generated_certificate.status == CertificateStatuses.downloadable:
|
|
d['download_url'] = generated_certificate.download_url
|
|
|
|
return d
|
|
except GeneratedCertificate.DoesNotExist:
|
|
pass
|
|
return {'status': CertificateStatuses.unavailable, 'mode': GeneratedCertificate.MODES.honor}
|