Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
dacfcc98
Commit
dacfcc98
authored
Aug 31, 2016
by
Mushtaq Ali
Committed by
Qubad786
Oct 21, 2016
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Generate certificates for verified users with audit certificate statues - ECOM-5012
parent
ada4e082
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
111 additions
and
8 deletions
+111
-8
common/djangoapps/student/models.py
+11
-6
lms/djangoapps/instructor/tests/test_certificates.py
+71
-0
lms/djangoapps/instructor/views/api.py
+7
-1
lms/djangoapps/instructor/views/instructor_dashboard.py
+6
-0
lms/djangoapps/instructor_task/api.py
+6
-1
lms/djangoapps/instructor_task/tasks_helper.py
+4
-0
lms/templates/instructor/instructor_dashboard_2/certificates.html
+6
-0
No files found.
common/djangoapps/student/models.py
View file @
dacfcc98
...
...
@@ -943,12 +943,17 @@ class CourseEnrollmentManager(models.Manager):
return
is_course_full
def
users_enrolled_in
(
self
,
course_id
):
"""Return a queryset of User for every user enrolled in the course."""
return
User
.
objects
.
filter
(
courseenrollment__course_id
=
course_id
,
courseenrollment__is_active
=
True
)
def
users_enrolled_in
(
self
,
course_id
,
mode
=
None
):
"""
Returns a queryset of User for every user enrolled in the course.
course_id (CourseKey): The key of the course associated with the enrollment.
mode (String): The enrolled mode of the users.
"""
_query
=
{
'courseenrollment__course_id'
:
course_id
,
'courseenrollment__is_active'
:
True
}
if
mode
:
_query
[
'courseenrollment__mode'
]
=
mode
return
User
.
objects
.
filter
(
**
_query
)
def
enrollment_counts
(
self
,
course_id
):
"""
...
...
lms/djangoapps/instructor/tests/test_certificates.py
View file @
dacfcc98
...
...
@@ -3,12 +3,19 @@ import contextlib
import
ddt
import
mock
import
json
import
pytz
from
datetime
import
datetime
,
timedelta
from
nose.plugins.attrib
import
attr
from
django.core.urlresolvers
import
reverse
from
django.core.exceptions
import
ObjectDoesNotExist
from
django.test.utils
import
override_settings
from
django.conf
import
settings
from
mock
import
patch
,
PropertyMock
from
course_modes.models
import
CourseMode
from
xmodule.modulestore.tests.django_utils
import
SharedModuleStoreTestCase
from
xmodule.modulestore.tests.factories
import
CourseFactory
from
config_models.models
import
cache
...
...
@@ -344,6 +351,70 @@ class CertificatesInstructorApiTest(SharedModuleStoreTestCase):
u'the "Pending Tasks" section.'
)
@patch
(
'lms.djangoapps.grades.new.course_grade.CourseGrade.summary'
,
PropertyMock
(
return_value
=
{
'grade'
:
'Pass'
,
'percent'
:
0.75
})
)
@override_settings
(
AUDIT_CERT_CUTOFF_DATE
=
datetime
.
now
(
pytz
.
UTC
)
-
timedelta
(
days
=
1
))
@ddt.data
(
(
'verified'
,
'ID Verified'
,
True
),
(
'unverified'
,
'Not ID Verified'
,
False
)
)
@ddt.unpack
def
test_verified_users_with_audit_certs
(
self
,
expected_cert_status
,
verification_output
,
user_verified
):
"""
Test that `verified_users_with_audit_certs` option regenerates certificate for verified users with audit
certificates get certificate.
Scenario:
User enrolled in course as audit,
User passed the course as audit so they have `audit_passing` certificate status,
User switched to verified mode and is ID verified,
Regenerate certificates for `verified_users_with_audit_certs` is run,
Modified certificate status is `verified` if user is ID verified otherwise `unverified`.
"""
# Check that user is enrolled in audit mode.
enrollment
=
CourseEnrollment
.
get_enrollment
(
self
.
user
,
self
.
course
.
id
)
self
.
assertEqual
(
enrollment
.
mode
,
CourseMode
.
AUDIT
)
# Generate certificate for user and check that user has a audit passing certificate.
with
patch
(
'student.models.CourseEnrollment.refund_cutoff_date'
)
as
cutoff_date
:
cutoff_date
.
return_value
=
datetime
.
now
(
pytz
.
UTC
)
-
timedelta
(
minutes
=
5
)
cert_status
=
certs_api
.
generate_user_certificates
(
student
=
self
.
user
,
course_key
=
self
.
course
.
id
,
course
=
self
.
course
)
self
.
assertEqual
(
cert_status
,
CertificateStatuses
.
audit_passing
)
# Update user enrollment mode to verified mode.
enrollment
.
update_enrollment
(
mode
=
'verified'
)
self
.
assertEqual
(
enrollment
.
mode
,
CourseMode
.
VERIFIED
)
with
patch
(
'lms.djangoapps.verify_student.models.SoftwareSecurePhotoVerification.user_is_verified'
)
as
user_verify
:
user_verify
.
return_value
=
user_verified
# Login the client and access the url with 'certificate_statuses'
self
.
client
.
login
(
username
=
self
.
global_staff
.
username
,
password
=
'test'
)
url
=
reverse
(
'start_certificate_regeneration'
,
kwargs
=
{
'course_id'
:
unicode
(
self
.
course
.
id
)})
response
=
self
.
client
.
post
(
url
,
data
=
{
'certificate_statuses'
:
[
'verified_users_with_audit_certs'
]})
# Assert 200 status code in response
self
.
assertEqual
(
response
.
status_code
,
200
)
res_json
=
json
.
loads
(
response
.
content
)
# Assert request is successful
self
.
assertTrue
(
res_json
[
'success'
])
# Assert success message
self
.
assertEqual
(
res_json
[
'message'
],
u'Certificate regeneration task has been started. You can view the status of the generation task in '
u'the "Pending Tasks" section.'
)
# Check user has a not audit passing certificate now.
cert
=
certs_api
.
get_certificate_for_user
(
self
.
user
.
username
,
self
.
course
.
id
)
self
.
assertNotEqual
(
cert
[
'status'
],
CertificateStatuses
.
audit_passing
)
self
.
assertEqual
(
cert
[
'status'
],
expected_cert_status
)
def
test_certificate_regeneration_error
(
self
):
"""
Test certificate regeneration errors out when accessed with either empty list of 'certificate_statuses' or
...
...
lms/djangoapps/instructor/views/api.py
View file @
dacfcc98
...
...
@@ -2862,7 +2862,13 @@ def start_certificate_regeneration(request, course_id):
)
# Check if the selected statuses are allowed
allowed_statuses
=
[
CertificateStatuses
.
downloadable
,
CertificateStatuses
.
error
,
CertificateStatuses
.
notpassing
]
allowed_statuses
=
[
CertificateStatuses
.
downloadable
,
CertificateStatuses
.
error
,
CertificateStatuses
.
notpassing
,
# verified users with audit passing and not passing certificate statuses.
'verified_users_with_audit_certs'
]
if
not
set
(
certificates_statuses
)
.
issubset
(
allowed_statuses
):
return
JsonResponse
(
{
'message'
:
_
(
'Please select certificate statuses from the list only.'
)},
...
...
lms/djangoapps/instructor/views/instructor_dashboard.py
View file @
dacfcc98
...
...
@@ -343,6 +343,11 @@ def _section_certificates(course):
for
certificate
in
GeneratedCertificate
.
get_unique_statuses
(
course_key
=
course
.
id
)
}
# Get the count of all course verified users with audit passing and audit not passing statuses.
verified_users_with_audit_certs
=
CourseEnrollment
.
objects
.
users_enrolled_in
(
course
.
id
,
mode
=
'verified'
)
.
filter
(
generatedcertificate__status__in
=
[
CertificateStatuses
.
audit_passing
,
CertificateStatuses
.
audit_notpassing
]
)
.
count
()
return
{
'section_key'
:
'certificates'
,
'section_display_name'
:
_
(
'Certificates'
),
...
...
@@ -354,6 +359,7 @@ def _section_certificates(course):
'html_cert_enabled'
:
html_cert_enabled
,
'active_certificate'
:
certs_api
.
get_active_web_certificate
(
course
),
'certificate_statuses_with_count'
:
certificate_statuses_with_count
,
'verified_users_with_audit_certs'
:
verified_users_with_audit_certs
,
'status'
:
CertificateStatuses
,
'certificate_generation_history'
:
CertificateGenerationHistory
.
objects
.
filter
(
course_id
=
course
.
id
)
.
order_by
(
"-created"
),
...
...
lms/djangoapps/instructor_task/api.py
View file @
dacfcc98
...
...
@@ -33,7 +33,7 @@ from lms.djangoapps.instructor_task.tasks import (
export_ora2_data
,
)
from
certificates.models
import
CertificateGenerationHistory
from
certificates.models
import
CertificateGenerationHistory
,
CertificateStatuses
from
lms.djangoapps.instructor_task.api_helper
import
(
check_arguments_for_rescoring
,
...
...
@@ -507,6 +507,11 @@ def regenerate_certificates(request, course_key, statuses_to_regenerate):
task_type
=
'regenerate_certificates_all_student'
task_input
=
{}
# Update task_input for verified users with audit passing and not passing certificate statuses.
if
'verified_users_with_audit_certs'
in
statuses_to_regenerate
:
task_input
.
update
({
"student_set"
:
'verified_users_with_audit_certs'
})
statuses_to_regenerate
=
[
CertificateStatuses
.
audit_passing
,
CertificateStatuses
.
audit_notpassing
]
task_input
.
update
({
"statuses_to_regenerate"
:
statuses_to_regenerate
})
task_class
=
generate_certificates
task_key
=
""
...
...
lms/djangoapps/instructor_task/tasks_helper.py
View file @
dacfcc98
...
...
@@ -1429,6 +1429,10 @@ def generate_students_certificates(
specific_student_id
=
task_input
.
get
(
'specific_student_id'
)
students_to_generate_certs_for
=
students_to_generate_certs_for
.
filter
(
id
=
specific_student_id
)
# Verified users with audit passing and not passing certificate statuses.
elif
student_set
==
"verified_users_with_audit_certs"
:
students_to_generate_certs_for
=
CourseEnrollment
.
objects
.
users_enrolled_in
(
course_id
,
mode
=
'verified'
)
task_progress
=
TaskProgress
(
action_name
,
students_to_generate_certs_for
.
count
(),
start_time
)
current_step
=
{
'step'
:
'Calculating students already have certificates'
}
...
...
lms/templates/instructor/instructor_dashboard_2/certificates.html
View file @
dacfcc98
...
...
@@ -130,6 +130,12 @@ from openedx.core.djangolib.js_utils import dump_js_escaped_json, js_escaped_str
</div>
<div>
<label>
<input
id=
"certificate_status_verified_users_with_audit_certs}"
type=
"checkbox"
name=
"certificate_statuses"
value=
"verified_users_with_audit_certs"
>
${_("Regenerate for verified learners with audit certificates. ({count})").format(count=section_data['verified_users_with_audit_certs'])}
</label>
</div>
<div>
<label>
<input
id=
"certificate_status_${section_data['status'].error}"
type=
"checkbox"
name=
"certificate_statuses"
value=
"${section_data['status'].error}"
>
${_("Regenerate for learners in an error state. ({count})").format(count=section_data['certificate_statuses_with_count'].get(section_data['status'].error, 0))}
</label>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment