Ejemplo n.º 1
0
    def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
        self.full_clean(validate_unique=False)

        # .. event_implemented_name: COHORT_MEMBERSHIP_CHANGED
        COHORT_MEMBERSHIP_CHANGED.send_event(
            cohort=CohortData(
                user=UserData(
                    pii=UserPersonalData(
                        username=self.user.username,
                        email=self.user.email,
                        name=self.user.profile.name,
                    ),
                    id=self.user.id,
                    is_active=self.user.is_active,
                ),
                course=CourseData(
                    course_key=self.course_id,
                ),
                name=self.course_user_group.name,
            )
        )

        log.info("Saving CohortMembership for user '%s' in '%s'", self.user.id, self.course_id)
        return super().save(
            force_insert=force_insert,
            force_update=force_update,
            using=using,
            update_fields=update_fields
        )
Ejemplo n.º 2
0
 def setUp(self):
     """
     Setup common conditions for every test case.
     """
     super().setUp()
     self.certificate = CertificateData(
         user=UserData(
             pii=UserPersonalData(
                 username="******",
                 email="*****@*****.**",
                 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=100,
         download_url="https://downdloadurl.com",
         name="Certs",
     )
Ejemplo n.º 3
0
 def setUp(self):
     """
     Setup common conditions for test cases.
     """
     enrollment = CourseEnrollmentData(
         user=UserData(
             pii=UserPersonalData(
                 username="******",
                 email="*****@*****.**",
                 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 = {
         "enrollment": enrollment,
     }
Ejemplo n.º 4
0
    def test_send_certificate_changed_event(self):
        """
        Test whether the certificate changed event is sent at the end of the
        certificate update process.

        Expected result:
            - CERTIFICATE_CHANGED is sent and received by the mocked receiver.
            - The arguments that the receiver gets are the arguments sent by the event
            except the metadata generated on the fly.
        """
        event_receiver = Mock(side_effect=self._event_receiver_side_effect)
        CERTIFICATE_CHANGED.connect(event_receiver)
        certificate = GeneratedCertificateFactory.create(
            status=CertificateStatuses.downloadable,
            user=self.user,
            course_id=self.course.id,
            mode=GeneratedCertificate.MODES.honor,
            name="Certificate",
            grade="100",
            download_url="https://certificate.pdf")

        certificate.grade = "50"
        certificate.save()

        self.assertTrue(self.receiver_called)
        self.assertDictContainsSubset(
            {
                "signal":
                CERTIFICATE_CHANGED,
                "sender":
                None,
                "certificate":
                CertificateData(
                    user=UserData(
                        pii=UserPersonalData(
                            username=certificate.user.username,
                            email=certificate.user.email,
                            name=certificate.user.profile.name,
                        ),
                        id=certificate.user.id,
                        is_active=certificate.user.is_active,
                    ),
                    course=CourseData(course_key=certificate.course_id, ),
                    mode=certificate.mode,
                    grade=certificate.grade,
                    current_status=certificate.status,
                    download_url=certificate.download_url,
                    name=certificate.name,
                ),
            }, event_receiver.call_args.kwargs)
Ejemplo n.º 5
0
    def test_unenrollment_completed_event_emitted(self):
        """
        Test whether the student un-enrollment completed event is sent after the
        user's unenrollment process.

        Expected result:
            - COURSE_UNENROLLMENT_COMPLETED is sent and received by the mocked receiver.
            - The arguments that the receiver gets are the arguments sent by the event
            except the metadata generated on the fly.
        """
        enrollment = CourseEnrollment.enroll(self.user, self.course.id)
        event_receiver = mock.Mock(
            side_effect=self._event_receiver_side_effect)
        COURSE_UNENROLLMENT_COMPLETED.connect(event_receiver)

        CourseEnrollment.unenroll(self.user, self.course.id)

        self.assertTrue(self.receiver_called)
        self.assertDictContainsSubset(
            {
                "signal":
                COURSE_UNENROLLMENT_COMPLETED,
                "sender":
                None,
                "enrollment":
                CourseEnrollmentData(
                    user=UserData(
                        pii=UserPersonalData(
                            username=self.user.username,
                            email=self.user.email,
                            name=self.user.profile.name,
                        ),
                        id=self.user.id,
                        is_active=self.user.is_active,
                    ),
                    course=CourseData(
                        course_key=self.course.id,
                        display_name=self.course.display_name,
                    ),
                    mode=enrollment.mode,
                    is_active=False,
                    creation_date=enrollment.created,
                ),
            }, event_receiver.call_args.kwargs)
Ejemplo n.º 6
0
    def test_send_cohort_membership_changed_event(self):
        """
        Test whether the COHORT_MEMBERSHIP_CHANGED event is sent when a cohort
        membership update ends.

        Expected result:
            - COHORT_MEMBERSHIP_CHANGED is sent and received by the mocked receiver.
            - The arguments that the receiver gets are the arguments sent by the event
            except the metadata generated on the fly.
        """
        event_receiver = Mock(side_effect=self._event_receiver_side_effect)
        COHORT_MEMBERSHIP_CHANGED.connect(event_receiver)

        cohort_membership, _ = CohortMembership.assign(
            cohort=self.cohort,
            user=self.user,
        )

        self.assertTrue(self.receiver_called)
        self.assertDictContainsSubset(
            {
                "signal": COHORT_MEMBERSHIP_CHANGED,
                "sender": None,
                "cohort": CohortData(
                    user=UserData(
                        pii=UserPersonalData(
                            username=cohort_membership.user.username,
                            email=cohort_membership.user.email,
                            name=cohort_membership.user.profile.name,
                        ),
                        id=cohort_membership.user.id,
                        is_active=cohort_membership.user.is_active,
                    ),
                    course=CourseData(
                        course_key=cohort_membership.course_id,
                    ),
                    name=cohort_membership.course_user_group.name,
                ),
            },
            event_receiver.call_args.kwargs
        )
Ejemplo n.º 7
0
 def setUp(self):
     """
     Setup common conditions for every test case.
     """
     super().setUp()
     self.cohort = CohortData(
         user=UserData(
             pii=UserPersonalData(
                 username="******",
                 email="*****@*****.**",
                 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",
         ),
         name="Uchiha",
     )
Ejemplo n.º 8
0
 def setUp(self):
     """
     Setup common conditions for test cases.
     """
     self.certificate = CertificateData(
         user=UserData(
             pii=UserPersonalData(
                 username="******",
                 email="*****@*****.**",
                 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,
     }
     self.course_key = CourseKey.from_string("course-v1:edx+DemoX+Demo_Course")
     self.grading_config = {
         "block_id": "467f8ab131634e52bb6c22b60940d857",
         "program_id": "course-v1:edx+DemoX+Demo_Course",
     }
     self.usage_key = self.course_key.make_usage_key(
         "staffgradedxblock",
         self.grading_config.get("block_id")
     )
Ejemplo n.º 9
0
    def save(self, *args, **kwargs):  # pylint: disable=signature-differs
        """
        After the base save() method finishes, fire the COURSE_CERT_CHANGED signal. If the learner is currently passing
        the course we also fire the COURSE_CERT_AWARDED signal.

        The COURSE_CERT_CHANGED signal helps determine if a Course Certificate can be awarded to a learner in the
        Credentials IDA.

        The COURSE_CERT_AWARDED signal helps determine if a Program Certificate can be awarded to a learner in the
        Credentials IDA.
        """
        super().save(*args, **kwargs)
        COURSE_CERT_CHANGED.send_robust(
            sender=self.__class__,
            user=self.user,
            course_key=self.course_id,
            mode=self.mode,
            status=self.status,
        )

        # .. event_implemented_name: CERTIFICATE_CHANGED
        CERTIFICATE_CHANGED.send_event(certificate=CertificateData(
            user=UserData(
                pii=UserPersonalData(
                    username=self.user.username,
                    email=self.user.email,
                    name=self.user.profile.name,
                ),
                id=self.user.id,
                is_active=self.user.is_active,
            ),
            course=CourseData(course_key=self.course_id, ),
            mode=self.mode,
            grade=self.grade,
            current_status=self.status,
            download_url=self.download_url,
            name=self.name,
        ))

        if CertificateStatuses.is_passing_status(self.status):
            COURSE_CERT_AWARDED.send_robust(
                sender=self.__class__,
                user=self.user,
                course_key=self.course_id,
                mode=self.mode,
                status=self.status,
            )

            # .. event_implemented_name: CERTIFICATE_CREATED
            CERTIFICATE_CREATED.send_event(certificate=CertificateData(
                user=UserData(
                    pii=UserPersonalData(
                        username=self.user.username,
                        email=self.user.email,
                        name=self.user.profile.name,
                    ),
                    id=self.user.id,
                    is_active=self.user.is_active,
                ),
                course=CourseData(course_key=self.course_id, ),
                mode=self.mode,
                grade=self.grade,
                current_status=self.status,
                download_url=self.download_url,
                name=self.name,
            ))
Ejemplo n.º 10
0
    def _revoke_certificate(self, status, mode=None, grade=None, source=None):
        """
        Revokes a course certificate from a learner, updating the certificate's status as specified by the value of the
        `status` argument. This will prevent the learner from being able to access their certificate in the associated
        course run.

        We remove the `download_uuid` and the `download_url` as well, but this is only important to PDF certificates.

        Invalidating a certificate fires the `COURSE_CERT_REVOKED` signal. This kicks off a task to determine if there
        are any program certificates that also need to be revoked from the learner.

        If the certificate had a status of `downloadable` before being revoked then we will also emit an
        `edx.certificate.revoked` event for tracking purposes.

        Args:
            status (CertificateStatus) - certificate status to set for the `GeneratedCertificate` record
            mode (String) - learner's current enrollment mode
            grade (float) - snapshot of the learner's current grade as a decimal
            source (String) - source requesting invalidation of the certificate for tracking purposes
        """
        previous_certificate_status = self.status

        if not grade:
            grade = ''

        if not mode:
            mode = self.mode

        preferred_name = self._get_preferred_certificate_name(self.user)

        self.error_reason = ''
        self.download_uuid = ''
        self.download_url = ''
        self.grade = grade
        self.status = status
        self.mode = mode
        self.name = preferred_name
        self.save()

        COURSE_CERT_REVOKED.send_robust(
            sender=self.__class__,
            user=self.user,
            course_key=self.course_id,
            mode=self.mode,
            status=self.status,
        )

        # .. event_implemented_name: CERTIFICATE_REVOKED
        CERTIFICATE_REVOKED.send_event(certificate=CertificateData(
            user=UserData(
                pii=UserPersonalData(
                    username=self.user.username,
                    email=self.user.email,
                    name=self.user.profile.name,
                ),
                id=self.user.id,
                is_active=self.user.is_active,
            ),
            course=CourseData(course_key=self.course_id, ),
            mode=self.mode,
            grade=self.grade,
            current_status=self.status,
            download_url=self.download_url,
            name=self.name,
        ))

        if previous_certificate_status == CertificateStatuses.downloadable:
            # imported here to avoid a circular import issue
            from lms.djangoapps.certificates.utils import emit_certificate_event

            event_data = {
                'user_id': self.user.id,
                'course_id': str(self.course_id),
                'certificate_id': self.verify_uuid,
                'enrollment_mode': self.mode,
                'source': source or '',
            }
            emit_certificate_event('revoked',
                                   self.user,
                                   str(self.course_id),
                                   event_data=event_data)