@@ -0,0 +1,34 @@
|
||||
# Generated by Django 2.2.20 on 2021-06-01 19:00
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import django.utils.timezone
|
||||
import model_utils.fields
|
||||
import opaque_keys.edx.django.models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('certificates', '0025_cleanup_certificate_errors'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='CertificateAllowlist',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')),
|
||||
('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')),
|
||||
('course_id', opaque_keys.edx.django.models.CourseKeyField(blank=True, default=None, max_length=255)),
|
||||
('allowlist', models.BooleanField(default=0)),
|
||||
('notes', models.TextField(default=None, null=True)),
|
||||
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
options={
|
||||
'unique_together': {('course_id', 'user')},
|
||||
},
|
||||
),
|
||||
]
|
||||
@@ -115,6 +115,8 @@ class CertificateWhitelist(models.Model):
|
||||
in this table will always qualify for a certificate
|
||||
regardless of their grade.
|
||||
|
||||
This model is deprecated. CertificateAllowlist should be used in its place.
|
||||
|
||||
.. no_pii:
|
||||
"""
|
||||
class Meta:
|
||||
@@ -175,6 +177,69 @@ class CertificateWhitelist(models.Model):
|
||||
return result
|
||||
|
||||
|
||||
class CertificateAllowlist(TimeStampedModel):
|
||||
"""
|
||||
Tracks students who are on the certificate allowlist for a given course run.
|
||||
|
||||
.. no_pii:
|
||||
"""
|
||||
class Meta:
|
||||
app_label = "certificates"
|
||||
unique_together = [['course_id', 'user']]
|
||||
|
||||
objects = NoneToEmptyManager()
|
||||
|
||||
user = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||
course_id = CourseKeyField(max_length=255, blank=True, default=None)
|
||||
allowlist = models.BooleanField(default=0)
|
||||
notes = models.TextField(default=None, null=True)
|
||||
|
||||
@classmethod
|
||||
def get_certificate_allowlist(cls, course_id, student=None):
|
||||
"""
|
||||
Return the certificate allowlist for the given course as dict object
|
||||
with the following key-value pairs:
|
||||
|
||||
[{
|
||||
id: 'id (pk) of CertificateAllowlist item'
|
||||
user_id: 'User Id of the student'
|
||||
user_name: 'name of the student'
|
||||
user_email: 'email of the student'
|
||||
course_id: 'Course key of the course to whom certificate exception belongs'
|
||||
created: 'Creation date of the certificate exception'
|
||||
notes: 'Additional notes for the certificate exception'
|
||||
}, {...}, ...]
|
||||
|
||||
"""
|
||||
allowlist = cls.objects.filter(course_id=course_id, allowlist=True)
|
||||
if student:
|
||||
allowlist = allowlist.filter(user=student)
|
||||
result = []
|
||||
generated_certificates = GeneratedCertificate.eligible_certificates.filter(
|
||||
course_id=course_id,
|
||||
user__in=[allowlist_item.user for allowlist_item in allowlist],
|
||||
status=CertificateStatuses.downloadable
|
||||
)
|
||||
generated_certificates = {
|
||||
certificate['user']: certificate['created_date']
|
||||
for certificate in generated_certificates.values('user', 'created_date')
|
||||
}
|
||||
|
||||
for item in allowlist:
|
||||
certificate_generated = generated_certificates.get(item.user.id, '')
|
||||
result.append({
|
||||
'id': item.id,
|
||||
'user_id': item.user.id,
|
||||
'user_name': str(item.user.username),
|
||||
'user_email': str(item.user.email),
|
||||
'course_id': str(item.course_id),
|
||||
'created': item.created.strftime("%B %d, %Y"),
|
||||
'certificate_generated': certificate_generated and certificate_generated.strftime("%B %d, %Y"),
|
||||
'notes': str(item.notes or ''),
|
||||
})
|
||||
return result
|
||||
|
||||
|
||||
class EligibleCertificateManager(models.Manager):
|
||||
"""
|
||||
A manager for `GeneratedCertificate` models that automatically
|
||||
@@ -395,7 +460,7 @@ class GeneratedCertificate(models.Model):
|
||||
def _revoke_certificate(self, status, grade=None, source=None):
|
||||
"""
|
||||
Revokes a course certificate from a learner, updating the certificate's status as specified by the value of the
|
||||
`status` argument. This will prevent the learner from being able to access their certiticate in the associated
|
||||
`status` argument. This will prevent the learner from being able to access their certificate in the associated
|
||||
course run.
|
||||
|
||||
We remove the `download_uuid` and the `download_url` as well, but this is only important to PDF certificates.
|
||||
@@ -503,7 +568,7 @@ class CertificateGenerationHistory(TimeStampedModel):
|
||||
|
||||
1. "All learners" Certificate Generation task was initiated for all learners of the given course.
|
||||
2. Comma separated list of certificate statuses, This usually happens when instructor regenerates certificates.
|
||||
3. "for exceptions", This is the case when instructor generates certificates for white-listed
|
||||
3. "for exceptions", This is the case when instructor generates certificates for allowlisted
|
||||
students.
|
||||
"""
|
||||
task_input = self.instructor_task.task_input
|
||||
@@ -524,7 +589,7 @@ class CertificateGenerationHistory(TimeStampedModel):
|
||||
return ", ".join(readable_statuses)
|
||||
|
||||
# If "student_set" is present in task_input, then this task only
|
||||
# generates certificates for white listed students. Note that
|
||||
# generates certificates for allowlisted students. Note that
|
||||
# this key used to be "students", so we include that in this conditional
|
||||
# for backwards compatibility.
|
||||
if 'student_set' in task_input_json or 'students' in task_input_json:
|
||||
@@ -1092,11 +1157,11 @@ class CertificateHtmlViewConfiguration(ConfigurationModel):
|
||||
Example configuration :
|
||||
{
|
||||
"default": {
|
||||
"url": "http://www.edx.org",
|
||||
"logo_src": "http://www.edx.org/static/images/logo.png"
|
||||
"url": "https://www.edx.org",
|
||||
"logo_src": "https://www.edx.org/static/images/logo.png"
|
||||
},
|
||||
"honor": {
|
||||
"logo_src": "http://www.edx.org/static/images/honor-logo.png"
|
||||
"logo_src": "https://www.edx.org/static/images/honor-logo.png"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user