Exemplo n.º 1
0
    def test_format_benefit_value(self):
        """ format_benefit_value(benefit) should format benefit value based on benefit type """
        benefit_value = format_benefit_value(self.percentage_benefit)
        self.assertEqual(benefit_value, '35%')

        benefit_value = format_benefit_value(self.value_benefit)
        self.assertEqual(benefit_value, currency(self.seat_price - 10))
Exemplo n.º 2
0
    def test_format_benefit_value(self):
        """ format_benefit_value(benefit) should format benefit value based on benefit type """
        benefit_value = format_benefit_value(self.percentage_benefit)
        self.assertEqual(benefit_value, '35%')

        benefit_value = format_benefit_value(self.value_benefit)
        self.assertEqual(benefit_value, currency(self.seat_price - 10))
Exemplo n.º 3
0
    def test_format_benefit_value(self):
        """ format_benefit_value(benefit) should format benefit value based on benefit type """
        benefit_value = format_benefit_value(self.percentage_benefit)
        self.assertEqual(benefit_value, '35%')

        benefit_value = format_benefit_value(self.value_benefit)
        expected_benefit = add_currency(Decimal((self.seat_price - 10)))
        self.assertEqual(benefit_value, '${expected_benefit}'.format(expected_benefit=expected_benefit))
Exemplo n.º 4
0
    def test_format_benefit_value(self):
        """ format_benefit_value(benefit) should format benefit value based on benefit type """
        benefit_value = format_benefit_value(self.percentage_benefit)
        self.assertEqual(benefit_value, '35%')

        benefit_value = format_benefit_value(self.value_benefit)
        expected_benefit = add_currency(Decimal((self.seat_price - 10)))
        self.assertEqual(benefit_value, '${expected_benefit}'.format(expected_benefit=expected_benefit))
Exemplo n.º 5
0
    def test_format_program_benefit_value(self):
        """ format_benefit_value(program_benefit) should format benefit value based on proxy class. """
        percentage_benefit = PercentageDiscountBenefitWithoutRangeFactory()
        benefit_value = format_benefit_value(percentage_benefit)
        self.assertEqual(benefit_value, '{}%'.format(percentage_benefit.value))

        absolute_benefit = AbsoluteDiscountBenefitWithoutRangeFactory()
        benefit_value = format_benefit_value(absolute_benefit)
        expected_value = add_currency(Decimal(absolute_benefit.value))
        self.assertEqual(benefit_value, '${}'.format(expected_value))
Exemplo n.º 6
0
    def test_format_benefit_value(self):
        """ format_benefit_value(benefit) should format benefit value based on benefit type """
        benefit_value = format_benefit_value(self.percentage_benefit)
        self.assertEqual(benefit_value, '35%')

        benefit_value = format_benefit_value(self.value_benefit)
        expected_benefit = format_currency(Decimal((self.seat_price - 10)),
                                           settings.OSCAR_DEFAULT_CURRENCY,
                                           format=u'#,##0.00',
                                           locale=to_locale(get_language()))
        self.assertEqual(
            benefit_value,
            '${expected_benefit}'.format(expected_benefit=expected_benefit))
Exemplo n.º 7
0
    def process_totals(self, context):
        """
        Returns a Dictionary of data related to total price and discounts.
        """
        # Total benefit displayed in price summary.
        # Currently only one voucher per basket is supported.
        try:
            applied_voucher = self.request.basket.vouchers.first()
            total_benefit_object = applied_voucher.best_offer.benefit if applied_voucher else None
        # TODO This ValueError handling no longer seems to be required and could probably be removed
        except ValueError:  # pragma: no cover
            total_benefit_object = None

        num_of_items = self.request.basket.num_items

        discount_jwt = None
        discount_percent = None
        if waffle.flag_is_active(self.request, DYNAMIC_DISCOUNT_FLAG):
            applied_offers = self.request.basket.applied_offers().values()
            if len(applied_offers) == 1 and list(applied_offers)[0].condition.name == 'dynamic_discount_condition':
                discount_jwt = self.request.GET.get('discount_jwt')
                discount_percent = get_percentage_from_request()
        return {
            'total_benefit_object': total_benefit_object,
            'total_benefit': format_benefit_value(total_benefit_object) if total_benefit_object else None,
            'free_basket': context['order_total'].incl_tax == 0,
            'line_price': (self.request.basket.total_incl_tax_excl_discounts / num_of_items) if num_of_items > 0 else 0,
            'discount_jwt': discount_jwt,
            'discount_percent': discount_percent,
        }
Exemplo n.º 8
0
    def test_response_success(self, benefit_type, benefit_value):
        """ Verify a successful response is returned. """
        seat = self.create_seat(self.course, 500)
        basket = self.create_basket_and_add_product(seat)
        self.create_and_apply_benefit_to_basket(basket, seat, benefit_type,
                                                benefit_value)

        self.assertEqual(basket.lines.count(), 1)
        self.mock_dynamic_catalog_single_course_runs_api(self.course)

        benefit, __ = Benefit.objects.get_or_create(type=benefit_type,
                                                    value=benefit_value)

        response = self.client.get(self.path)
        self.assertEqual(response.status_code, 200)
        self.assertEqual(len(response.context['formset_lines_data']), 1)
        line_data = response.context['formset_lines_data'][0][1]
        self.assertEqual(line_data['benefit_value'],
                         format_benefit_value(benefit))
        self.assertEqual(line_data['seat_type'],
                         _(seat.attr.certificate_type.capitalize()))
        self.assertEqual(line_data['course_name'], self.course.name)
        self.assertFalse(line_data['enrollment_code'])
        self.assertEqual(response.context['payment_processors'][0].NAME,
                         DummyProcessor.NAME)
Exemplo n.º 9
0
 def _get_benefit_value(self, line):
     if line.has_discount:
         applied_offer_values = list(self.request.basket.applied_offers().values())
         if applied_offer_values:
             benefit = applied_offer_values[0].benefit
             return format_benefit_value(benefit)
     return None
Exemplo n.º 10
0
    def get_context_data(self, **kwargs):
        context = super(BasketSummaryView, self).get_context_data(**kwargs)
        formset = context.get('formset', [])
        lines = context.get('line_list', [])
        site_configuration = self.request.site.siteconfiguration

        failed_enterprise_consent_code = self.request.GET.get(CONSENT_FAILED_PARAM)
        if failed_enterprise_consent_code:
            messages.error(
                self.request,
                _("Could not apply the code '{code}'; it requires data sharing consent.").format(
                    code=failed_enterprise_consent_code
                )
            )

        context_updates, lines_data = self._process_basket_lines(lines)
        context.update(context_updates)

        user = self.request.user
        context.update({
            'analytics_data': prepare_analytics_data(
                user,
                site_configuration.segment_key,
            ),
            'enable_client_side_checkout': False,
            'sdn_check': site_configuration.enable_sdn_check
        })

        payment_processors = site_configuration.get_payment_processors()
        if site_configuration.client_side_payment_processor \
                and waffle.flag_is_active(self.request, CLIENT_SIDE_CHECKOUT_FLAG_NAME):
            payment_processors_data = self._get_payment_processors_data(payment_processors)
            context.update(payment_processors_data)

        # Total benefit displayed in price summary.
        # Currently only one voucher per basket is supported.
        try:
            applied_voucher = self.request.basket.vouchers.first()
            total_benefit = (
                format_benefit_value(applied_voucher.best_offer.benefit)
                if applied_voucher else None
            )
        except ValueError:
            total_benefit = None
        num_of_items = self.request.basket.num_items
        context.update({
            'formset_lines_data': zip(formset, lines_data),
            'free_basket': context['order_total'].incl_tax == 0,
            'homepage_url': get_lms_url(''),
            'min_seat_quantity': 1,
            'max_seat_quantity': 100,
            'payment_processors': payment_processors,
            'total_benefit': total_benefit,
            'enable_alipay_wechatpay': settings.ENABLE_ALIPAY_WECHATPAY,
            'line_price': (self.request.basket.total_incl_tax_excl_discounts / num_of_items) if num_of_items > 0 else 0
        })
        return context
Exemplo n.º 11
0
    def test_response_success(self, benefit_type, benefit_value):
        """ Verify a successful response is returned. """
        seat = self.create_seat(self.course, 500)
        basket = self.create_basket_and_add_product(seat)
        self.mock_access_token_response()
        self.create_and_apply_benefit_to_basket(basket, seat, benefit_type,
                                                benefit_value)

        self.assertEqual(basket.lines.count(), 1)
        self.mock_course_run_detail_endpoint(
            self.course,
            discovery_api_url=self.site_configuration.discovery_api_url)

        benefit, __ = Benefit.objects.get_or_create(type=benefit_type,
                                                    value=benefit_value)

        with mock.patch(
                'ecommerce.extensions.basket.views.track_segment_event',
                return_value=(True, '')) as mock_track:
            response = self.client.get(self.path)

            # Verify events are sent to Segment
            calls = []
            properties = {
                'cart_id':
                basket.id,
                'products': [
                    translate_basket_line_for_segment(line)
                    for line in basket.all_lines()
                ],
            }
            calls.append(
                mock.call(
                    self.site,
                    self.user,
                    'Cart Viewed',
                    properties,
                ))

            properties = {'checkout_id': basket.order_number, 'step': 1}
            calls.append(
                mock.call(self.site, self.user, 'Checkout Step Viewed',
                          properties))
            mock_track.assert_has_calls(calls)

        self.assertEqual(response.status_code, 200)
        self.assertEqual(len(response.context['formset_lines_data']), 1)

        line_data = response.context['formset_lines_data'][0][1]
        self.assertEqual(line_data['benefit_value'],
                         format_benefit_value(benefit))
        self.assertEqual(line_data['seat_type'],
                         seat.attr.certificate_type.capitalize())
        self.assertEqual(line_data['product_title'], self.course.name)
        self.assertFalse(line_data['enrollment_code'])
        self.assertEqual(response.context['payment_processors'][0].NAME,
                         DummyProcessor.NAME)
Exemplo n.º 12
0
    def _get_providers_detail(self, credit_seats):
        """ Get details for the credit providers for the given credit seats.

        Arguments:
            credit_seats (Products[]): List of credit_seats objects.

        Returns:
            A list of dictionaries with provider(s) detail.
        """
        code = self.request.GET.get('code')
        if code:
            voucher = Voucher.objects.get(code=code)
            discount_type = voucher.benefit.type
            discount_value = voucher.benefit.value

        providers = self._get_providers_from_lms(credit_seats)
        if not providers:
            return None

        providers_dict = {}
        for provider in providers:
            providers_dict[provider['id']] = provider

        partner = get_partner_for_site(self.request)
        for seat in credit_seats:
            stockrecord = seat.stockrecords.filter(partner=partner).first()
            new_price = None
            discount = None
            if code:
                discount = format_benefit_value(voucher.benefit)
                if discount_type == 'Percentage':
                    new_price = stockrecord.price_excl_tax - (
                        stockrecord.price_excl_tax * (discount_value / 100))
                else:
                    new_price = stockrecord.price_excl_tax - discount_value
                new_price = '{0:.2f}'.format(new_price)
            providers_dict[seat.attr.credit_provider].update({
                'price':
                stockrecord.price_excl_tax,
                'sku':
                stockrecord.partner_sku,
                'credit_hours':
                seat.attr.credit_hours,
                'discount':
                discount,
                'new_price':
                new_price
            })

        return providers_dict.values()
Exemplo n.º 13
0
    def get_context_data(self, **kwargs):
        context = super(BasketSummaryView, self).get_context_data(**kwargs)
        formset = context.get('formset', [])
        lines = context.get('line_list', [])
        site_configuration = self.request.site.siteconfiguration

        context_updates, lines_data = self._process_basket_lines(lines)
        context.update(context_updates)

        course_key = lines_data[0].get('course_key') if len(
            lines) == 1 else None
        user = self.request.user
        context.update({
            'analytics_data':
            prepare_analytics_data(user, site_configuration.segment_key,
                                   unicode(course_key)),
            'enable_client_side_checkout':
            False,
            'sdn_check':
            site_configuration.enable_sdn_check
        })

        payment_processors = site_configuration.get_payment_processors()
        if site_configuration.client_side_payment_processor \
                and waffle.flag_is_active(self.request, CLIENT_SIDE_CHECKOUT_FLAG_NAME):
            payment_processors_data = self._get_payment_processors_data(
                payment_processors)
            context.update(payment_processors_data)

        # Total benefit displayed in price summary.
        # Currently only one voucher per basket is supported.
        try:
            applied_voucher = self.request.basket.vouchers.first()
            total_benefit = (format_benefit_value(
                applied_voucher.offers.first().benefit)
                             if applied_voucher else None)
        except ValueError:
            total_benefit = None

        context.update({
            'course_key': course_key,
            'formset_lines_data': zip(formset, lines_data),
            'free_basket': context['order_total'].incl_tax == 0,
            'homepage_url': get_lms_url(''),
            'min_seat_quantity': 1,
            'payment_processors': payment_processors,
            'total_benefit': total_benefit
        })
        return context
Exemplo n.º 14
0
def benefit_discount(benefit):
    """
    Format benefit value for display based on the benefit type.

    Example:
        '100%' if benefit.value == 100.00 and benefit.type == 'Percentage'
        '$100.00' if benefit.value == 100.00 and benefit.type == 'Absolute'

    Arguments:
        benefit (Benefit): Voucher's Benefit.

    Returns:
        str: String value containing formatted benefit value and type.
    """
    return format_benefit_value(benefit)
Exemplo n.º 15
0
def benefit_discount(benefit):
    """
    Format benefit value for display based on the benefit type.

    Example:
        '100%' if benefit.value == 100.00 and benefit.type == 'Percentage'
        '$100.00' if benefit.value == 100.00 and benefit.type == 'Absolute'

    Arguments:
        benefit (Benefit): Voucher's Benefit.

    Returns:
        str: String value containing formatted benefit value and type.
    """
    return format_benefit_value(benefit)
Exemplo n.º 16
0
    def test_response_success(self, benefit_type, benefit_value):
        """ Verify a successful response is returned. """
        seat = self.create_seat(self.course, 500)
        basket = self.create_basket_and_add_product(seat)
        self.create_and_apply_benefit_to_basket(basket, seat, benefit_type,
                                                benefit_value)

        self.assertEqual(basket.lines.count(), 1)
        self.mock_dynamic_catalog_single_course_runs_api(self.course)

        benefit, __ = Benefit.objects.get_or_create(type=benefit_type,
                                                    value=benefit_value)

        with mock.patch(
                'ecommerce.extensions.basket.views.track_segment_event',
                return_value=(True, '')) as mock_track:
            response = self.client.get(self.path)

            # Verify an event is sent to Segment
            properties = {
                'cart_id':
                basket.id,
                'products': [
                    translate_basket_line_for_segment(line)
                    for line in basket.all_lines()
                ],
            }
            mock_track.assert_called_once_with(self.site, self.user,
                                               'Cart Viewed', properties)

        self.assertEqual(response.status_code, 200)
        self.assertEqual(len(response.context['formset_lines_data']), 1)
        line_data = response.context['formset_lines_data'][0][1]
        self.assertEqual(line_data['benefit_value'],
                         format_benefit_value(benefit))
        self.assertEqual(line_data['seat_type'],
                         seat.attr.certificate_type.capitalize())
        self.assertEqual(line_data['product_title'], self.course.name)
        self.assertFalse(line_data['enrollment_code'])
        self.assertEqual(response.context['payment_processors'][0].NAME,
                         DummyProcessor.NAME)
Exemplo n.º 17
0
    def _process_basket_lines(self, lines):
        """Processes the basket lines and extracts information for the view's context.
        In addition determines whether:
            * verification message should be displayed
            * voucher form should be displayed
            * switch link (for switching between seat and enrollment code products) should be displayed
        and returns that information for the basket view context to be updated with it.

        Args:
            lines (list): List of basket lines.
        Returns:
            context_updates (dict): Containing information with which the context needs to
                                    be updated with.
            lines_data (list): List of information about the basket lines.
        """
        display_verification_message = False
        lines_data = []
        show_voucher_form = True
        switch_link_text = partner_sku = order_details_msg = None

        for line in lines:
            if line.product.is_seat_product or line.product.is_course_entitlement_product:
                line_data = self._get_course_data(line.product)
                certificate_type = line.product.attr.certificate_type

                if getattr(line.product.attr, 'id_verification_required',
                           False) and certificate_type != 'credit':
                    display_verification_message = True

                if line.product.is_course_entitlement_product:
                    order_details_msg = _(
                        'After you complete your order you will be able to select course dates from your dashboard.'
                    )
                else:
                    if certificate_type == 'verified':
                        order_details_msg = _(
                            'After you complete your order you will be automatically enrolled '
                            'in the verified track of the course.')
                    elif certificate_type == 'credit':
                        order_details_msg = _(
                            'After you complete your order you will receive credit for your course.'
                        )
                    else:
                        order_details_msg = _(
                            'After you complete your order you will be automatically enrolled in the course.'
                        )
            elif line.product.is_enrollment_code_product:
                line_data = self._get_course_data(line.product)
                show_voucher_form = False
                order_details_msg = _(
                    'You will receive an email at {user_email} with your enrollment code(s).'
                ).format(user_email=self.request.user.email)
            else:
                line_data = {
                    'product_title': line.product.title,
                    'image_url': None,
                    'product_description': line.product.description
                }

            # TODO: handle these links for multi-line baskets.
            if self.request.site.siteconfiguration.enable_enrollment_codes:
                # Get variables for the switch link that toggles from enrollment codes and seat.
                switch_link_text, partner_sku = get_basket_switch_data(
                    line.product)

            if line.has_discount:
                benefit = self.request.basket.applied_offers().values(
                )[0].benefit
                benefit_value = format_benefit_value(benefit)
            else:
                benefit_value = None

            line_data.update({
                'sku':
                line.product.stockrecords.first().partner_sku,
                'benefit_value':
                benefit_value,
                'enrollment_code':
                line.product.is_enrollment_code_product,
                'line':
                line,
                'seat_type':
                self._determine_product_type(line.product),
            })
            lines_data.append(line_data)

        context_updates = {
            'display_verification_message': display_verification_message,
            'order_details_msg': order_details_msg,
            'partner_sku': partner_sku,
            'show_voucher_form': show_voucher_form,
            'switch_link_text': switch_link_text
        }

        return context_updates, lines_data
Exemplo n.º 18
0
    def get_context_data(self, **kwargs):
        context = super(BasketSummaryView, self).get_context_data(**kwargs)
        formset = context.get('formset', [])
        lines = context.get('line_list', [])
        lines_data = []
        is_verification_required = is_bulk_purchase = False
        switch_link_text = partner_sku = ''
        basket = self.request.basket
        site = self.request.site
        site_configuration = site.siteconfiguration

        for line in lines:
            course_key = CourseKey.from_string(line.product.attr.course_key)
            course_name = None
            image_url = None
            short_description = None
            try:
                course = get_course_info_from_catalog(self.request.site, course_key)
                try:
                    image_url = course['image']['src']
                except (KeyError, TypeError):
                    image_url = ''
                short_description = course.get('short_description', '')
                course_name = course.get('title', '')
            except (ConnectionError, SlumberBaseException, Timeout):
                logger.exception('Failed to retrieve data from Catalog Service for course [%s].', course_key)

            if self.request.site.siteconfiguration.enable_enrollment_codes:
                # Get variables for the switch link that toggles from enrollment codes and seat.
                switch_link_text, partner_sku = get_basket_switch_data(line.product)
                if line.product.get_product_class().name == ENROLLMENT_CODE_PRODUCT_CLASS_NAME:
                    is_bulk_purchase = True
                    # Iterate on message storage so all messages are marked as read.
                    # This will hide the success messages when a user updates the quantity
                    # for an item in the basket.
                    list(messages.get_messages(self.request))

            if line.has_discount:
                benefit = basket.applied_offers().values()[0].benefit
                benefit_value = format_benefit_value(benefit)
            else:
                benefit_value = None

            lines_data.append({
                'seat_type': self._determine_seat_type(line.product),
                'course_name': course_name,
                'course_key': course_key,
                'image_url': image_url,
                'course_short_description': short_description,
                'benefit_value': benefit_value,
                'enrollment_code': line.product.get_product_class().name == ENROLLMENT_CODE_PRODUCT_CLASS_NAME,
                'line': line,
            })

            user = self.request.user
            context.update({
                'analytics_data': prepare_analytics_data(
                    user,
                    self.request.site.siteconfiguration.segment_key,
                    unicode(course_key)
                ),
                'enable_client_side_checkout': False,
            })

            if site_configuration.client_side_payment_processor \
                    and waffle.flag_is_active(self.request, CLIENT_SIDE_CHECKOUT_FLAG_NAME):
                payment_processor_class = site_configuration.get_client_side_payment_processor_class()

                if payment_processor_class:
                    payment_processor = payment_processor_class(site)

                    context.update({
                        'enable_client_side_checkout': True,
                        'payment_form': PaymentForm(user=user, initial={'basket': basket}, label_suffix=''),
                        'payment_url': payment_processor.client_side_payment_url,
                    })
                else:
                    msg = 'Unable to load client-side payment processor [{processor}] for ' \
                          'site configuration [{sc}]'.format(processor=site_configuration.client_side_payment_processor,
                                                             sc=site_configuration.id)
                    raise SiteConfigurationError(msg)

            # Check product attributes to determine if ID verification is required for this basket
            try:
                is_verification_required = line.product.attr.id_verification_required \
                    and line.product.attr.certificate_type != 'credit'
            except AttributeError:
                pass

        context.update({
            'free_basket': context['order_total'].incl_tax == 0,
            'payment_processors': site_configuration.get_payment_processors(),
            'homepage_url': get_lms_url(''),
            'formset_lines_data': zip(formset, lines_data),
            'is_verification_required': is_verification_required,
            'min_seat_quantity': 1,
            'is_bulk_purchase': is_bulk_purchase,
            'switch_link_text': switch_link_text,
            'partner_sku': partner_sku,
        })

        return context
Exemplo n.º 19
0
    def get_context_data(self, **kwargs):
        context = super(CouponOfferView, self).get_context_data(**kwargs)
        code = self.request.GET.get('code', None)
        if code is not None:
            try:
                voucher, product = get_voucher_from_code(code=code)
            except Voucher.DoesNotExist:
                return {
                    'error': _('Coupon does not exist'),
                }
            except exceptions.ProductNotFoundError:
                return {
                    'error':
                    _('The voucher is not applicable to your current basket.'),
                }
            valid_voucher, msg = voucher_is_valid(voucher, product,
                                                  self.request)
            if valid_voucher:
                api = EdxRestApiClient(get_lms_url('api/courses/v1/'), )
                try:
                    course = api.courses(product.course_id).get()
                except SlumberHttpBaseException as e:
                    logger.exception('Could not get course information. [%s]',
                                     e)
                    return {
                        'error':
                        _('Could not get course information. [{error}]'.format(
                            error=e)),
                    }
                course['image_url'] = get_lms_url(
                    course['media']['course_image']['uri'])
                benefit = voucher.offers.first().benefit
                # Note (multi-courses): fix this to work for all stock records / courses.
                if benefit.range.catalog:
                    stock_record = benefit.range.catalog.stock_records.first()
                else:
                    stock_record = StockRecord.objects.get(
                        product=benefit.range.included_products.first())
                price = stock_record.price_excl_tax
                benefit_value = format_benefit_value(benefit)
                if benefit.type == 'Percentage':
                    new_price = price - (price * (benefit.value / 100))
                else:
                    new_price = price - benefit.value
                    if new_price < 0:
                        new_price = Decimal(0)

                context.update({
                    'analytics_data':
                    prepare_analytics_data(
                        self.request.user,
                        self.request.site.siteconfiguration.segment_key,
                        product.course_id),
                    'benefit_value':
                    benefit_value,
                    'course':
                    course,
                    'code':
                    code,
                    'is_discount_value_percentage':
                    benefit.type == 'Percentage',
                    'is_enrollment_code':
                    benefit.type == Benefit.PERCENTAGE
                    and benefit.value == 100.00,
                    'discount_value':
                    "%.2f" % (price - new_price),
                    'price':
                    price,
                    'new_price':
                    "%.2f" % new_price,
                    'verified': (product.attr.certificate_type == 'verified'),
                    'verification_deadline':
                    product.course.verification_deadline,
                })
                return context
            return {
                'error': msg,
            }
        return {
            'error': _('This coupon code is invalid.'),
        }
Exemplo n.º 20
0
    def get_context_data(self, **kwargs):
        context = super(BasketSummaryView, self).get_context_data(**kwargs)
        formset = context.get('formset', [])
        lines = context.get('line_list', [])
        lines_data = []
        is_verification_required = is_bulk_purchase = False
        switch_link_text = partner_sku = ''

        for line in lines:
            course_key = CourseKey.from_string(line.product.attr.course_key)
            course_name = None
            image_url = None
            short_description = None
            try:
                course = get_course_info_from_lms(course_key)
                image_url = get_lms_url(course['media']['course_image']['uri'])
                short_description = course['short_description']
                course_name = course['name']
            except (ConnectionError, SlumberBaseException, Timeout):
                logger.exception('Failed to retrieve data from Course API for course [%s].', course_key)

            # Set to true if any course in basket has bulk purchase scenario
            if line.product.get_product_class().name == ENROLLMENT_CODE_PRODUCT_CLASS_NAME:
                is_bulk_purchase = True
                # Iterate on message storage so all messages are marked as read
                list(messages.get_messages(self.request))

            # Get variables for alternative basket view
            switch_link_text, partner_sku = get_basket_switch_data(line.product)

            if line.has_discount:
                benefit = self.request.basket.applied_offers().values()[0].benefit
                benefit_value = format_benefit_value(benefit)
            else:
                benefit_value = None

            lines_data.append({
                'seat_type': self._determine_seat_type(line.product),
                'course_name': course_name,
                'course_key': course_key,
                'image_url': image_url,
                'course_short_description': short_description,
                'benefit_value': benefit_value,
                'enrollment_code': line.product.get_product_class().name == ENROLLMENT_CODE_PRODUCT_CLASS_NAME,
                'line': line,
            })

            context.update({
                'analytics_data': prepare_analytics_data(
                    self.request.user,
                    self.request.site.siteconfiguration.segment_key,
                    unicode(course_key)
                ),
            })

            # Check product attributes to determine if ID verification is required for this basket
            try:
                is_verification_required = is_verification_required or line.product.attr.id_verification_required
            except AttributeError:
                pass

        context.update({
            'free_basket': context['order_total'].incl_tax == 0,
            'payment_processors': self.request.site.siteconfiguration.get_payment_processors(),
            'homepage_url': get_lms_url(''),
            'formset_lines_data': zip(formset, lines_data),
            'is_verification_required': is_verification_required,
            'min_seat_quantity': 1,
            'is_bulk_purchase': is_bulk_purchase,
            'switch_link_text': switch_link_text,
            'partner_sku': partner_sku,
        })

        return context
Exemplo n.º 21
0
    def _process_basket_lines(self, lines):
        """Processes the basket lines and extracts information for the view's context.
        In addition determines whether:
            * verification message should be displayed
            * voucher form should be displayed
            * switch link (for switching between seat and enrollment code products) should be displayed
        and returns that information for the basket view context to be updated with it.

        Args:
            lines (list): List of basket lines.
        Returns:
            context_updates (dict): Containing information with which the context needs to
                                    be updated with.
            lines_data (list): List of information about the basket lines.
        """
        display_verification_message = False
        lines_data = []
        show_voucher_form = True
        is_enrollment_code_purchase = False
        switch_link_text = partner_sku = order_details_msg = None

        for line in lines:
            if line.product.is_seat_product or line.product.is_course_entitlement_product:
                line_data = self._get_course_data(line.product)
                certificate_type = line.product.attr.certificate_type

                if getattr(line.product.attr, 'id_verification_required',
                           False) and certificate_type != 'credit':
                    display_verification_message = True

                if line.product.is_course_entitlement_product:
                    order_details_msg = _(
                        'After you complete your order you will be able to select course dates from your dashboard.'
                    )
                else:
                    if certificate_type == 'verified':
                        order_details_msg = _(
                            'After you complete your order you will be automatically enrolled '
                            'in the verified track of the course.')
                    elif certificate_type == 'credit':
                        order_details_msg = _(
                            'After you complete your order you will receive credit for your course.'
                        )
                    else:
                        order_details_msg = _(
                            'After you complete your order you will be automatically enrolled in the course.'
                        )
            elif line.product.is_enrollment_code_product:
                line_data = self._get_course_data(line.product)
                is_enrollment_code_purchase = True
                show_voucher_form = False
                order_details_msg = _(
                    '{paragraph_start}By purchasing, you and your organization agree to the following terms:'
                    '{paragraph_end} {ul_start} {li_start}Each code is valid for the one course covered and can be '
                    'used only one time.{li_end} '
                    '{li_start}You are responsible for distributing codes to your learners in your organization.'
                    '{li_end} {li_start}Each code will expire in one year from date of purchase or, if earlier, once '
                    'the course is closed.{li_end} {li_start}If a course is not designated as self-paced, you should '
                    'confirm that a course run is available before expiration. {li_end} {li_start}You may not resell '
                    'codes to third parties.{li_end} '
                    '{li_start}All edX for Business Sales are final and not eligible for refunds.{li_end}{ul_end} '
                    '{paragraph_start}You will receive an email at {user_email} with your enrollment code(s). '
                    '{paragraph_end}').format(
                        paragraph_start='<p>',
                        paragraph_end='</p>',
                        ul_start='<ul>',
                        li_start='<li>',
                        li_end='</li>',
                        ul_end='</ul>',
                        user_email=self.request.user.email)
            else:
                line_data = {
                    'product_title': line.product.title,
                    'image_url': None,
                    'product_description': line.product.description
                }

            # Get variables for the switch link that toggles from enrollment codes and seat.
            switch_link_text, partner_sku = get_basket_switch_data(
                line.product)

            try:
                if line.has_discount:
                    benefit = self.request.basket.applied_offers().values(
                    )[0].benefit
                    benefit_value = format_benefit_value(benefit)
                else:
                    benefit_value = None
            except IndexError:
                logger.exception(
                    'Basket {%d} line{%d} has discount value {%s} ',
                    self.request.basket.id, line.id, line.discount_value)
                benefit_value = None

            product_course_id = line.product.course_id.split('+')
            line_data.update({
                'sku':
                line.product.stockrecords.first().partner_sku,
                'benefit_value':
                benefit_value,
                'enrollment_code':
                line.product.is_enrollment_code_product,
                'line':
                line,
                'seat_type':
                self._determine_product_type(line.product),
                'product_course_id':
                product_course_id[1] if len(product_course_id) > 1 else '',
            })
            lines_data.append(line_data)

        context_updates = {
            'display_verification_message': display_verification_message,
            'order_details_msg': order_details_msg,
            'partner_sku': partner_sku,
            'show_voucher_form': show_voucher_form,
            'switch_link_text': switch_link_text,
            'is_enrollment_code_purchase': is_enrollment_code_purchase
        }

        return context_updates, lines_data
Exemplo n.º 22
0
    def get_context_data(self, **kwargs):
        context = super(BasketSummaryView, self).get_context_data(**kwargs)
        formset = context.get('formset', [])
        lines = context.get('line_list', [])
        lines_data = []
        api = EdxRestApiClient(get_lms_url('api/courses/v1/'))
        is_verification_required = False
        for line in lines:
            course_key = CourseKey.from_string(line.product.attr.course_key)
            cache_key = 'courses_api_detail_{}'.format(course_key)
            cache_hash = hashlib.md5(cache_key).hexdigest()
            course_name = None
            image_url = None
            short_description = None
            try:
                course = cache.get(cache_hash)
                if not course:
                    course = api.courses(course_key).get()
                    cache.set(cache_hash, course, settings.COURSES_API_CACHE_TIMEOUT)
                image_url = get_lms_url(course['media']['course_image']['uri'])
                short_description = course['short_description']
                course_name = course['name']
            except (ConnectionError, SlumberBaseException, Timeout):
                logger.exception('Failed to retrieve data from Course API for course [%s].', course_key)

            if line.has_discount:
                benefit = self.request.basket.applied_offers().values()[0].benefit
                benefit_value = format_benefit_value(benefit)
            else:
                benefit_value = None

            lines_data.append({
                'seat_type': self._determine_seat_type(line.product),
                'course_name': course_name,
                'course_key': course_key,
                'image_url': image_url,
                'course_short_description': short_description,
                'benefit_value': benefit_value,
                'enrollment_code': line.product.get_product_class().name == ENROLLMENT_CODE_PRODUCT_CLASS_NAME,
                'line': line,
            })

            context.update({
                'analytics_data': prepare_analytics_data(
                    self.request.user,
                    self.request.site.siteconfiguration.segment_key,
                    unicode(course_key)
                ),
            })

            # Check product attributes to determine if ID verification is required for this basket
            try:
                is_verification_required = is_verification_required or line.product.attr.id_verification_required
            except AttributeError:
                pass

        context.update({
            'free_basket': context['order_total'].incl_tax == 0,
            'payment_processors': self.request.site.siteconfiguration.get_payment_processors(),
            'homepage_url': get_lms_url(''),
            'formset_lines_data': zip(formset, lines_data),
            'is_verification_required': is_verification_required,
        })
        return context