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
03db7a7f
Commit
03db7a7f
authored
Jun 16, 2015
by
Ahsan Ulhaq
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #8228 from edx/ahsan/ECOM-1602-update-ICRV-requirments-status-new
update the ICRV requirments status
parents
905512b6
7d117683
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
214 additions
and
5 deletions
+214
-5
lms/djangoapps/verify_student/views.py
+32
-2
openedx/core/djangoapps/credit/api.py
+64
-1
openedx/core/djangoapps/credit/models.py
+43
-1
openedx/core/djangoapps/credit/tests/test_api.py
+75
-1
No files found.
lms/djangoapps/verify_student/views.py
View file @
03db7a7f
...
...
@@ -42,6 +42,7 @@ from microsite_configuration import microsite
from
openedx.core.djangoapps.user_api.accounts
import
NAME_MIN_LENGTH
from
openedx.core.djangoapps.user_api.accounts.api
import
get_account_settings
,
update_account_settings
from
openedx.core.djangoapps.user_api.errors
import
UserNotFound
,
AccountValidationError
from
openedx.core.djangoapps.credit.api
import
get_credit_requirement
,
set_credit_requirement_status
from
student.models
import
CourseEnrollment
from
shoppingcart.models
import
Order
,
CertificateItem
from
shoppingcart.processors
import
(
...
...
@@ -921,6 +922,32 @@ def _send_email(user_id, subject, message):
user
.
email_user
(
subject
,
message
,
from_address
)
def
_set_user_requirement_status
(
attempt
,
namespace
,
status
,
reason
=
None
):
"""Sets the status of a credit requirement for the user,
based on a verification checkpoint.
"""
checkpoint
=
None
try
:
checkpoint
=
VerificationCheckpoint
.
objects
.
get
(
photo_verification
=
attempt
)
except
VerificationCheckpoint
.
DoesNotExist
:
log
.
error
(
"Unable to find checkpoint for user with id
%
d"
,
attempt
.
user
.
id
)
if
checkpoint
is
not
None
:
course_key
=
checkpoint
.
course_id
credit_requirement
=
get_credit_requirement
(
course_key
,
namespace
,
checkpoint
.
checkpoint_location
)
if
credit_requirement
is
not
None
:
try
:
set_credit_requirement_status
(
attempt
.
user
.
username
,
credit_requirement
,
status
,
reason
)
except
Exception
:
# pylint: disable=broad-except
# Catch exception if unable to add credit requirement
# status for user
log
.
error
(
"Unable to add Credit requirement status for user with id
%
d"
,
attempt
.
user
.
id
)
@require_POST
@csrf_exempt
# SS does its own message signing, and their API won't have a cookie value
def
results_callback
(
request
):
...
...
@@ -974,15 +1001,19 @@ def results_callback(request):
except
SoftwareSecurePhotoVerification
.
DoesNotExist
:
log
.
error
(
"Software Secure posted back for receipt_id
%
s, but not found"
,
receipt_id
)
return
HttpResponseBadRequest
(
"edX ID {} not found"
.
format
(
receipt_id
))
if
result
==
"PASS"
:
log
.
debug
(
"Approving verification for
%
s"
,
receipt_id
)
attempt
.
approve
()
status
=
"approved"
_set_user_requirement_status
(
attempt
,
'reverification'
,
'satisfied'
)
elif
result
==
"FAIL"
:
log
.
debug
(
"Denying verification for
%
s"
,
receipt_id
)
attempt
.
deny
(
json
.
dumps
(
reason
),
error_code
=
error_code
)
status
=
"denied"
_set_user_requirement_status
(
attempt
,
'reverification'
,
'failed'
,
json
.
dumps
(
reason
)
)
elif
result
==
"SYSTEM FAIL"
:
log
.
debug
(
"System failure for
%
s -- resetting to must_retry"
,
receipt_id
)
attempt
.
system_error
(
json
.
dumps
(
reason
),
error_code
=
error_code
)
...
...
@@ -993,7 +1024,6 @@ def results_callback(request):
return
HttpResponseBadRequest
(
"Result {} not understood. Known results: PASS, FAIL, SYSTEM FAIL"
.
format
(
result
)
)
incourse_reverify_enabled
=
InCourseReverificationConfiguration
.
current
()
.
enabled
if
incourse_reverify_enabled
:
checkpoints
=
VerificationCheckpoint
.
objects
.
filter
(
photo_verification
=
attempt
)
.
all
()
...
...
openedx/core/djangoapps/credit/api.py
View file @
03db7a7f
...
...
@@ -29,7 +29,6 @@ from .models import (
)
from
.signature
import
signature
,
get_shared_secret_key
log
=
logging
.
getLogger
(
__name__
)
...
...
@@ -488,6 +487,70 @@ def is_credit_course(course_key):
return
CreditCourse
.
is_credit_course
(
course_key
)
def
get_credit_requirement
(
course_key
,
namespace
,
name
):
"""Returns the requirement of a given course, namespace and name.
Args:
course_key(CourseKey): The identifier for course
namespace(str): Namespace of requirement
name(str): Name of the requirement
Returns: dict
Example:
>>> get_credit_requirement_status(
"course-v1-edX-DemoX-1T2015", "proctored_exam", "i4x://edX/DemoX/proctoring-block/final_uuid"
)
{
"course_key": "course-v1-edX-DemoX-1T2015"
"namespace": "reverification",
"name": "i4x://edX/DemoX/edx-reverification-block/assessment_uuid",
"display_name": "reverification"
"criteria": {},
}
"""
requirement
=
CreditRequirement
.
get_course_requirement
(
course_key
,
namespace
,
name
)
return
{
"course_key"
:
requirement
.
course
.
course_key
,
"namespace"
:
requirement
.
namespace
,
"name"
:
requirement
.
name
,
"display_name"
:
requirement
.
display_name
,
"criteria"
:
requirement
.
criteria
}
if
requirement
else
None
def
set_credit_requirement_status
(
username
,
requirement
,
status
=
"satisfied"
,
reason
=
None
):
"""Update Credit Requirement Status for given username and requirement
if exists else add new.
Args:
username(str): Username of the user
requirement(dict): requirement dict
status(str): Status of the requirement
reason(dict): Reason of the status
Example:
>>> set_credit_requirement_status(
"staff",
{
"course_key": "course-v1-edX-DemoX-1T2015"
"namespace": "reverification",
"name": "i4x://edX/DemoX/edx-reverification-block/assessment_uuid",
},
"satisfied",
{}
)
"""
credit_requirement
=
CreditRequirement
.
get_course_requirement
(
requirement
[
'course_key'
],
requirement
[
'namespace'
],
requirement
[
'name'
]
)
CreditRequirementStatus
.
add_or_update_requirement_status
(
username
,
credit_requirement
,
status
,
reason
)
def
_get_requirements_to_disable
(
old_requirements
,
new_requirements
):
"""
Get the ids of 'CreditRequirement' entries to be disabled that are
...
...
openedx/core/djangoapps/credit/models.py
View file @
03db7a7f
...
...
@@ -9,6 +9,7 @@ successful completion of a course on EdX
import
logging
from
django.db
import
models
from
django.db
import
transaction
from
django.core.validators
import
RegexValidator
from
simple_history.models
import
HistoricalRecords
...
...
@@ -208,6 +209,26 @@ class CreditRequirement(TimeStampedModel):
"""
cls
.
objects
.
filter
(
id__in
=
requirement_ids
)
.
update
(
active
=
False
)
@classmethod
def
get_course_requirement
(
cls
,
course_key
,
namespace
,
name
):
"""Get credit requirement of a given course.
Args:
course_key(CourseKey): The identifier for a course
namespace(str): Namespace of credit course requirements
name(str): Name of credit course requirement
Returns:
CreditRequirement object if exists
"""
try
:
return
cls
.
objects
.
get
(
course__course_key
=
course_key
,
active
=
True
,
namespace
=
namespace
,
name
=
name
)
except
cls
.
DoesNotExist
:
return
None
class
CreditRequirementStatus
(
TimeStampedModel
):
"""
...
...
@@ -257,13 +278,34 @@ class CreditRequirementStatus(TimeStampedModel):
"""
return
cls
.
objects
.
filter
(
requirement__in
=
requirements
,
username
=
username
)
@classmethod
@transaction.commit_on_success
def
add_or_update_requirement_status
(
cls
,
username
,
requirement
,
status
=
"satisfied"
,
reason
=
None
):
"""Add credit requirement status for given username.
Args:
username(str): Username of the user
requirement(CreditRequirement): 'CreditRequirement' object
status(str): Status of the requirement
reason(dict): Reason of the status
"""
requirement_status
,
created
=
cls
.
objects
.
get_or_create
(
username
=
username
,
requirement
=
requirement
,
defaults
=
{
"reason"
:
reason
,
"status"
:
status
}
)
if
not
created
:
requirement_status
.
status
=
status
requirement_status
.
reason
=
reason
if
reason
else
{}
requirement_status
.
save
()
class
CreditEligibility
(
TimeStampedModel
):
"""
A record of a user's eligibility for credit from a specific credit
provider for a specific course.
"""
username
=
models
.
CharField
(
max_length
=
255
,
db_index
=
True
)
course
=
models
.
ForeignKey
(
CreditCourse
,
related_name
=
"eligibilities"
)
provider
=
models
.
ForeignKey
(
CreditProvider
,
related_name
=
"eligibilities"
)
...
...
openedx/core/djangoapps/credit/tests/test_api.py
View file @
03db7a7f
...
...
@@ -27,7 +27,12 @@ from openedx.core.djangoapps.credit.models import (
CreditProvider
,
CreditRequirement
,
CreditRequirementStatus
,
CreditEligibility
,
CreditEligibility
)
from
openedx.core.djangoapps.credit.api
import
(
set_credit_requirements
,
set_credit_requirement_status
,
get_credit_requirement
)
...
...
@@ -215,6 +220,74 @@ class CreditRequirementApiTests(CreditApiTestBase):
is_eligible
=
api
.
is_user_eligible_for_credit
(
'abc'
,
credit_course
.
course_key
)
self
.
assertFalse
(
is_eligible
)
def
test_get_credit_requirement
(
self
):
self
.
add_credit_course
()
requirements
=
[
{
"namespace"
:
"grade"
,
"name"
:
"grade"
,
"display_name"
:
"Grade"
,
"criteria"
:
{
"min_grade"
:
0.8
}
}
]
requirement
=
get_credit_requirement
(
self
.
course_key
,
"grade"
,
"grade"
)
self
.
assertIsNone
(
requirement
)
expected_requirement
=
{
"course_key"
:
self
.
course_key
,
"namespace"
:
"grade"
,
"name"
:
"grade"
,
"display_name"
:
"Grade"
,
"criteria"
:
{
"min_grade"
:
0.8
}
}
set_credit_requirements
(
self
.
course_key
,
requirements
)
requirement
=
get_credit_requirement
(
self
.
course_key
,
"grade"
,
"grade"
)
self
.
assertIsNotNone
(
requirement
)
self
.
assertEqual
(
requirement
,
expected_requirement
)
def
test_set_credit_requirement_status
(
self
):
self
.
add_credit_course
()
requirements
=
[
{
"namespace"
:
"grade"
,
"name"
:
"grade"
,
"display_name"
:
"Grade"
,
"criteria"
:
{
"min_grade"
:
0.8
}
},
{
"namespace"
:
"reverification"
,
"name"
:
"i4x://edX/DemoX/edx-reverification-block/assessment_uuid"
,
"display_name"
:
"Assessment 1"
,
"criteria"
:
{}
}
]
set_credit_requirements
(
self
.
course_key
,
requirements
)
course_requirements
=
CreditRequirement
.
get_course_requirements
(
self
.
course_key
)
self
.
assertEqual
(
len
(
course_requirements
),
2
)
requirement
=
get_credit_requirement
(
self
.
course_key
,
"grade"
,
"grade"
)
set_credit_requirement_status
(
"staff"
,
requirement
,
'satisfied'
,
{})
course_requirement
=
CreditRequirement
.
get_course_requirement
(
requirement
[
'course_key'
],
requirement
[
'namespace'
],
requirement
[
'name'
]
)
status
=
CreditRequirementStatus
.
objects
.
get
(
username
=
"staff"
,
requirement
=
course_requirement
)
self
.
assertEqual
(
status
.
requirement
.
namespace
,
requirement
[
'namespace'
])
self
.
assertEqual
(
status
.
status
,
"satisfied"
)
set_credit_requirement_status
(
"staff"
,
requirement
,
'failed'
,
{
'failure_reason'
:
"requirements not satisfied"
}
)
status
=
CreditRequirementStatus
.
objects
.
get
(
username
=
"staff"
,
requirement
=
course_requirement
)
self
.
assertEqual
(
status
.
requirement
.
namespace
,
requirement
[
'namespace'
])
self
.
assertEqual
(
status
.
status
,
"failed"
)
@ddt.ddt
class
CreditProviderIntegrationApiTests
(
CreditApiTestBase
):
...
...
@@ -425,6 +498,7 @@ class CreditProviderIntegrationApiTests(CreditApiTestBase):
self
.
assertEqual
(
requests
,
[])
def
_configure_credit
(
self
):
"""
Configure a credit course and its requirements.
...
...
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