Merge pull request #30686 from openedx/ammar/send-followup-segment-events-for-passed-learners
feat: Schedule a follow up segment event for first time passed learners
This commit is contained in:
@@ -4,6 +4,7 @@ Emits course grade events.
|
||||
from logging import getLogger
|
||||
|
||||
from crum import get_current_user
|
||||
from django.conf import settings
|
||||
from eventtracking import tracker
|
||||
|
||||
from common.djangoapps.course_modes.models import CourseMode
|
||||
@@ -15,6 +16,7 @@ from common.djangoapps.track.event_transaction_utils import (
|
||||
get_event_transaction_type,
|
||||
set_event_transaction_type
|
||||
)
|
||||
from lms.djangoapps.grades.signals.signals import SCHEDULE_FOLLOW_UP_SEGMENT_EVENT_FOR_COURSE_PASSED_FIRST_TIME
|
||||
from openedx.core.djangoapps.content.course_overviews.models import CourseOverview
|
||||
from openedx.features.enterprise_support.context import get_enterprise_event_context
|
||||
|
||||
@@ -30,7 +32,6 @@ SUBSECTION_GRADE_CALCULATED = 'edx.grades.subsection.grade_calculated'
|
||||
COURSE_GRADE_PASSED_FIRST_TIME_EVENT_TYPE = 'edx.course.grade.passed.first_time'
|
||||
COURSE_GRADE_NOW_PASSED_EVENT_TYPE = 'edx.course.grade.now_passed'
|
||||
COURSE_GRADE_NOW_FAILED_EVENT_TYPE = 'edx.course.grade.now_failed'
|
||||
LEARNER_PASSED_COURSE_FIRST_TIME = 'edx.course.learner.passed.first_time'
|
||||
|
||||
|
||||
def grade_updated(**kwargs):
|
||||
@@ -215,7 +216,7 @@ def fire_segment_event_on_course_grade_passed_first_time(user_id, course_locator
|
||||
|
||||
* Event should be only fired for learners enrolled in paid enrollment modes.
|
||||
"""
|
||||
event_name = LEARNER_PASSED_COURSE_FIRST_TIME
|
||||
event_name = 'edx.course.learner.passed.first_time'
|
||||
courserun_key = str(course_locator)
|
||||
courserun_org = course_locator.org
|
||||
paid_enrollment_modes = (
|
||||
@@ -247,4 +248,13 @@ def fire_segment_event_on_course_grade_passed_first_time(user_id, course_locator
|
||||
}
|
||||
segment.track(user_id, event_name, event_properties)
|
||||
|
||||
if getattr(settings, 'OUTCOME_SURVEYS_FOLLOW_UP_SIGNAL_ENABLED', False):
|
||||
# fire signal so that a follow up event can be scheduled in outcome_surveys app
|
||||
SCHEDULE_FOLLOW_UP_SEGMENT_EVENT_FOR_COURSE_PASSED_FIRST_TIME.send(
|
||||
sender=None,
|
||||
user_id=user_id,
|
||||
course_id=course_locator,
|
||||
event_properties=event_properties
|
||||
)
|
||||
|
||||
log.info("Segment event fired for passed learners. Event: [{}], Data: [{}]".format(event_name, event_properties))
|
||||
|
||||
@@ -37,7 +37,6 @@ class TestSendSegmentEventsForFailedLearnersCommand(SharedModuleStoreTestCase):
|
||||
# we will create enrollments for paid modes plus `audit` mode
|
||||
enrollment_modes = PAID_ENROLLMENT_MODES + ['audit']
|
||||
|
||||
# import pdb ; pdb.set_trace()
|
||||
cls.course_end = timezone.now() - timedelta(days=31)
|
||||
cls.course_overviews = CourseOverviewFactory.create_batch(4, end=cls.course_end)
|
||||
|
||||
|
||||
@@ -112,3 +112,11 @@ SUBSECTION_OVERRIDE_CHANGED = Signal()
|
||||
# ]
|
||||
COURSE_GRADE_PASSED_FIRST_TIME = Signal()
|
||||
COURSE_GRADE_PASSED_UPDATE_IN_LEARNER_PATHWAY = Signal()
|
||||
|
||||
# This Signal indicates that a segment event has fired for user who has passed a course for the first time
|
||||
# providing_args=[
|
||||
# 'user_id', # User object id
|
||||
# 'course_id', # Course object id
|
||||
# 'event_properties', # Segment event properties that will be needed for follow up event
|
||||
# ]
|
||||
SCHEDULE_FOLLOW_UP_SEGMENT_EVENT_FOR_COURSE_PASSED_FIRST_TIME = Signal()
|
||||
|
||||
@@ -11,15 +11,16 @@ import ddt
|
||||
import pytest
|
||||
import pytz
|
||||
from django.test import TestCase
|
||||
from django.test.utils import override_settings
|
||||
from opaque_keys.edx.locator import CourseLocator
|
||||
from submissions.models import score_reset, score_set
|
||||
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
|
||||
|
||||
from common.djangoapps.student.tests.factories import CourseEnrollmentFactory, UserFactory
|
||||
from common.djangoapps.track.event_transaction_utils import get_event_transaction_id, get_event_transaction_type
|
||||
from common.djangoapps.util.date_utils import to_timestamp
|
||||
from lms.djangoapps.grades.models import PersistentCourseGrade
|
||||
from openedx.core.djangoapps.content.course_overviews.tests.factories import CourseOverviewFactory
|
||||
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
|
||||
|
||||
from ..constants import ScoreDatabaseTableEnum
|
||||
from ..signals.handlers import (
|
||||
@@ -388,8 +389,10 @@ class CourseEventsSignalsTest(ModuleStoreTestCase):
|
||||
}
|
||||
)
|
||||
|
||||
@override_settings(OUTCOME_SURVEYS_FOLLOW_UP_SIGNAL_ENABLED=True)
|
||||
@patch('lms.djangoapps.grades.events.segment.track')
|
||||
def test_segment_event_on_course_grade_passed_first_time(self, segment_track_mock):
|
||||
@patch('lms.djangoapps.grades.signals.signals.SCHEDULE_FOLLOW_UP_SEGMENT_EVENT_FOR_COURSE_PASSED_FIRST_TIME.send')
|
||||
def test_segment_event_on_course_grade_passed_first_time(self, signal_mock, segment_track_mock):
|
||||
course = CourseOverviewFactory()
|
||||
enrollment = CourseEnrollmentFactory(
|
||||
is_active=True,
|
||||
@@ -425,3 +428,15 @@ class CourseEventsSignalsTest(ModuleStoreTestCase):
|
||||
'COURSE_ORG_NAME': course.org,
|
||||
}
|
||||
)
|
||||
|
||||
assert signal_mock.call_count == 1
|
||||
signal_mock.assert_called_with(
|
||||
sender=None,
|
||||
user_id=self.user.id,
|
||||
course_id=course.id,
|
||||
event_properties={
|
||||
'LMS_ENROLLMENT_ID': enrollment.id,
|
||||
'COURSE_TITLE': course.display_name,
|
||||
'COURSE_ORG_NAME': course.org,
|
||||
}
|
||||
)
|
||||
|
||||
@@ -5179,3 +5179,6 @@ MFE_CONFIG = {}
|
||||
# .. setting_description: The MFE Config API response will be cached during the
|
||||
# specified time
|
||||
MFE_CONFIG_API_CACHE_TIMEOUT = 60 * 5
|
||||
|
||||
######################## Settings for Outcome Surveys plugin ########################
|
||||
OUTCOME_SURVEYS_FOLLOW_UP_SIGNAL_ENABLED = False
|
||||
|
||||
@@ -126,6 +126,7 @@ openedx-calc # Library supporting mathematical calculatio
|
||||
openedx-events # Open edX Events from Hooks Extension Framework (OEP-50)
|
||||
openedx-filters # Open edX Filters from Hooks Extension Framework (OEP-50)
|
||||
ora2>=4.4.0
|
||||
outcome-surveys # edx-platform plugin to send and track segment events needed for surveys
|
||||
path
|
||||
piexif # Exif image metadata manipulation, used in the profile_images app
|
||||
Pillow # Image manipulation library; used for course assets, profile images, invoice PDFs, etc.
|
||||
|
||||
@@ -747,6 +747,8 @@ ora2==4.4.4
|
||||
# via -r requirements/edx/base.in
|
||||
oscrypto==1.3.0
|
||||
# via snowflake-connector-python
|
||||
outcome-surveys==1.1.0
|
||||
# via -r requirements/edx/base.in
|
||||
packaging==21.3
|
||||
# via
|
||||
# drf-yasg
|
||||
|
||||
@@ -974,6 +974,8 @@ oscrypto==1.3.0
|
||||
# via
|
||||
# -r requirements/edx/testing.txt
|
||||
# snowflake-connector-python
|
||||
outcome-surveys==1.1.0
|
||||
# via -r requirements/edx/testing.txt
|
||||
packaging==21.3
|
||||
# via
|
||||
# -r requirements/edx/testing.txt
|
||||
|
||||
@@ -925,6 +925,8 @@ oscrypto==1.3.0
|
||||
# via
|
||||
# -r requirements/edx/base.txt
|
||||
# snowflake-connector-python
|
||||
outcome-surveys==1.1.0
|
||||
# via -r requirements/edx/base.txt
|
||||
packaging==21.3
|
||||
# via
|
||||
# -r requirements/edx/base.txt
|
||||
|
||||
Reference in New Issue
Block a user