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))
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))
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))
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))
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))
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))
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, }
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)
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
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
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)
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()
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
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)
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)
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)
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
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
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.'), }
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
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
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