Esempio n. 1
0
    def publish_to_ecommerce(self, partner, course_run):
        api = EdxRestApiClient(partner.ecommerce_api_url,
                               jwt=partner.access_token)
        data = {
            'id':
            course_run.lms_course_id,
            'name':
            course_run.title_override or course_run.course.title,
            'verification_deadline':
            serialize_datetime(course_run.end),
            'create_or_activate_enrollment_code':
            False,
            # NOTE (CCB): We only order here to aid testing. The E-Commerce API does NOT care about ordering.
            'products': [
                serialize_seat_for_ecommerce_api(seat)
                for seat in course_run.seats.exclude(
                    type=Seat.CREDIT).order_by('created')
            ],
        }

        try:
            api.publication.post(data)
            return self.PUBLICATION_SUCCESS_STATUS
        except SlumberBaseException as ex:
            content = ex.content.decode('utf8')
            logger.exception(
                'Failed to publish course run [%d] to E-Commerce! Error was: [%s]',
                course_run.pk, content)
            return 'FAILED: ' + content
Esempio n. 2
0
    def publish_to_ecommerce(self, partner, course_run):
        course_key = self.get_course_key(course_run.course)
        discovery_course = Course.objects.get(partner=partner, key=course_key)

        api = EdxRestApiClient(partner.ecommerce_api_url,
                               jwt=partner.access_token)
        data = {
            'id': course_run.lms_course_id,
            'uuid': str(discovery_course.uuid),
            'name': course_run.title_override or course_run.course.title,
            'verification_deadline': serialize_datetime(course_run.end),
        }

        # NOTE: We only order here to aid testing. The E-Commerce API does NOT care about ordering.
        products = [
            serialize_seat_for_ecommerce_api(seat)
            for seat in course_run.seats.exclude(
                type=Seat.CREDIT).order_by('created')
        ]
        products.extend([
            serialize_entitlement_for_ecommerce_api(entitlement) for
            entitlement in course_run.course.entitlements.order_by('created')
        ])
        data['products'] = products

        try:
            api.publication.post(data)
            return self.PUBLICATION_SUCCESS_STATUS
        except SlumberBaseException as ex:
            content = ex.content.decode('utf8')
            logger.exception(
                'Failed to publish course run [%d] to E-Commerce! Error was: [%s]',
                course_run.pk, content)
            return 'FAILED: ' + content
Esempio n. 3
0
 def test_serialize_seat_for_ecommerce_api_with_id_verification(
         self, seat_type):
     seat = SeatFactory(type=seat_type)
     actual = serialize_seat_for_ecommerce_api(seat)
     expected_attribute_values = [{
         'name': 'certificate_type',
         'value': seat_type,
     }, {
         'name': 'id_verification_required',
         'value': True,
     }]
     assert actual['attribute_values'] == expected_attribute_values
Esempio n. 4
0
    def test_serialize_seat_for_ecommerce_api_with_audit_seat(self):
        seat = SeatFactory(type=Seat.AUDIT)
        actual = serialize_seat_for_ecommerce_api(seat)
        expected = {
            'expires':
            serialize_datetime(seat.calculated_upgrade_deadline),
            'price':
            str(seat.price),
            'product_class':
            'Seat',
            'attribute_values': [{
                'name': 'certificate_type',
                'value': '',
            }, {
                'name': 'id_verification_required',
                'value': False,
            }]
        }

        assert actual == expected
Esempio n. 5
0
 def test_serialize_seat_for_ecommerce_api(self):
     seat = SeatFactory()
     actual = serialize_seat_for_ecommerce_api(seat)
     assert actual['price'] == str(seat.price)
     assert actual['product_class'] == 'Seat'
Esempio n. 6
0
    def test_publish(self, mock_access_token):  # pylint: disable=unused-argument,too-many-statements
        publisher_course_run = self._create_course_run_for_publication()

        currency = Currency.objects.get(code='USD')
        common_seat_kwargs = {
            'course_run': publisher_course_run,
            'currency': currency,
        }
        audit_seat = SeatFactory(type=Seat.AUDIT,
                                 upgrade_deadline=None,
                                 **common_seat_kwargs)
        # The credit seat should NOT be published.
        SeatFactory(type=Seat.CREDIT, **common_seat_kwargs)
        professional_seat = SeatFactory(type=Seat.PROFESSIONAL,
                                        **common_seat_kwargs)
        verified_seat = SeatFactory(type=Seat.VERIFIED, **common_seat_kwargs)

        partner = publisher_course_run.course.organizations.first().partner
        self._set_test_client_domain_and_login(partner)

        self._mock_studio_api_success(publisher_course_run)
        self._mock_ecommerce_api(publisher_course_run)

        url = reverse('publisher:api:v1:course_run-publish',
                      kwargs={'pk': publisher_course_run.pk})
        response = self.client.post(url, {})
        assert response.status_code == 200
        assert len(responses.calls) == 3
        expected = {
            'discovery': CourseRunViewSet.PUBLICATION_SUCCESS_STATUS,
            'ecommerce': CourseRunViewSet.PUBLICATION_SUCCESS_STATUS,
            'studio': CourseRunViewSet.PUBLICATION_SUCCESS_STATUS,
        }
        assert response.data == expected

        # Verify the correct deadlines were sent to the E-Commerce API
        ecommerce_body = json.loads(responses.calls[2].request.body)
        expected = [
            serialize_seat_for_ecommerce_api(audit_seat),
            serialize_seat_for_ecommerce_api(professional_seat),
            serialize_seat_for_ecommerce_api(verified_seat),
        ]
        assert ecommerce_body['products'] == expected
        assert ecommerce_body['verification_deadline'] == serialize_datetime(
            publisher_course_run.end)

        discovery_course_run = CourseRun.objects.get(
            key=publisher_course_run.lms_course_id)
        publisher_course = publisher_course_run.course
        discovery_course = discovery_course_run.course

        # pylint: disable=no-member
        assert discovery_course_run.title_override == publisher_course_run.title_override
        assert discovery_course_run.short_description_override is None
        assert discovery_course_run.full_description_override is None
        assert discovery_course_run.start == publisher_course_run.start
        assert discovery_course_run.end == publisher_course_run.end
        assert discovery_course_run.enrollment_start == publisher_course_run.enrollment_start
        assert discovery_course_run.enrollment_end == publisher_course_run.enrollment_end
        assert discovery_course_run.pacing_type == publisher_course_run.pacing_type
        assert discovery_course_run.min_effort == publisher_course_run.min_effort
        assert discovery_course_run.max_effort == publisher_course_run.max_effort
        assert discovery_course_run.language == publisher_course_run.language
        assert discovery_course_run.weeks_to_complete == publisher_course_run.length
        assert discovery_course_run.learner_testimonials == publisher_course.learner_testimonial
        expected = set(publisher_course_run.transcript_languages.all())
        assert set(discovery_course_run.transcript_languages.all()) == expected
        assert set(discovery_course_run.staff.all()) == set(
            publisher_course_run.staff.all())

        assert discovery_course.canonical_course_run == discovery_course_run
        assert discovery_course.partner == partner
        assert discovery_course.title == publisher_course.title
        assert discovery_course.short_description == publisher_course.short_description
        assert discovery_course.full_description == publisher_course.full_description
        assert discovery_course.level_type == publisher_course.level_type
        assert discovery_course.video == Video.objects.get(
            src=publisher_course.video_link)
        assert discovery_course.image.name is not None
        assert discovery_course.image.url is not None
        assert discovery_course.image.file is not None
        assert discovery_course.image.small.url is not None
        assert discovery_course.image.small.file is not None
        assert discovery_course.outcome == publisher_course.expected_learnings
        assert discovery_course.prerequisites_raw == publisher_course.prerequisites
        assert discovery_course.syllabus_raw == publisher_course.syllabus
        expected = list(publisher_course_run.course.organizations.all())
        assert list(discovery_course.authoring_organizations.all()) == expected
        expected = {
            publisher_course.primary_subject,
            publisher_course.secondary_subject
        }
        assert set(discovery_course.subjects.all()) == expected

        common_seat_kwargs = {
            'course_run': discovery_course_run,
            'currency': currency,
        }
        DiscoverySeat.objects.get(type=DiscoverySeat.AUDIT,
                                  upgrade_deadline__isnull=True,
                                  **common_seat_kwargs)
        DiscoverySeat.objects.get(type=DiscoverySeat.PROFESSIONAL,
                                  upgrade_deadline__isnull=True,
                                  price=professional_seat.price,
                                  **common_seat_kwargs)
        DiscoverySeat.objects.get(
            type=DiscoverySeat.VERIFIED,
            upgrade_deadline=verified_seat.upgrade_deadline,
            price=verified_seat.price,
            **common_seat_kwargs)