Skip to content
Snippets Groups Projects
Unverified Commit 3b23a9b2 authored by Hammad Ahmad Waqas's avatar Hammad Ahmad Waqas Committed by GitHub
Browse files

Merge pull request #25003 from edx/hammad/ENT-3337

catch signal UNENROLL_DONE signal and call /api/v2/enterprise/coupons…
parents eada6326 30edb7ef
No related branches found
No related tags found
No related merge requests found
...@@ -6,6 +6,7 @@ This module contains signals related to enterprise. ...@@ -6,6 +6,7 @@ This module contains signals related to enterprise.
import logging import logging
import six import six
from django.conf import settings
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.db.models.signals import post_save, pre_save from django.db.models.signals import post_save, pre_save
from django.dispatch import receiver from django.dispatch import receiver
...@@ -13,10 +14,12 @@ from enterprise.models import EnterpriseCourseEnrollment, EnterpriseCustomer, En ...@@ -13,10 +14,12 @@ from enterprise.models import EnterpriseCourseEnrollment, EnterpriseCustomer, En
from integrated_channels.integrated_channel.tasks import transmit_single_learner_data from integrated_channels.integrated_channel.tasks import transmit_single_learner_data
from email_marketing.tasks import update_user from email_marketing.tasks import update_user
from openedx.core.djangoapps.commerce.utils import ecommerce_api_client
from openedx.core.djangoapps.signals.signals import COURSE_GRADE_NOW_PASSED from openedx.core.djangoapps.signals.signals import COURSE_GRADE_NOW_PASSED
from openedx.features.enterprise_support.api import enterprise_enabled from openedx.features.enterprise_support.api import enterprise_enabled
from openedx.features.enterprise_support.tasks import clear_enterprise_customer_data_consent_share_cache from openedx.features.enterprise_support.tasks import clear_enterprise_customer_data_consent_share_cache
from openedx.features.enterprise_support.utils import clear_data_consent_share_cache, is_enterprise_learner from openedx.features.enterprise_support.utils import clear_data_consent_share_cache, is_enterprise_learner
from student.signals import UNENROLL_DONE
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
...@@ -80,3 +83,30 @@ def handle_enterprise_learner_passing_grade(sender, user, course_id, **kwargs): ...@@ -80,3 +83,30 @@ def handle_enterprise_learner_passing_grade(sender, user, course_id, **kwargs):
} }
transmit_single_learner_data.apply_async(kwargs=kwargs) transmit_single_learner_data.apply_async(kwargs=kwargs)
@receiver(UNENROLL_DONE)
def refund_order_voucher(sender, course_enrollment=None, skip_refund=False, **kwargs): # pylint: disable=unused-argument
"""
Call the /api/v2/enterprise/coupons/create_refunded_voucher/ API to create new voucher and assign it to user.
"""
if skip_refund:
return
if not course_enrollment.refundable():
return
if not EnterpriseCourseEnrollment.objects.filter(
enterprise_customer_user__user_id=course_enrollment.user_id,
course_id=str(course_enrollment.course.id)
).exists():
return
service_user = User.objects.get(username=settings.ECOMMERCE_SERVICE_WORKER_USERNAME)
client = ecommerce_api_client(service_user)
order_number = course_enrollment.get_order_attribute_value('order_number')
if order_number:
client.enterprise.coupons.create_refunded_voucher.post(
{
"order": order_number
}
)
...@@ -2,25 +2,31 @@ ...@@ -2,25 +2,31 @@
import logging import logging
from datetime import timedelta
import ddt import ddt
from django.test import TestCase
from django.test.utils import override_settings from django.test.utils import override_settings
from mock import patch from django.utils.timezone import now
from edx_django_utils.cache import TieredCache from edx_django_utils.cache import TieredCache
from mock import patch
from opaque_keys.edx.keys import CourseKey from opaque_keys.edx.keys import CourseKey
from course_modes.tests.factories import CourseModeFactory
from lms.djangoapps.certificates.signals import listen_for_passing_grade from lms.djangoapps.certificates.signals import listen_for_passing_grade
from student.tests.factories import UserFactory from openedx.core.djangoapps.commerce.utils import ECOMMERCE_DATE_FORMAT
from openedx.core.djangoapps.credit.tests.test_api import TEST_ECOMMERCE_WORKER
from openedx.core.djangoapps.signals.signals import COURSE_GRADE_NOW_PASSED from openedx.core.djangoapps.signals.signals import COURSE_GRADE_NOW_PASSED
from openedx.features.enterprise_support.tests import FEATURES_WITH_ENTERPRISE_ENABLED
from openedx.features.enterprise_support.tests.factories import ( from openedx.features.enterprise_support.tests.factories import (
EnterpriseCourseEnrollmentFactory, EnterpriseCourseEnrollmentFactory,
EnterpriseCustomerFactory, EnterpriseCustomerFactory,
EnterpriseCustomerUserFactory EnterpriseCustomerUserFactory
) )
from openedx.features.enterprise_support.tests import FEATURES_WITH_ENTERPRISE_ENABLED
from openedx.features.enterprise_support.utils import get_data_consent_share_cache_key from openedx.features.enterprise_support.utils import get_data_consent_share_cache_key
from student.models import CourseEnrollmentAttribute
from student.tests.factories import CourseEnrollmentFactory, UserFactory
from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
...@@ -31,12 +37,14 @@ TEST_EMAIL = "test@edx.org" ...@@ -31,12 +37,14 @@ TEST_EMAIL = "test@edx.org"
@ddt.ddt @ddt.ddt
@override_settings(FEATURES=FEATURES_WITH_ENTERPRISE_ENABLED) @override_settings(FEATURES=FEATURES_WITH_ENTERPRISE_ENABLED)
class EnterpriseSupportSignals(TestCase): @override_settings(ECOMMERCE_SERVICE_WORKER_USERNAME=TEST_ECOMMERCE_WORKER)
class EnterpriseSupportSignals(SharedModuleStoreTestCase):
""" """
Tests for the enterprise support signals. Tests for the enterprise support signals.
""" """
def setUp(self): def setUp(self):
UserFactory.create(username=TEST_ECOMMERCE_WORKER)
self.user = UserFactory.create(username='test', email=TEST_EMAIL) self.user = UserFactory.create(username='test', email=TEST_EMAIL)
self.course_id = 'course-v1:edX+DemoX+Demo_Course' self.course_id = 'course-v1:edX+DemoX+Demo_Course'
self.enterprise_customer = EnterpriseCustomerFactory() self.enterprise_customer = EnterpriseCustomerFactory()
...@@ -108,6 +116,44 @@ class EnterpriseSupportSignals(TestCase): ...@@ -108,6 +116,44 @@ class EnterpriseSupportSignals(TestCase):
self.assertFalse(self._is_dsc_cache_found(self.user.id, self.course_id)) self.assertFalse(self._is_dsc_cache_found(self.user.id, self.course_id))
@ddt.data(
(True, True, 2, False), # test if skip_refund
(False, True, 20, False), # test refundable time passed
(False, False, 2, False), # test not enterprise enrollment
(False, True, 2, True), # success: no skip_refund, is enterprise enrollment and still in refundable window.
)
@ddt.unpack
def test_refund_order_voucher(self, skip_refund, enterprise_enrollment_exists, no_of_days_placed, api_called):
"""Test refund_order_voucher signal"""
# import pdb; pdb.set_trace()
date_placed = now() - timedelta(days=no_of_days_placed)
course = CourseFactory.create(display_name='test course', run="Testing_course", start=date_placed)
enrollment = CourseEnrollmentFactory(
course_id=course.id,
user=self.user,
mode="verified",
)
CourseModeFactory.create(course_id=course.id, mode_slug='verified')
CourseEnrollmentAttribute.objects.create(
enrollment=enrollment,
name='date_placed',
namespace='order',
value=date_placed.strftime(ECOMMERCE_DATE_FORMAT)
)
CourseEnrollmentAttribute.objects.create(
enrollment=enrollment,
name='order_number',
namespace='order',
value='EDX-000000001'
)
if enterprise_enrollment_exists:
self._create_enterprise_enrollment(self.user.id, course.id)
with patch('openedx.features.enterprise_support.signals.ecommerce_api_client') as mock_ecommerce_api_client:
enrollment.update_enrollment(is_active=False, skip_refund=skip_refund)
self.assertEqual(mock_ecommerce_api_client.called, api_called)
def test_handle_enterprise_learner_passing_grade(self): def test_handle_enterprise_learner_passing_grade(self):
""" """
Test to assert transmit_single_learner_data is called when COURSE_GRADE_NOW_PASSED signal is fired Test to assert transmit_single_learner_data is called when COURSE_GRADE_NOW_PASSED signal is fired
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment