Commit 3ce7d773 by Vedran Karacic

Omit unavailable seats in offer landing page.

parent af166e02
......@@ -19,22 +19,23 @@ class CatalogPreviewMockMixin(object):
def setUp(self):
super(CatalogPreviewMockMixin, self).setUp()
def mock_dynamic_catalog_course_runs_api(self, course_run=None, query=None):
def mock_dynamic_catalog_course_runs_api(self, course_run=None, query=None, course_run_info=None):
""" Helper function to register a dynamic course catalog API endpoint for the course run information. """
course_run_info = {
'count': 1,
'results': [{
'key': course_run.id,
'title': course_run.name,
'start': '2016-05-01T00:00:00Z',
'image': {
'src': 'path/to/the/course/image'
}
}] if course_run else [{
'key': 'test',
'title': 'Test course',
}],
}
if not course_run_info:
course_run_info = {
'count': 1,
'results': [{
'key': course_run.id,
'title': course_run.name,
'start': '2016-05-01T00:00:00Z',
'image': {
'src': 'path/to/the/course/image'
}
}] if course_run else [{
'key': 'test',
'title': 'Test course',
}],
}
course_run_info_json = json.dumps(course_run_info)
course_run_url = '{}course_runs/?q={}'.format(
settings.COURSE_CATALOG_API_URL,
......
......@@ -64,7 +64,7 @@ class CouponAppViewTests(TestCase):
self.assertEqual(response.status_code, 200)
class GetVoucherTests(TestCase):
class GetVoucherTests(CourseCatalogTestMixin, TestCase):
def test_get_voucher_and_products_from_code(self):
""" Verify that get_voucher_and_products_from_code() returns products and voucher. """
original_voucher, original_product = prepare_voucher(code=COUPON_CODE)
......@@ -130,6 +130,15 @@ class GetVoucherTests(TestCase):
valid, __ = voucher_is_valid(voucher=voucher, products=[product], request=request)
self.assertFalse(valid)
def test_omitting_unavailable_voucher(self):
""" Verify if there are more than one product, that availability check is omitted. """
request = RequestFactory().request()
voucher, product = prepare_voucher(code=COUPON_CODE)
product.expires = pytz.utc.localize(datetime.datetime.min)
__, seat = self.create_course_and_seat()
valid, __ = voucher_is_valid(voucher=voucher, products=[product, seat], request=request)
self.assertTrue(valid)
def assert_error_messages(self, voucher, product, user, error_msg):
""" Assert the proper error message is returned. """
voucher.offers.first().record_usage(discount={'freq': 1, 'discount': 1})
......
......@@ -90,10 +90,10 @@ def voucher_is_valid(voucher, products, request):
voucher_msg = msg.replace('voucher', 'coupon')
return False, voucher_msg
for product in products:
purchase_info = request.strategy.fetch_for_product(product)
if len(products) == 1:
purchase_info = request.strategy.fetch_for_product(products[0])
if not purchase_info.availability.is_available_to_buy:
return False, _('Product [{product}] not available for purchase.'.format(product=product))
return False, _('Product [{product}] not available for purchase.'.format(product=products[0]))
# If the voucher's number of applications exceeds it's limit.
offer = voucher.offers.first()
......
from __future__ import unicode_literals
import datetime
import json
import mock
import ddt
import httpretty
import pytz
from django.core.urlresolvers import reverse
from django.http import Http404
from opaque_keys.edx.keys import CourseKey
......@@ -22,6 +24,7 @@ from ecommerce.courses.models import Course
from ecommerce.extensions.api import serializers
from ecommerce.extensions.api.v2.views.vouchers import VoucherViewSet
from ecommerce.extensions.catalogue.tests.mixins import CourseCatalogTestMixin
from ecommerce.extensions.partner.strategy import DefaultStrategy
from ecommerce.extensions.test.factories import prepare_voucher
from ecommerce.tests.mixins import Catalog, LmsApiMockMixin
from ecommerce.tests.testcases import TestCase
......@@ -33,7 +36,7 @@ Range = get_model('offer', 'Range')
StockRecord = get_model('partner', 'StockRecord')
class VoucherViewSetTests(TestCase):
class VoucherViewSetTests(CatalogPreviewMockMixin, CourseCatalogTestMixin, TestCase):
""" Tests for the VoucherViewSet view set. """
path = reverse('api:v2:vouchers-list')
......@@ -63,6 +66,50 @@ class VoucherViewSetTests(TestCase):
self.assertEqual(response_data['count'], 1)
self.assertEqual(response_data['results'][0]['code'], COUPON_CODE)
# NOTE (VK): This unit test is added here because it results in a segmentation fault if
# added to the test class below.
@httpretty.activate
@mock_course_catalog_api_client
def test_omitting_unavailable_seats(self):
""" Verify an unavailable seat is omitted from offer page results. """
course1, seat1 = self.create_course_and_seat()
course2, seat2 = self.create_course_and_seat()
course_run_info = {
'count': 2,
'results': [{
'key': course1.id,
'title': course1.name,
'start': '2016-05-01T00:00:00Z',
'image': {
'src': 'path/to/the/course/image'
}
}, {
'key': course2.id,
'title': course2.name,
'start': '2016-05-01T00:00:00Z',
'image': {
'src': 'path/to/the/course/image'
}
}]
}
self.mock_dynamic_catalog_course_runs_api(query='*:*', course_run_info=course_run_info)
new_range, __ = Range.objects.get_or_create(catalog_query='*:*')
new_range.add_product(seat1)
new_range.add_product(seat2)
voucher, __ = prepare_voucher(_range=new_range)
voucher, products = get_voucher_and_products_from_code(voucher.code)
factory = APIRequestFactory()
request = factory.get('/?code={}&page_size=6'.format(voucher.code))
request.site = self.site
request.strategy = DefaultStrategy()
offers = VoucherViewSet().get_offers(products=products, request=request, voucher=voucher)
self.assertEqual(len(offers), 2)
products[1].expires = pytz.utc.localize(datetime.datetime.min)
offers = VoucherViewSet().get_offers(products=products, request=request, voucher=voucher)
self.assertEqual(len(offers), 1)
@ddt.ddt
@httpretty.activate
......@@ -86,6 +133,7 @@ class VoucherViewOffersEndpointTests(
factory = APIRequestFactory()
request = factory.get('/?code={}&page_size=6'.format(code))
request.site = self.site
request.strategy = DefaultStrategy()
return request
@ddt.data(('COUPONCODE',), ('NOT_FOUND_CODE',))
......
......@@ -110,7 +110,6 @@ class VoucherViewSet(NonDestroyableModelViewSet):
benefit = voucher.offers.first().benefit
catalog_query = benefit.range.catalog_query
offers = []
if catalog_query:
query_results = request.site.siteconfiguration.course_catalog_api_client.course_runs.get(
q=catalog_query,
......@@ -124,6 +123,11 @@ class VoucherViewSet(NonDestroyableModelViewSet):
contains_verified_course = (benefit.range.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 = next((result for result in query_results if result['key'] == course_id), None)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment