Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 3 additions & 8 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,9 @@ workflows:
only: /v?[0-9]+(\.[0-9]+)*/
matrix:
parameters:
python_version: ["3.5", "3.8"]
debian_version: ["stretch", "buster"]
exclude:
- python_version: "3.8"
debian_version: "stretch"
- python_version: "3.5"
debian_version: "buster"
python_version: ["3.8"]
debian_version: ["buster"]

- pypi:
requires:
- test
Expand All @@ -39,7 +35,6 @@ jobs:
type: string
debian_version:
type: string
default: stretch
docker:
# specify the version you desire here
# use `-browsers` prefix for selenium tests, e.g. `3.6.1-browsers`
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ Change Log
Unreleased
----------
* **BREAKING CHANGE**: add support for lilac and therefore changed backends defaults.
* **BREAKING CHANGE**: add support for openedx-events. Only works for Lilac with PRs backport 28266 and 18640
and >= Maple.

[1.0.0] - 2021-08-17
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand Down
19 changes: 13 additions & 6 deletions eox_hooks/actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@
from opaque_keys.edx.keys import CourseKey

from eox_hooks.edxapp_wrapper.courses import get_item_not_found_exception, get_load_single_xblock
from eox_hooks.edxapp_wrapper.models import get_certificate_model
from eox_hooks.serializers import CertificateSerializer, CourseSerializer, UserSerializer
from eox_hooks.tasks import create_enrollments_for_program
from eox_hooks.utils import _get_course, flatten_dict, get_trigger_settings

COURSE_PASSING_GRADE = 1
ItemNotFoundError = get_item_not_found_exception()
load_single_xblock = get_load_single_xblock()
COURSE_PASSING_GRADE = 1
GeneratedCertificate = get_certificate_model()
log = logging.getLogger(__name__)


Expand Down Expand Up @@ -61,6 +63,9 @@ def post_to_webhook_url(**kwargs):

if trigger_settings.get("send_certificate_data", False):
certificate = kwargs.get("certificate", {})
certificate = GeneratedCertificate.objects.get(
user__id=certificate.user.id, course_id=certificate.course.course_key,
)
extended_data = get_extended_certificate_data(certificate)
data.update(extended_data)

Expand Down Expand Up @@ -144,8 +149,8 @@ def trigger_enrollments_creation(**kwargs):
course_key (str): course identifier.
user (User): user that just enrolled in the course.
"""
course = _get_course(kwargs.get("course_key"))
user = kwargs.get("user")
enrollment = kwargs.get("enrollment")
course = _get_course(enrollment.course.course_key)

followup_enrollments = getattr(course, "other_course_settings", {}).get(
"EDNX_TRIGGER_FOLLOWUP_ENROLLMENTS"
Expand All @@ -154,7 +159,9 @@ def trigger_enrollments_creation(**kwargs):
if not followup_enrollments:
return

create_enrollments_for_program.delay(user.username, followup_enrollments)
create_enrollments_for_program.delay(
enrollment.user.pii.username, followup_enrollments,
)


def trigger_grades_assignment(**kwargs):
Expand Down Expand Up @@ -189,10 +196,10 @@ def trigger_grades_assignment(**kwargs):
User `U` obtains 90% of the grade in X, then 1 is assigned to the component x.

Keyword args:
certificate (GeneratedCertificate): certificate generated by the course.
certificate (CertificateData): certificate data generated by the course.
"""
certificate = kwargs.get("certificate")
course = _get_course(certificate.course_id)
course = _get_course(certificate.course.course_key)

grades_assignment_settings = getattr(course, "other_course_settings", {}).get(
"EDNX_TRIGGER_GRADES_ASSIGNMENT", {}
Expand Down
39 changes: 32 additions & 7 deletions eox_hooks/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,23 +67,48 @@ class EoxHooksConfig(AppConfig):
'receivers': [
{
'receiver_func_name': 'hooks_handler',
'signal_path': get_signal_module('pre_enrollment'),
'dispatch_uid': 'eox-hooks:pre_enrollment',
'signal_path': 'openedx_events.learning.signals.STUDENT_REGISTRATION_COMPLETED',
'dispatch_uid': 'eox-hooks:post_register',
},
{
'receiver_func_name': 'hooks_handler',
'signal_path': 'openedx_events.learning.signals.SESSION_LOGIN_COMPLETED',
'dispatch_uid': 'eox-hooks:post_session_login',
},
{
'receiver_func_name': 'hooks_handler',
'signal_path': 'openedx_events.learning.signals.COURSE_ENROLLMENT_CREATED',
'dispatch_uid': 'eox-hooks:post_enrollment',
},
{
'receiver_func_name': 'hooks_handler',
'signal_path': get_signal_module('post_certificate_creation'),
'signal_path': 'openedx_events.learning.signals.COURSE_ENROLLMENT_CHANGED',
'dispatch_uid': 'eox-hooks:post_enrollment_change',
},
{
'receiver_func_name': 'hooks_handler',
'signal_path': 'openedx_events.learning.signals.COURSE_UNENROLLMENT_COMPLETED',
'dispatch_uid': 'eox-hooks:post_unenrollment',
},
{
'receiver_func_name': 'hooks_handler',
'signal_path': 'openedx_events.learning.signals.CERTIFICATE_CREATED',
'dispatch_uid': 'eox-hooks:post_certificate_creation',
},
{
'receiver_func_name': 'hooks_handler',
'signal_path': get_signal_module('post_register'),
'dispatch_uid': 'eox-hooks:post_register',
'signal_path': 'openedx_events.learning.signals.CERTIFICATE_CHANGED',
'dispatch_uid': 'eox-hooks:post_certificate_change',
},
{
'receiver_func_name': 'hooks_handler',
'signal_path': get_signal_module('post_enrollment'),
'dispatch_uid': 'eox-hooks:post_enrollment',
'signal_path': 'openedx_events.learning.signals.CERTIFICATE_REVOKED',
'dispatch_uid': 'eox-hooks:post_certificate_revoke',
},
{
'receiver_func_name': 'hooks_handler',
'signal_path': 'openedx_events.learning.signals.COHORT_MEMBERSHIP_CHANGED',
'dispatch_uid': 'eox-hooks:post_cohort_change',
},
],
}
Expand Down
4 changes: 2 additions & 2 deletions eox_hooks/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

from eox_hooks.edxapp_wrapper.models import get_certificate_model, get_user_profile_model

Certificate = get_certificate_model()
GeneratedCertificate = get_certificate_model()
UserProfile = get_user_profile_model()


Expand All @@ -20,7 +20,7 @@ class CertificateSerializer(serializers.ModelSerializer):

class Meta:
"""Meta class."""
model = Certificate
model = GeneratedCertificate
fields = '__all__'


Expand Down
69 changes: 53 additions & 16 deletions eox_hooks/tests/test_actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@
TestPostToWebhookUrl.
TriggerEnrollmentsTest.
"""
import datetime
from unittest.mock import MagicMock, patch

from django.contrib.auth import get_user_model
from django.test import TestCase
from opaque_keys.edx.keys import CourseKey
from openedx_events.learning.data import CertificateData, CourseData, CourseEnrollmentData, UserData, UserPersonalData

from eox_hooks.actions import get_request_fields, trigger_enrollments_creation, trigger_grades_assignment

Expand All @@ -18,11 +19,14 @@ class TestPostToWebhookUrl(TestCase):

def setUp(self):
"""Set up class for post_to_webhook_url testing."""
self.user = get_user_model().objects.create(
id='1',
first_name='Tania',
last_name='Chernova',
username='taniacher',
self.user = UserData(
pii=UserPersonalData(
username="taniacher",
email="test@example.com",
name="Tania Chernova",
),
id=1,
is_active=True,
)
self.kwargs = {
'user': self.user,
Expand All @@ -35,13 +39,11 @@ def test_get_request_fields(self):
This should return a dictionary with all the fields found.
"""
fields = {
"first_name": "user.first_name",
"last_name": "user.last_name",
"username": "user.username",
"name": "user.pii.name",
"username": "user.pii.username",
}
expected_data = {
"first_name": "Tania",
"last_name": "Chernova",
"name": "Tania Chernova",
"username": "taniacher",
}

Expand All @@ -60,7 +62,7 @@ def test_get_request_fields_missing_fields(self):
fields = {
"favorite_color": "user.favorite_color",
"favorite_food": "user.favorite_food",
"username": "user.username",
"username": "user.pii.username",
"course": "course.id",
}
extra_fields = {
Expand Down Expand Up @@ -91,9 +93,26 @@ def setUp(self):
"""
Setup common conditions for test cases.
"""
self.user = MagicMock(username="test")
enrollment = CourseEnrollmentData(
user=UserData(
pii=UserPersonalData(
username="test",
email="test@example.com",
name="Test Example",
),
id=39,
is_active=True,
),
course=CourseData(
course_key=CourseKey.from_string("course-v1:edX+DemoX+Demo_Course"),
display_name="Demonstration Course",
),
mode="audit",
is_active=True,
creation_date=datetime.datetime.now(),
)
self.kwargs = {
"user": self.user,
"enrollment": enrollment,
}

@create_enrollments_for_program
Expand Down Expand Up @@ -177,8 +196,26 @@ def setUp(self):
"""
Setup common conditions for test cases.
"""
user = MagicMock(id=1, username="test")
self.certificate = MagicMock(user=user, grade=0.5)
self.certificate = CertificateData(
user=UserData(
pii=UserPersonalData(
username="test",
email="test@example.com",
name="Test Example",
),
id=39,
is_active=True,
),
course=CourseData(
course_key=CourseKey.from_string("course-v1:edX+DemoX+Demo_Course"),
display_name="Demonstration Course",
),
mode="audit",
current_status="notpassing",
grade=0.5,
download_url="https://downdloadurl.com",
name="Certs",
)
self.kwargs = {
"certificate": self.certificate,
}
Expand Down
Loading