diff --git a/eox_nelp/edxapp_wrapper/backends/student_m_v1.py b/eox_nelp/edxapp_wrapper/backends/student_m_v1.py index a08dfb03..57ee544e 100644 --- a/eox_nelp/edxapp_wrapper/backends/student_m_v1.py +++ b/eox_nelp/edxapp_wrapper/backends/student_m_v1.py @@ -2,6 +2,7 @@ This file contains all the necessary student dependencies from https://github.com/eduNEXT/edunext-platform/tree/ednx-release/mango.master/common/djangoapps/student """ +from common.djangoapps.student import models_api as student_api # pylint: disable=import-error from common.djangoapps.student.models import ( # pylint: disable=import-error CourseAccessRole, CourseEnrollment, @@ -34,3 +35,13 @@ def get_user_profile_model(): UserProfile Model. """ return UserProfile + + +def get_student_api(): + """Allow to get the student_api module from + https://github.com/eduNEXT/edunext-platform/blob/ednx-release/mango.master/common/djangoapps/student/models_api.py + + Returns: + models_api module. + """ + return student_api diff --git a/eox_nelp/edxapp_wrapper/student.py b/eox_nelp/edxapp_wrapper/student.py index 7b8a0ef2..df85da10 100644 --- a/eox_nelp/edxapp_wrapper/student.py +++ b/eox_nelp/edxapp_wrapper/student.py @@ -13,3 +13,4 @@ CourseEnrollment = backend.get_course_enrollment_model() CourseAccessRole = backend.get_course_access_role_model() UserProfile = backend.get_user_profile_model() +student_api = backend.get_student_api() diff --git a/eox_nelp/edxapp_wrapper/test_backends/student_m_v1.py b/eox_nelp/edxapp_wrapper/test_backends/student_m_v1.py index 526961cb..f45af36f 100644 --- a/eox_nelp/edxapp_wrapper/test_backends/student_m_v1.py +++ b/eox_nelp/edxapp_wrapper/test_backends/student_m_v1.py @@ -24,3 +24,11 @@ def get_user_profile_model(): Mock class. """ return Mock() + + +def get_student_api(): + """Return test Module. + Returns: + Mock class. + """ + return Mock() diff --git a/eox_nelp/signals/receivers.py b/eox_nelp/signals/receivers.py index 226fbfa6..8f3d64b4 100644 --- a/eox_nelp/signals/receivers.py +++ b/eox_nelp/signals/receivers.py @@ -13,7 +13,7 @@ from django.conf import settings from eox_nelp.notifications.tasks import create_course_notifications as create_course_notifications_task -from eox_nelp.signals.tasks import dispatch_futurex_progress +from eox_nelp.signals.tasks import create_external_certificate, dispatch_futurex_progress LOGGER = logging.getLogger(__name__) @@ -63,7 +63,7 @@ def create_course_notifications(course_key, **kwargs): # pylint: disable=unused create_course_notifications_task.delay(course_id=str(course_key)) -def certificate_publisher(certificate, **kwargs): # pylint: disable=unused-argument +def certificate_publisher(certificate, time, **kwargs): # pylint: disable=unused-argument """ Receiver that is connected to the CERTIFICATE_CREATED signal from 'openedx_events.learning.signals'. @@ -75,6 +75,7 @@ def certificate_publisher(certificate, **kwargs): # pylint: disable=unused-argu - CERTIFICATE_PUBLISHER_VALID_MODES: List of valid modes, default ['no-id-professional'] Args: + time: Date when the certificate was created. certificate: This an instance of the class defined in this link https://github.com/eduNEXT/openedx-events/blob/main/openedx_events/learning/data.py#L100 and will provide of the user certificate data. @@ -95,6 +96,7 @@ def certificate_publisher(certificate, **kwargs): # pylint: disable=unused-argu certificate.user.pii.username, certificate.course.course_key, ) + create_external_certificate(timestamp=time, certificate_data=certificate) else: LOGGER.info( "The %s certificate associated with the user <%s> and course <%s>" diff --git a/eox_nelp/signals/tasks.py b/eox_nelp/signals/tasks.py index 9d9af706..b328e5b5 100644 --- a/eox_nelp/signals/tasks.py +++ b/eox_nelp/signals/tasks.py @@ -10,16 +10,21 @@ from django.conf import settings from django.contrib.auth.models import User from django.db.models import Q +from django.utils import timezone from eox_core.edxapp_wrapper.courseware import get_courseware_courses from eox_core.edxapp_wrapper.enrollments import get_enrollment from eox_core.edxapp_wrapper.grades import get_course_grade_factory from opaque_keys.edx.keys import CourseKey +from eox_nelp.api_clients.certificates import ExternalCertificatesApiClient from eox_nelp.api_clients.futurex import FuturexApiClient +from eox_nelp.edxapp_wrapper.certificates import get_generated_certificate from eox_nelp.edxapp_wrapper.course_overviews import CourseOverview +from eox_nelp.edxapp_wrapper.student import student_api courses = get_courseware_courses() CourseGradeFactory = get_course_grade_factory() +GeneratedCertificate = get_generated_certificate() logger = logging.getLogger(__name__) @@ -148,3 +153,51 @@ def _generate_progress_enrollment_data(user, course_id, user_has_passing_grade): progress_enrollment_data, ) return progress_enrollment_data + + +@shared_task +def create_external_certificate(timestamp, certificate_data): + """This will create an external NELP certificate base on the input data + + Args: + timestamp: Date when the certificate was created. + certificate: This an instance of the class defined in this link + https://github.com/eduNEXT/openedx-events/blob/main/openedx_events/learning/data.py#L100 + and will provide of the user certificate data. + """ + external_certificate_data = _generate_external_certificate_data( + certificate_data=certificate_data + ) + api_client = ExternalCertificatesApiClient() + api_client.create_external_certificate(external_certificate_data) + + +def _generate_external_certificate_data(timestamp, certificate_data): + """ + + Args: + timestamp: Date when the certificate was created. + certificate: This an instance of the class defined in this link + https://github.com/eduNEXT/openedx-events/blob/main/openedx_events/learning/data.py#L100 + and will provide of the user certificate data. + """ + user = User.objects.get(id=certificate_data.user.id) + certificate = GeneratedCertificate.objects.get( + user=user, + course_id=certificate_data.course, + ) + extra_info = getattr(user, "extra_info", None) + + return { + "id": certificate.id, + "created_at": timestamp, + # Certificate doesn't have an expiration date, so this is a thing that the client must define. + "expiration_date": timestamp + timezone.timedelta(days=365), + "grade": certificate_data.grade, + "is_passing": _user_has_passing_grade(user, certificate_data.course), + "user": { + "national_id": user.username, + "english_name": student_api.get_name(user.id), + "arabic_name": extra_info.arabic_name if extra_info else "", + } + }