models.py 5.63 KB
Newer Older
1 2
from django.contrib.auth.models import User
from django.db import models
3
from datetime import datetime
4
from model_utils import Choices
5

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

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

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

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

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]

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

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
52
"""
John Jarvis committed
53

54

55
class CertificateStatuses(object):
56 57
    deleted      = 'deleted'
    deleting     = 'deleting'
John Jarvis committed
58
    downloadable = 'downloadable'
59 60 61 62 63 64
    error        = 'error'
    generating   = 'generating'
    notpassing   = 'notpassing'
    regenerating = 'regenerating'
    restricted   = 'restricted'
    unavailable  = 'unavailable'
John Jarvis 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 90
    MODES = Choices('verified', 'honor', 'audit')
    mode = models.CharField(max_length=32, choices=MODES, default=MODES.honor)
91
    name = models.CharField(blank=True, max_length=255)
92
    created_date = models.DateTimeField(
93
        auto_now_add=True, default=datetime.now)
94
    modified_date = models.DateTimeField(
95
        auto_now=True, default=datetime.now)
John Jarvis committed
96
    error_reason = models.CharField(max_length=512, blank=True, default='')
97 98

    class Meta:
John Jarvis committed
99 100
        unique_together = (('user', 'course_id'),)

101 102

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

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

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

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

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

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

        return d
142 143
    except GeneratedCertificate.DoesNotExist:
        pass
144
    return {'status': CertificateStatuses.unavailable, 'mode': GeneratedCertificate.MODES.honor}