Exemple #1
0
    def get_offers_from_catalog(self, request, voucher):
        """ Helper method for collecting offers from catalog query or enterprise catalog.

        Args:
            request (WSGIRequest): Request data.
            voucher (Voucher): Oscar Voucher for which the offers are returned.

        Returns:
            A list of dictionaries with retrieved offers and a link to the next
            page of the Course Discovery results.
            """
        benefit = voucher.best_offer.benefit
        condition = voucher.best_offer.condition

        # Pull all catalog related data from the offer.
        catalog_query = benefit.range.catalog_query if benefit.range else None
        catalog_id = benefit.range.course_catalog if benefit.range else None
        enterprise_customer = (condition.enterprise_customer_uuid
                               or (benefit.range
                                   and benefit.range.enterprise_customer))
        enterprise_catalog = (condition.enterprise_customer_catalog_uuid or
                              (benefit.range
                               and benefit.range.enterprise_customer_catalog))

        if catalog_id:
            catalog = fetch_course_catalog(request.site, catalog_id)
            catalog_query = catalog.get("query") if catalog else catalog_query

        # There is no catalog related data specified for this condition, so return None.
        if not catalog_query and not enterprise_customer:
            return None, None

        if enterprise_catalog:
            response = get_enterprise_catalog(
                site=request.site,
                enterprise_catalog=enterprise_catalog,
                limit=request.GET.get('limit', DEFAULT_CATALOG_PAGE_SIZE),
                page=request.GET.get('page'),
            )
        elif catalog_query:
            response = get_catalog_course_runs(
                site=request.site,
                query=catalog_query,
                limit=request.GET.get('limit', DEFAULT_CATALOG_PAGE_SIZE),
                offset=request.GET.get('offset'),
            )
        else:
            logger.warning(
                'User is trying to redeem Voucher %s, but no catalog information is configured!',
                voucher.code)
            return [], None

        next_page = response['next']
        offers = self.convert_catalog_response_to_offers(
            request, voucher, response)

        return offers, next_page
    def preview(self, request):
        """ Preview the results of the catalog query.

        A list of course runs, indicating a course run presence within the catalog, will be returned.
        ---
        parameters:
            - name: query
              description: Elasticsearch querystring query
              required: true
              type: string
              paramType: query
              multiple: false
        """
        query = request.GET.get('query')
        seat_types = request.GET.get('seat_types')
        offset = request.GET.get('offset')
        limit = request.GET.get('limit', DEFAULT_CATALOG_PAGE_SIZE)

        if not (query and seat_types):
            detail = {}

            if not query:
                detail['query'] = 'The query parameter is required.'

            if not seat_types:
                detail['seat_types'] = 'The seat_type parameter is required.'

            raise ValidationError(detail=detail)

        seat_types = seat_types.split(',')

        try:
            response = get_catalog_course_runs(
                site=request.site,
                query=query,
                limit=limit,
                offset=offset
            )
            results = response['results']
            course_ids = [result['key'] for result in results]
            seats = serializers.ProductSerializer(
                Product.objects.filter(
                    course_id__in=course_ids,
                    attributes__name='certificate_type',
                    attribute_values__value_text__in=seat_types
                ),
                many=True,
                context={'request': request}
            ).data
            data = {
                'next': response['next'],
                'seats': seats
            }
            return Response(data=data)
        except (ConnectionError, SlumberBaseException, Timeout):
            logger.error('Unable to connect to Catalog API.')
            return Response(status=status.HTTP_400_BAD_REQUEST)
Exemple #3
0
def get_course_ids_from_voucher(site, voucher):
    """
    Get site base list of course run keys from the provided voucher object.

    Arguments:
        site: (django.contrib.sites.Site) site instance
        voucher (Voucher): voucher class object

    Returns:
        list of course ids

    """
    voucher_offer = voucher.offers.first()
    offer_range = voucher_offer.condition.range
    if offer_range.course_catalog:
        try:
            course_catalog = get_course_catalogs(site=site, resource_id=offer_range.course_catalog)
        except (ConnectionError, SlumberBaseException, Timeout):
            logger.error('Unable to connect to Course Catalog service for course catalogs.')
            return None

        try:
            course_runs = get_catalog_course_runs(site, course_catalog.get('query'))['results']
        except (ConnectionError, SlumberBaseException, Timeout, KeyError):
            logger.error('Unable to get course runs from Course Catalog service.')
            return None

        voucher_course_ids = [course_run.get('key') for course_run in course_runs if course_run.get('key')]
    elif offer_range.catalog_query:
        try:
            course_runs = get_catalog_course_runs(site, offer_range.catalog_query)['results']
        except (ConnectionError, SlumberBaseException, Timeout, KeyError):
            logger.error('Unable to get course runs from Course Catalog service.')
            return None

        voucher_course_ids = [course_run.get('key') for course_run in course_runs if course_run.get('key')]
    else:
        stock_records = offer_range.catalog.stock_records.all()
        seats = Product.objects.filter(id__in=[sr.product.id for sr in stock_records])
        voucher_course_ids = [seat.course_id for seat in seats]

    return voucher_course_ids
Exemple #4
0
    def preview(self, request):
        """
        Preview the results of the catalog query.
        A list of course runs, indicating a course run presence within the catalog, will be returned.
        ---
        parameters:
            - name: query
              description: Elasticsearch querystring query
              required: true
              type: string
              paramType: query
              multiple: false
        """
        query = request.GET.get('query')
        seat_types = request.GET.get('seat_types')
        offset = request.GET.get('offset')
        limit = request.GET.get('limit', DEFAULT_CATALOG_PAGE_SIZE)

        if query and seat_types:
            seat_types = seat_types.split(',')
            try:
                response = get_catalog_course_runs(
                    site=request.site,
                    query=query,
                    limit=limit,
                    offset=offset
                )
                results = response['results']
                course_ids = [result['key'] for result in results]
                seats = serializers.ProductSerializer(
                    Product.objects.filter(
                        course_id__in=course_ids,
                        attributes__name='certificate_type',
                        attribute_values__value_text__in=seat_types
                    ),
                    many=True,
                    context={'request': request}
                ).data
                data = {
                    'next': response['next'],
                    'seats': seats
                }
                return Response(data=data)
            except (ConnectionError, SlumberBaseException, Timeout):
                logger.error('Unable to connect to Course Catalog service.')
                return Response(status=status.HTTP_400_BAD_REQUEST)
        return Response(status=status.HTTP_400_BAD_REQUEST)
Exemple #5
0
    def get_offers_from_catalog(self, request, voucher, catalog_query,
                                enterprise_catalog):
        """ Helper method for collecting offers from catalog query or enterprise catalog.

        Args:
            request (WSGIRequest): Request data.
            voucher (Voucher): Oscar Voucher for which the offers are returned.
            catalog_query (str): The query for the Course Discovery.

        Returns:
            A list of dictionaries with retrieved offers and a link to the next
            page of the Course Discovery results.
            """
        offers = []
        benefit = voucher.offers.first().benefit
        course_seat_types = benefit.range.course_seat_types
        multiple_credit_providers = False
        credit_provider_price = None
        response = {}

        if enterprise_catalog:
            response = get_enterprise_catalog(
                site=request.site,
                enterprise_catalog=enterprise_catalog,
                limit=request.GET.get('limit', DEFAULT_CATALOG_PAGE_SIZE),
                page=request.GET.get('page'),
            )
        elif catalog_query:
            response = get_catalog_course_runs(
                site=request.site,
                query=catalog_query,
                limit=request.GET.get('limit', DEFAULT_CATALOG_PAGE_SIZE),
                offset=request.GET.get('offset'),
            )

        next_page = response['next']
        products, stock_records, course_run_metadata = self.retrieve_course_objects(
            response['results'], course_seat_types)
        contains_verified_course = (course_seat_types == 'verified')
        for product in products:
            # Omit unavailable seats from the offer results so that one seat does not cause an
            # error message for every seat in the query result.
            if not request.strategy.fetch_for_product(
                    product).availability.is_available_to_buy:
                logger.info(
                    '%s is unavailable to buy. Omitting it from the results.',
                    product)
                continue

            course_id = product.course_id
            course_catalog_data = course_run_metadata[course_id]
            if course_seat_types == 'credit':
                # Omit credit seats for which the user is not eligible or which the user already bought.
                if request.user.is_eligible_for_credit(product.course_id):
                    if Order.objects.filter(user=request.user,
                                            lines__product=product).exists():
                        continue
                else:
                    continue
                credit_seats = Product.objects.filter(
                    parent=product.parent, attributes__name='credit_provider')

                if credit_seats.count() > 1:
                    multiple_credit_providers = True
                    credit_provider_price = None
                else:
                    multiple_credit_providers = False
                    credit_provider_price = StockRecord.objects.get(
                        product=product).price_excl_tax

            try:
                stock_record = stock_records.get(product__id=product.id)
            except StockRecord.DoesNotExist:
                stock_record = None
                logger.error('Stock Record for product %s not found.',
                             product.id)

            try:
                course = Course.objects.get(id=course_id)
            except Course.DoesNotExist:  # pragma: no cover
                course = None
                logger.error('Course %s not found.', course_id)

            if course_catalog_data and course and stock_record:
                offers.append(
                    self.get_course_offer_data(
                        benefit=benefit,
                        course=course,
                        course_info=course_catalog_data,
                        credit_provider_price=credit_provider_price,
                        multiple_credit_providers=multiple_credit_providers,
                        is_verified=contains_verified_course,
                        product=product,
                        stock_record=stock_record,
                        voucher=voucher))

        return offers, next_page