models.py 5.38 KB
Newer Older
1 2
from django.contrib.auth.models import User
from django.db import models
3
from datetime import datetime
4

Victor Shnayder committed
5
"""
6 7
Certificates are created for a student and an offering of a course.

8
When a certificate is generated, a unique ID is generated so that
9
the certificate can be verified later. The ID is a UUID4, so that
John Jarvis committed
10
it can't be easily guessed and so that it is unique.
11

12 13 14 15
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.
16

17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37

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]

38 39 40 41 42 43 44 45 46 47 48 49 50

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.

Victor Shnayder committed
51
"""
John Jarvis committed
52

53

54
class CertificateStatuses(object):
John Jarvis committed
55 56 57 58 59 60
    unavailable = 'unavailable'
    generating = 'generating'
    regenerating = 'regenerating'
    deleting = 'deleting'
    deleted = 'deleted'
    downloadable = 'downloadable'
61
    notpassing = 'notpassing'
62
    restricted = 'restricted'
John Jarvis committed
63 64
    error = 'error'

Calen Pennington committed
65

66
class CertificateWhitelist(models.Model):
67 68 69 70 71 72 73
    """
    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).
    """
74 75 76
    user = models.ForeignKey(User)
    course_id = models.CharField(max_length=255, blank=True, default='')
    whitelist = models.BooleanField(default=0)
77

Calen Pennington committed
78

79
class GeneratedCertificate(models.Model):
80
    user = models.ForeignKey(User)
81 82 83 84 85 86 87 88
    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')
89
    name = models.CharField(blank=True, max_length=255)
90 91 92 93
    created_date = models.DateTimeField(
            auto_now_add=True, default=datetime.now)
    modified_date = models.DateTimeField(
            auto_now=True, default=datetime.now)
John Jarvis committed
94
    error_reason = models.CharField(max_length=512, blank=True, default='')
95 96

    class Meta:
John Jarvis committed
97 98
        unique_together = (('user', 'course_id'),)

99 100

def certificate_status_for_student(student, course_id):
101
    '''
102 103
    This returns a dictionary with a key for status, and other information.
    The status is one of the following:
104

105 106 107
    unavailable  - No entry for this student--if they are actually in
                   the course, they probably have not been graded for
                   certificate generation yet.
108 109 110
    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,
John Jarvis committed
111
                   but it has not been generated yet.
112
    deleting     - A request has been made to delete a certificate.
John Jarvis committed
113

114 115
    deleted      - The certificate has been deleted.
    downloadable - The certificate is available for download.
116
    notpassing   - The student was graded but is not passing
117
    restricted   - The student is on the restricted embargo list and
118 119 120
                   should not be issued a certificate. This will
                   be set if allow_certificate is set to False in
                   the userprofile table
121 122 123

    If the status is "downloadable", the dictionary also contains
    "download_url".
124

125
    If the student has been graded, the dictionary also contains their
126
    grade for the course with the key "grade".
127
    '''
128

129 130
    try:
        generated_certificate = GeneratedCertificate.objects.get(
131
                user=student, course_id=course_id)
132 133 134
        d = {'status': generated_certificate.status}
        if generated_certificate.grade:
            d['grade'] = generated_certificate.grade
135
        if generated_certificate.status == CertificateStatuses.downloadable:
136
            d['download_url'] = generated_certificate.download_url
137 138

        return d
139 140
    except GeneratedCertificate.DoesNotExist:
        pass
141
    return {'status': CertificateStatuses.unavailable}