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
e88a4e5c
Commit
e88a4e5c
authored
May 12, 2016
by
Renzo Lucioni
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #12437 from edx/renzo/filter-by-passing-certs
Tune program credential backpopulation command
parents
76449b6a
dbe6dfc2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
63 additions
and
4 deletions
+63
-4
openedx/core/djangoapps/programs/management/commands/backpopulate_program_credentials.py
+5
-3
openedx/core/djangoapps/programs/tests/test_backpopulate_program_credentials.py
+58
-1
No files found.
openedx/core/djangoapps/programs/management/commands/backpopulate_program_credentials.py
View file @
e88a4e5c
...
...
@@ -7,7 +7,7 @@ from django.db.models import Q
from
opaque_keys.edx.keys
import
CourseKey
from
provider.oauth2.models
import
Client
from
certificates.models
import
GeneratedCertificate
# pylint: disable=import-error
from
certificates.models
import
GeneratedCertificate
,
CertificateStatuses
# pylint: disable=import-error
from
openedx.core.djangoapps.programs.models
import
ProgramsApiConfig
from
openedx.core.djangoapps.programs.tasks.v1.tasks
import
award_program_certificates
from
openedx.core.djangoapps.programs.utils
import
get_programs
...
...
@@ -109,11 +109,13 @@ class Command(BaseCommand):
This is done by finding users who have earned a certificate in at least one
program course code's run mode.
"""
query
=
reduce
(
status_query
=
Q
(
status__in
=
CertificateStatuses
.
PASSED_STATUSES
)
run_mode_query
=
reduce
(
lambda
x
,
y
:
x
|
y
,
[
Q
(
course_id
=
r
.
course_key
,
mode
=
r
.
mode_slug
)
for
r
in
self
.
run_modes
]
)
# TODO: Filter further, by passing status?
query
=
status_query
&
run_mode_query
username_dicts
=
GeneratedCertificate
.
eligible_certificates
.
filter
(
query
)
.
values
(
'user__username'
)
.
distinct
()
self
.
usernames
=
[
d
[
'user__username'
]
for
d
in
username_dicts
]
openedx/core/djangoapps/programs/tests/test_backpopulate_program_credentials.py
View file @
e88a4e5c
...
...
@@ -11,6 +11,7 @@ import httpretty
import
mock
from
provider.constants
import
CONFIDENTIAL
from
certificates.models
import
CertificateStatuses
# pylint: disable=import-error
from
lms.djangoapps.certificates.api
import
MODES
from
lms.djangoapps.certificates.tests.factories
import
GeneratedCertificateFactory
from
openedx.core.djangoapps.programs.models
import
ProgramsApiConfig
...
...
@@ -38,7 +39,10 @@ class BackpopulateProgramCredentialsTests(ProgramsApiConfigMixin, TestCase):
self
.
oauth2_user
=
UserFactory
()
self
.
oauth2_client
=
ClientFactory
(
name
=
ProgramsApiConfig
.
OAUTH2_CLIENT_NAME
,
client_type
=
CONFIDENTIAL
)
self
.
create_programs_config
()
# Disable certification to prevent the task from being triggered when
# setting up test data (i.e., certificates with a passing status), thereby
# skewing mock call counts.
self
.
create_programs_config
(
enable_certification
=
False
)
def
_link_oauth2_user
(
self
):
"""Helper to link user and OAuth2 client."""
...
...
@@ -74,12 +78,14 @@ class BackpopulateProgramCredentialsTests(ProgramsApiConfigMixin, TestCase):
user
=
self
.
alice
,
course_id
=
self
.
course_id
,
mode
=
MODES
.
verified
,
status
=
CertificateStatuses
.
downloadable
,
)
GeneratedCertificateFactory
(
user
=
self
.
bob
,
course_id
=
self
.
alternate_course_id
,
mode
=
MODES
.
verified
,
status
=
CertificateStatuses
.
downloadable
,
)
call_command
(
'backpopulate_program_credentials'
,
commit
=
commit
)
...
...
@@ -142,12 +148,14 @@ class BackpopulateProgramCredentialsTests(ProgramsApiConfigMixin, TestCase):
user
=
self
.
alice
,
course_id
=
self
.
course_id
,
mode
=
MODES
.
verified
,
status
=
CertificateStatuses
.
downloadable
,
)
GeneratedCertificateFactory
(
user
=
self
.
bob
,
course_id
=
self
.
alternate_course_id
,
mode
=
MODES
.
verified
,
status
=
CertificateStatuses
.
downloadable
,
)
call_command
(
'backpopulate_program_credentials'
,
commit
=
True
)
...
...
@@ -178,12 +186,14 @@ class BackpopulateProgramCredentialsTests(ProgramsApiConfigMixin, TestCase):
user
=
self
.
alice
,
course_id
=
self
.
course_id
,
mode
=
MODES
.
verified
,
status
=
CertificateStatuses
.
downloadable
,
)
GeneratedCertificateFactory
(
user
=
self
.
alice
,
course_id
=
self
.
alternate_course_id
,
mode
=
MODES
.
verified
,
status
=
CertificateStatuses
.
downloadable
,
)
call_command
(
'backpopulate_program_credentials'
,
commit
=
True
)
...
...
@@ -211,12 +221,56 @@ class BackpopulateProgramCredentialsTests(ProgramsApiConfigMixin, TestCase):
GeneratedCertificateFactory
(
user
=
self
.
alice
,
course_id
=
self
.
course_id
,
status
=
CertificateStatuses
.
downloadable
,
)
GeneratedCertificateFactory
(
user
=
self
.
bob
,
course_id
=
self
.
course_id
,
mode
=
MODES
.
verified
,
status
=
CertificateStatuses
.
downloadable
,
)
call_command
(
'backpopulate_program_credentials'
,
commit
=
True
)
mock_task
.
assert_called_once_with
(
self
.
alice
.
username
)
def
test_handle_passing_status
(
self
,
mock_task
):
"""Verify that only certificates with a passing status are selected."""
data
=
[
factories
.
Program
(
organizations
=
[
factories
.
Organization
()],
course_codes
=
[
factories
.
CourseCode
(
run_modes
=
[
factories
.
RunMode
(
course_key
=
self
.
course_id
),
factories
.
RunMode
(
course_key
=
self
.
alternate_course_id
),
]),
]
),
]
self
.
_mock_programs_api
(
data
)
self
.
_link_oauth2_user
()
passing_status
=
CertificateStatuses
.
downloadable
failing_status
=
CertificateStatuses
.
notpassing
self
.
assertIn
(
passing_status
,
CertificateStatuses
.
PASSED_STATUSES
)
self
.
assertNotIn
(
failing_status
,
CertificateStatuses
.
PASSED_STATUSES
)
GeneratedCertificateFactory
(
user
=
self
.
alice
,
course_id
=
self
.
course_id
,
mode
=
MODES
.
verified
,
status
=
passing_status
,
)
# The alternate course is used here to verify that the status and run_mode
# queries are being ANDed together correctly.
GeneratedCertificateFactory
(
user
=
self
.
bob
,
course_id
=
self
.
alternate_course_id
,
mode
=
MODES
.
verified
,
status
=
failing_status
,
)
call_command
(
'backpopulate_program_credentials'
,
commit
=
True
)
...
...
@@ -241,6 +295,7 @@ class BackpopulateProgramCredentialsTests(ProgramsApiConfigMixin, TestCase):
user
=
self
.
alice
,
course_id
=
self
.
course_id
,
mode
=
MODES
.
verified
,
status
=
CertificateStatuses
.
downloadable
,
)
with
self
.
assertRaises
(
CommandError
):
...
...
@@ -275,12 +330,14 @@ class BackpopulateProgramCredentialsTests(ProgramsApiConfigMixin, TestCase):
user
=
self
.
alice
,
course_id
=
self
.
course_id
,
mode
=
MODES
.
verified
,
status
=
CertificateStatuses
.
downloadable
,
)
GeneratedCertificateFactory
(
user
=
self
.
bob
,
course_id
=
self
.
course_id
,
mode
=
MODES
.
verified
,
status
=
CertificateStatuses
.
downloadable
,
)
call_command
(
'backpopulate_program_credentials'
,
commit
=
True
)
...
...
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