Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
ecommerce
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
ecommerce
Commits
c9f1d6d0
Commit
c9f1d6d0
authored
Jan 13, 2017
by
Zubair Afzal
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Revert "ENT-110: Add Catalog selection option to Coupon create/edit form"
parent
104f6147
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
35 changed files
with
42 additions
and
873 deletions
+42
-873
ecommerce/coupons/tests/mixins.py
+1
-8
ecommerce/courses/tests/mixins.py
+0
-143
ecommerce/courses/tests/test_utils.py
+3
-110
ecommerce/courses/utils.py
+0
-62
ecommerce/extensions/api/serializers.py
+1
-5
ecommerce/extensions/api/v2/tests/views/test_catalog.py
+1
-58
ecommerce/extensions/api/v2/tests/views/test_coupons.py
+1
-3
ecommerce/extensions/api/v2/views/catalog.py
+0
-18
ecommerce/extensions/api/v2/views/coupons.py
+0
-0
ecommerce/extensions/catalogue/tests/test_utils.py
+0
-1
ecommerce/extensions/catalogue/utils.py
+1
-4
ecommerce/extensions/offer/admin.py
+1
-2
ecommerce/extensions/offer/migrations/0008_range_course_catalog.py
+0
-19
ecommerce/extensions/offer/models.py
+0
-6
ecommerce/extensions/voucher/models.py
+0
-8
ecommerce/extensions/voucher/tests/test_utils.py
+0
-40
ecommerce/extensions/voucher/utils.py
+15
-25
ecommerce/static/js/apps/coupon_admin_app.js
+0
-6
ecommerce/static/js/collections/catalog_collection.js
+0
-15
ecommerce/static/js/models/catalog_model.js
+0
-11
ecommerce/static/js/models/coupon_model.js
+11
-47
ecommerce/static/js/test/mock_data/catalogs.js
+0
-36
ecommerce/static/js/test/mock_data/coupons.js
+0
-1
ecommerce/static/js/test/mock_data/selected_catalogs.js
+0
-17
ecommerce/static/js/test/spec-runner.js
+0
-2
ecommerce/static/js/test/spec-utils.js
+1
-7
ecommerce/static/js/test/specs/collections/catalog_collection_spec.js
+0
-29
ecommerce/static/js/test/specs/models/coupon_model_spec.js
+0
-50
ecommerce/static/js/test/specs/utils/utils_spec.js
+1
-4
ecommerce/static/js/test/specs/views/coupon_create_view_spec.js
+1
-4
ecommerce/static/js/test/specs/views/coupon_form_view_spec.js
+2
-51
ecommerce/static/js/views/coupon_detail_view.js
+0
-11
ecommerce/static/js/views/coupon_form_view.js
+2
-57
ecommerce/static/templates/coupon_detail.html
+0
-6
ecommerce/static/templates/coupon_form.html
+0
-7
No files found.
ecommerce/coupons/tests/mixins.py
View file @
c9f1d6d0
...
@@ -149,7 +149,7 @@ class CouponMixin(object):
...
@@ -149,7 +149,7 @@ class CouponMixin(object):
def
create_coupon
(
self
,
benefit_type
=
Benefit
.
PERCENTAGE
,
benefit_value
=
100
,
catalog
=
None
,
def
create_coupon
(
self
,
benefit_type
=
Benefit
.
PERCENTAGE
,
benefit_value
=
100
,
catalog
=
None
,
catalog_query
=
None
,
client
=
None
,
code
=
''
,
course_seat_types
=
None
,
email_domains
=
None
,
catalog_query
=
None
,
client
=
None
,
code
=
''
,
course_seat_types
=
None
,
email_domains
=
None
,
max_uses
=
None
,
note
=
None
,
partner
=
None
,
price
=
100
,
quantity
=
5
,
title
=
'Test coupon'
,
max_uses
=
None
,
note
=
None
,
partner
=
None
,
price
=
100
,
quantity
=
5
,
title
=
'Test coupon'
,
voucher_type
=
Voucher
.
SINGLE_USE
,
course_catalog
=
None
):
voucher_type
=
Voucher
.
SINGLE_USE
):
"""Helper method for creating a coupon.
"""Helper method for creating a coupon.
Arguments:
Arguments:
...
@@ -157,18 +157,12 @@ class CouponMixin(object):
...
@@ -157,18 +157,12 @@ class CouponMixin(object):
benefit_value(int): The voucher benefit value
benefit_value(int): The voucher benefit value
catalog(Catalog): Catalog of courses for which the coupon applies
catalog(Catalog): Catalog of courses for which the coupon applies
catalog_query(str): Course query string
catalog_query(str): Course query string
client (BusinessClient): Optional business client object
code(str): Custom coupon code
code(str): Custom coupon code
course_catalog (int): Course catalog id from Catalog Service
course_seat_types(str): A string of comma-separated list of seat types
course_seat_types(str): A string of comma-separated list of seat types
email_domains(str): A comma seperated list of email domains
email_domains(str): A comma seperated list of email domains
max_uses (int): Number of Voucher max uses
note (str): Coupon note.
partner(Partner): Partner used for creating a catalog
partner(Partner): Partner used for creating a catalog
price(int): Price of the coupon
price(int): Price of the coupon
quantity (int): Number of vouchers to be created and associated with the coupon
title(str): Title of the coupon
title(str): Title of the coupon
voucher_type (str): Voucher type
Returns:
Returns:
coupon (Coupon)
coupon (Coupon)
...
@@ -190,7 +184,6 @@ class CouponMixin(object):
...
@@ -190,7 +184,6 @@ class CouponMixin(object):
catalog_query
=
catalog_query
,
catalog_query
=
catalog_query
,
category
=
self
.
category
,
category
=
self
.
category
,
code
=
code
,
code
=
code
,
course_catalog
=
course_catalog
,
course_seat_types
=
course_seat_types
,
course_seat_types
=
course_seat_types
,
email_domains
=
email_domains
,
email_domains
=
email_domains
,
end_datetime
=
datetime
.
datetime
(
2020
,
1
,
1
),
end_datetime
=
datetime
.
datetime
(
2020
,
1
,
1
),
...
...
ecommerce/courses/tests/mixins.py
deleted
100644 → 0
View file @
104f6147
import
json
import
httpretty
from
django.conf
import
settings
from
django.core.cache
import
cache
class
CourseCatalogServiceMockMixin
(
object
):
"""
Mocks for the Open edX service 'Course Catalog Service' responses.
"""
COURSE_DISCOVERY_CATALOGS_URL
=
'{}catalogs/'
.
format
(
settings
.
COURSE_CATALOG_API_URL
,
)
def
setUp
(
self
):
super
(
CourseCatalogServiceMockMixin
,
self
)
.
setUp
()
cache
.
clear
()
def
mock_course_discovery_api_for_catalog_by_resource_id
(
self
):
"""
Helper function to register course catalog API endpoint for a
single catalog with its resource id.
"""
catalog_id
=
1
course_discovery_api_response
=
{
'count'
:
1
,
'next'
:
None
,
'previous'
:
None
,
'results'
:
[
{
'id'
:
catalog_id
,
'name'
:
'Catalog {}'
.
format
(
catalog_id
),
'query'
:
'title: *'
,
'courses_count'
:
0
,
'viewers'
:
[]
}
]
}
course_discovery_api_response_json
=
json
.
dumps
(
course_discovery_api_response
)
single_catalog_uri
=
'{}{}/'
.
format
(
self
.
COURSE_DISCOVERY_CATALOGS_URL
,
catalog_id
)
httpretty
.
register_uri
(
method
=
httpretty
.
GET
,
uri
=
single_catalog_uri
,
body
=
course_discovery_api_response_json
,
content_type
=
'application/json'
)
def
mock_course_discovery_api_for_catalogs
(
self
,
catalog_name_list
):
"""
Helper function to register course catalog API endpoint for a
single catalog or multiple catalogs response.
"""
mocked_results
=
[]
for
catalog_index
,
catalog_name
in
enumerate
(
catalog_name_list
):
catalog_id
=
catalog_index
+
1
mocked_results
.
append
(
{
'id'
:
catalog_id
,
'name'
:
catalog_name
,
'query'
:
'title: *'
,
'courses_count'
:
0
,
'viewers'
:
[]
}
)
course_discovery_api_response
=
{
'count'
:
len
(
catalog_name_list
),
'next'
:
None
,
'previous'
:
None
,
'results'
:
mocked_results
}
course_discovery_api_response_json
=
json
.
dumps
(
course_discovery_api_response
)
httpretty
.
register_uri
(
method
=
httpretty
.
GET
,
uri
=
self
.
COURSE_DISCOVERY_CATALOGS_URL
,
body
=
course_discovery_api_response_json
,
content_type
=
'application/json'
)
def
mock_course_discovery_api_for_paginated_catalogs
(
self
,
catalog_name_list
):
"""
Helper function to register course catalog API endpoint for multiple
catalogs with paginated response.
"""
mocked_api_responses
=
[]
for
catalog_index
,
catalog_name
in
enumerate
(
catalog_name_list
):
catalog_id
=
catalog_index
+
1
mocked_result
=
{
'id'
:
catalog_id
,
'name'
:
catalog_name
,
'query'
:
'title: *'
,
'courses_count'
:
0
,
'viewers'
:
[]
}
next_page_url
=
None
if
catalog_id
<
len
(
catalog_name_list
):
# Not a last page so there will be more catalogs for another page
next_page_url
=
'{}?limit=1&offset={}'
.
format
(
self
.
COURSE_DISCOVERY_CATALOGS_URL
,
catalog_id
)
previous_page_url
=
None
if
catalog_index
!=
0
:
# Not a first page so there will always be catalogs on previous page
previous_page_url
=
'{}?limit=1&offset={}'
.
format
(
self
.
COURSE_DISCOVERY_CATALOGS_URL
,
catalog_index
)
course_discovery_api_paginated_response
=
{
'count'
:
len
(
catalog_name_list
),
'next'
:
next_page_url
,
'previous'
:
previous_page_url
,
'results'
:
[
mocked_result
]
}
course_discovery_api_paginated_response_json
=
json
.
dumps
(
course_discovery_api_paginated_response
)
mocked_api_responses
.
append
(
httpretty
.
Response
(
body
=
course_discovery_api_paginated_response_json
,
content_type
=
'application/json'
)
)
httpretty
.
register_uri
(
method
=
httpretty
.
GET
,
uri
=
self
.
COURSE_DISCOVERY_CATALOGS_URL
,
responses
=
mocked_api_responses
)
def
mock_course_discovery_api_for_failure
(
self
):
"""
Helper function to register course catalog API endpoint for a
failure.
"""
httpretty
.
register_uri
(
method
=
httpretty
.
GET
,
uri
=
self
.
COURSE_DISCOVERY_CATALOGS_URL
,
responses
=
[
httpretty
.
Response
(
body
=
'Clunk'
,
content_type
=
'application/json'
,
status_code
=
500
)
]
)
ecommerce/courses/tests/test_utils.py
View file @
c9f1d6d0
import
hashlib
import
hashlib
import
ddt
import
ddt
from
django.core.cache
import
cache
import
httpretty
import
httpretty
from
django.core.cache
import
cache
from
ecommerce.core.constants
import
ENROLLMENT_CODE_SWITCH
from
ecommerce.core.constants
import
ENROLLMENT_CODE_SWITCH
from
ecommerce.core.tests
import
toggle_switch
from
ecommerce.core.tests
import
toggle_switch
from
ecommerce.core.tests.decorators
import
mock_course_catalog_api_client
from
ecommerce.core.tests.decorators
import
mock_course_catalog_api_client
from
ecommerce.coupons.tests.mixins
import
CourseCatalogMockMixin
from
ecommerce.coupons.tests.mixins
import
CourseCatalogMockMixin
from
ecommerce.courses.models
import
Course
from
ecommerce.courses.models
import
Course
from
ecommerce.courses.tests.factories
import
CourseFactory
from
ecommerce.courses.tests.factories
import
CourseFactory
from
ecommerce.courses.tests.mixins
import
CourseCatalogServiceMockMixin
from
ecommerce.courses.utils
import
(
from
ecommerce.courses.utils
import
(
get_certificate_type_display_value
,
get_course_info_from_catalog
,
mode_for_seat
,
get_course_catalogs
get_certificate_type_display_value
,
get_course_info_from_catalog
,
mode_for_seat
)
)
from
ecommerce.extensions.catalogue.tests.mixins
import
CourseCatalogTestMixin
from
ecommerce.extensions.catalogue.tests.mixins
import
CourseCatalogTestMixin
from
ecommerce.tests.testcases
import
TestCase
from
ecommerce.tests.testcases
import
TestCase
...
@@ -74,110 +74,3 @@ class UtilsTests(CourseCatalogTestMixin, CourseCatalogMockMixin, TestCase):
...
@@ -74,110 +74,3 @@ class UtilsTests(CourseCatalogTestMixin, CourseCatalogMockMixin, TestCase):
def
test_cert_display_assertion
(
self
):
def
test_cert_display_assertion
(
self
):
""" Verify assertion for invalid cert type """
""" Verify assertion for invalid cert type """
self
.
assertRaises
(
ValueError
,
lambda
:
get_certificate_type_display_value
(
'junk'
))
self
.
assertRaises
(
ValueError
,
lambda
:
get_certificate_type_display_value
(
'junk'
))
@ddt.ddt
@httpretty.activate
class
GetCourseCatalogUtilTests
(
CourseCatalogServiceMockMixin
,
TestCase
):
def
tearDown
(
self
):
# Reset HTTPretty state (clean up registered urls and request history)
httpretty
.
reset
()
def
_assert_num_requests
(
self
,
count
):
"""
DRY helper for verifying request counts.
"""
self
.
assertEqual
(
len
(
httpretty
.
httpretty
.
latest_requests
),
count
)
def
_assert_get_course_catalogs
(
self
,
catalog_name_list
):
"""
Helper method to validate the response from the method
"get_course_catalogs".
"""
cache_key
=
'{}.catalog.api.data'
.
format
(
self
.
request
.
site
.
domain
)
cache_key
=
hashlib
.
md5
(
cache_key
)
.
hexdigest
()
cached_course_catalogs
=
cache
.
get
(
cache_key
)
self
.
assertIsNone
(
cached_course_catalogs
)
response
=
get_course_catalogs
(
self
.
request
.
site
)
self
.
assertEqual
(
len
(
response
),
len
(
catalog_name_list
))
for
catalog_index
,
catalog
in
enumerate
(
response
):
self
.
assertEqual
(
catalog
[
'name'
],
catalog_name_list
[
catalog_index
])
cached_course
=
cache
.
get
(
cache_key
)
self
.
assertEqual
(
cached_course
,
response
)
@mock_course_catalog_api_client
def
test_get_course_catalogs_for_single_catalog_with_id
(
self
):
"""
Verify that method "get_course_catalogs" returns proper response for a
single catalog by its id.
"""
self
.
mock_course_discovery_api_for_catalog_by_resource_id
()
catalog_id
=
1
cache_key
=
'{}.catalog.api.data.{}'
.
format
(
self
.
request
.
site
.
domain
,
catalog_id
)
cache_key
=
hashlib
.
md5
(
cache_key
)
.
hexdigest
()
cached_course_catalog
=
cache
.
get
(
cache_key
)
self
.
assertIsNone
(
cached_course_catalog
)
response
=
get_course_catalogs
(
self
.
request
.
site
,
catalog_id
)
self
.
assertEqual
(
response
[
'count'
],
1
)
self
.
assertEqual
(
response
[
'results'
][
0
][
'name'
],
'Catalog {}'
.
format
(
catalog_id
))
cached_course
=
cache
.
get
(
cache_key
)
self
.
assertEqual
(
cached_course
,
response
)
# Verify the API was actually hit (not the cache)
self
.
_assert_num_requests
(
1
)
@mock_course_catalog_api_client
@ddt.data
(
[
'Catalog 1'
],
[
'Catalog 1'
,
'Catalog 2'
],
)
def
test_get_course_catalogs_for_single_page_api_response
(
self
,
catalog_name_list
):
"""
Verify that method "get_course_catalogs" returns proper response for
single page Course Discovery API response and uses cache to return data
in case of same API request.
"""
self
.
mock_course_discovery_api_for_catalogs
(
catalog_name_list
)
self
.
_assert_get_course_catalogs
(
catalog_name_list
)
# Verify the API was hit once
self
.
_assert_num_requests
(
1
)
# Now fetch the catalogs again and there should be no more actual call
# to Course Discovery API as the data will be fetched from the cache
get_course_catalogs
(
self
.
request
.
site
)
self
.
_assert_num_requests
(
1
)
@mock_course_catalog_api_client
def
test_get_course_catalogs_for_paginated_api_response
(
self
):
"""
Verify that method "get_course_catalogs" returns all catalogs for
paginated Course Discovery API response for multiple catalogs.
"""
catalog_name_list
=
[
'Catalog 1'
,
'Catalog 2'
,
'Catalog 3'
]
self
.
mock_course_discovery_api_for_paginated_catalogs
(
catalog_name_list
)
self
.
_assert_get_course_catalogs
(
catalog_name_list
)
# Verify the API was hit for each catalog page
self
.
_assert_num_requests
(
len
(
catalog_name_list
))
@mock_course_catalog_api_client
def
test_get_course_catalogs_for_failure
(
self
):
"""
Verify that method "get_course_catalogs" raises exception in case
the Course Discovery API fails to return data.
"""
self
.
mock_course_discovery_api_for_failure
()
with
self
.
assertRaises
(
Exception
):
get_course_catalogs
(
self
.
request
.
site
)
ecommerce/courses/utils.py
View file @
c9f1d6d0
import
hashlib
import
hashlib
from
urlparse
import
parse_qs
,
urlparse
from
django.conf
import
settings
from
django.conf
import
settings
from
django.core.cache
import
cache
from
django.core.cache
import
cache
...
@@ -34,67 +33,6 @@ def get_course_info_from_catalog(site, course_key):
...
@@ -34,67 +33,6 @@ def get_course_info_from_catalog(site, course_key):
return
course_run
return
course_run
def
get_course_catalogs
(
site
,
resource_id
=
None
):
"""
Get details related to course catalogs from Catalog Service.
Arguments:
site (Site): Site object containing Site Configuration data
resource_id (int or str): Identifies a specific resource to be retrieved
Returns:
dict: Course catalogs received from Course Catalog API
"""
resource
=
'catalogs'
base_cache_key
=
'{}.catalog.api.data'
.
format
(
site
.
domain
)
cache_key
=
'{}.{}'
.
format
(
base_cache_key
,
resource_id
)
if
resource_id
else
base_cache_key
cache_key
=
hashlib
.
md5
(
cache_key
)
.
hexdigest
()
cached
=
cache
.
get
(
cache_key
)
if
cached
:
return
cached
api
=
site
.
siteconfiguration
.
course_catalog_api_client
endpoint
=
getattr
(
api
,
resource
)
response
=
endpoint
(
resource_id
)
.
get
()
if
resource_id
:
results
=
response
else
:
results
=
traverse_pagination
(
response
,
endpoint
)
cache
.
set
(
cache_key
,
results
,
settings
.
COURSES_API_CACHE_TIMEOUT
)
return
results
def
traverse_pagination
(
response
,
endpoint
):
"""
Traverse a paginated API response.
Extracts and concatenates "results" (list of dict) returned by DRF-powered
APIs.
Arguments:
response (Dict): Current response dict from service API
endpoint (slumber Resource object): slumber Resource object from edx-rest-api-client
Returns:
list of dict.
"""
results
=
response
.
get
(
'results'
,
[])
next_page
=
response
.
get
(
'next'
)
while
next_page
:
querystring
=
parse_qs
(
urlparse
(
next_page
)
.
query
,
keep_blank_values
=
True
)
response
=
endpoint
.
get
(
**
querystring
)
results
+=
response
.
get
(
'results'
,
[])
next_page
=
response
.
get
(
'next'
)
return
results
def
get_certificate_type_display_value
(
certificate_type
):
def
get_certificate_type_display_value
(
certificate_type
):
display_values
=
{
display_values
=
{
'audit'
:
_
(
'Audit'
),
'audit'
:
_
(
'Audit'
),
...
...
ecommerce/extensions/api/serializers.py
View file @
c9f1d6d0
...
@@ -531,7 +531,6 @@ class CouponSerializer(ProductPaymentInfoMixin, serializers.ModelSerializer):
...
@@ -531,7 +531,6 @@ class CouponSerializer(ProductPaymentInfoMixin, serializers.ModelSerializer):
benefit_type
=
serializers
.
SerializerMethodField
()
benefit_type
=
serializers
.
SerializerMethodField
()
benefit_value
=
serializers
.
SerializerMethodField
()
benefit_value
=
serializers
.
SerializerMethodField
()
catalog_query
=
serializers
.
SerializerMethodField
()
catalog_query
=
serializers
.
SerializerMethodField
()
course_catalog
=
serializers
.
SerializerMethodField
()
category
=
serializers
.
SerializerMethodField
()
category
=
serializers
.
SerializerMethodField
()
client
=
serializers
.
SerializerMethodField
()
client
=
serializers
.
SerializerMethodField
()
code
=
serializers
.
SerializerMethodField
()
code
=
serializers
.
SerializerMethodField
()
...
@@ -559,9 +558,6 @@ class CouponSerializer(ProductPaymentInfoMixin, serializers.ModelSerializer):
...
@@ -559,9 +558,6 @@ class CouponSerializer(ProductPaymentInfoMixin, serializers.ModelSerializer):
def
get_catalog_query
(
self
,
obj
):
def
get_catalog_query
(
self
,
obj
):
return
retrieve_offer
(
obj
)
.
condition
.
range
.
catalog_query
return
retrieve_offer
(
obj
)
.
condition
.
range
.
catalog_query
def
get_course_catalog
(
self
,
obj
):
return
retrieve_offer
(
obj
)
.
condition
.
range
.
course_catalog
def
get_category
(
self
,
obj
):
def
get_category
(
self
,
obj
):
category
=
ProductCategory
.
objects
.
filter
(
product
=
obj
)
.
first
()
.
category
category
=
ProductCategory
.
objects
.
filter
(
product
=
obj
)
.
first
()
.
category
return
CategorySerializer
(
category
)
.
data
return
CategorySerializer
(
category
)
.
data
...
@@ -649,7 +645,7 @@ class CouponSerializer(ProductPaymentInfoMixin, serializers.ModelSerializer):
...
@@ -649,7 +645,7 @@ class CouponSerializer(ProductPaymentInfoMixin, serializers.ModelSerializer):
class
Meta
(
object
):
class
Meta
(
object
):
model
=
Product
model
=
Product
fields
=
(
fields
=
(
'benefit_type'
,
'benefit_value'
,
'catalog_query'
,
'c
ourse_catalog'
,
'c
ategory'
,
'benefit_type'
,
'benefit_value'
,
'catalog_query'
,
'category'
,
'client'
,
'code'
,
'code_status'
,
'coupon_type'
,
'course_seat_types'
,
'client'
,
'code'
,
'code_status'
,
'coupon_type'
,
'course_seat_types'
,
'email_domains'
,
'end_date'
,
'id'
,
'last_edited'
,
'max_uses'
,
'email_domains'
,
'end_date'
,
'id'
,
'last_edited'
,
'max_uses'
,
'note'
,
'num_uses'
,
'payment_information'
,
'price'
,
'quantity'
,
'note'
,
'num_uses'
,
'payment_information'
,
'price'
,
'quantity'
,
...
...
ecommerce/extensions/api/v2/tests/views/test_catalog.py
View file @
c9f1d6d0
...
@@ -5,28 +5,25 @@ import httpretty
...
@@ -5,28 +5,25 @@ import httpretty
from
django.conf
import
settings
from
django.conf
import
settings
from
django.core.urlresolvers
import
reverse
from
django.core.urlresolvers
import
reverse
from
django.test
import
RequestFactory
from
django.test
import
RequestFactory
import
mock
from
oscar.core.loading
import
get_model
from
oscar.core.loading
import
get_model
from
requests.exceptions
import
ConnectionError
,
Timeout
from
requests.exceptions
import
ConnectionError
,
Timeout
from
slumber.exceptions
import
SlumberBaseException
from
slumber.exceptions
import
SlumberBaseException
from
ecommerce.core.tests.decorators
import
mock_course_catalog_api_client
from
ecommerce.core.tests.decorators
import
mock_course_catalog_api_client
from
ecommerce.coupons.tests.mixins
import
CourseCatalogMockMixin
from
ecommerce.coupons.tests.mixins
import
CourseCatalogMockMixin
from
ecommerce.courses.tests.mixins
import
CourseCatalogServiceMockMixin
from
ecommerce.extensions.api.serializers
import
ProductSerializer
from
ecommerce.extensions.api.serializers
import
ProductSerializer
from
ecommerce.extensions.api.v2.tests.views.mixins
import
CatalogMixin
from
ecommerce.extensions.api.v2.tests.views.mixins
import
CatalogMixin
from
ecommerce.extensions.api.v2.views.catalog
import
CatalogViewSet
from
ecommerce.extensions.api.v2.views.catalog
import
CatalogViewSet
from
ecommerce.tests.mixins
import
ApiMockMixin
from
ecommerce.tests.mixins
import
ApiMockMixin
from
ecommerce.tests.testcases
import
TestCase
from
ecommerce.tests.testcases
import
TestCase
Catalog
=
get_model
(
'catalogue'
,
'Catalog'
)
Catalog
=
get_model
(
'catalogue'
,
'Catalog'
)
StockRecord
=
get_model
(
'partner'
,
'StockRecord'
)
StockRecord
=
get_model
(
'partner'
,
'StockRecord'
)
@httpretty.activate
@httpretty.activate
@ddt.ddt
@ddt.ddt
class
CatalogViewSetTest
(
CatalogMixin
,
CourseCatalogMockMixin
,
CourseCatalogServiceMockMixin
,
ApiMockMixin
,
TestCase
):
class
CatalogViewSetTest
(
CatalogMixin
,
CourseCatalogMockMixin
,
ApiMockMixin
,
TestCase
):
"""Test the Catalog and related products APIs."""
"""Test the Catalog and related products APIs."""
catalog_list_path
=
reverse
(
'api:v2:catalog-list'
)
catalog_list_path
=
reverse
(
'api:v2:catalog-list'
)
...
@@ -133,60 +130,6 @@ class CatalogViewSetTest(CatalogMixin, CourseCatalogMockMixin, CourseCatalogServ
...
@@ -133,60 +130,6 @@ class CatalogViewSetTest(CatalogMixin, CourseCatalogMockMixin, CourseCatalogServ
response
=
CatalogViewSet
()
.
preview
(
request
)
response
=
CatalogViewSet
()
.
preview
(
request
)
self
.
assertEqual
(
response
.
status_code
,
400
)
self
.
assertEqual
(
response
.
status_code
,
400
)
@ddt.data
(
(
'/api/v2/coupons/course_catalogs/'
,
[
'Catalog 1'
],
[
'Catalog 1'
]
),
(
'/api/v2/coupons/course_catalogs/'
,
[
'Clean Catalog'
,
'ABC Catalog'
,
'New Catalog'
,
'Edx Catalog'
],
[
'ABC Catalog'
,
'Clean Catalog'
,
'Edx Catalog'
,
'New Catalog'
]
),
)
@ddt.unpack
@mock_course_catalog_api_client
def
test_course_catalogs_for_single_page_api_response
(
self
,
url
,
catalog_name_list
,
sorted_catalog_name_list
):
"""
Test course catalogs list view "course_catalogs" for valid response
with catalogs in alphabetical order.
"""
self
.
mock_course_discovery_api_for_catalogs
(
catalog_name_list
)
request
=
self
.
prepare_request
(
url
)
response
=
CatalogViewSet
()
.
course_catalogs
(
request
)
self
.
assertEqual
(
response
.
status_code
,
200
)
# Validate that the catalogs are sorted by name in alphabetical order
self
.
_assert_get_course_catalogs_response_with_order
(
response
,
sorted_catalog_name_list
)
def
_assert_get_course_catalogs_response_with_order
(
self
,
response
,
catalog_name_list
):
"""
Helper method to validate the response from the method
"course_catalogs".
"""
response_results
=
response
.
data
.
get
(
'results'
)
self
.
assertEqual
(
len
(
response_results
),
len
(
catalog_name_list
))
for
catalog_index
,
catalog
in
enumerate
(
response_results
):
self
.
assertEqual
(
catalog
[
'name'
],
catalog_name_list
[
catalog_index
])
@mock_course_catalog_api_client
@mock.patch
(
'ecommerce.extensions.api.v2.views.catalog.logger.exception'
)
def
test_get_course_catalogs_for_failure
(
self
,
mock_exception
):
"""
Verify that the course catalogs list view "course_catalogs" returns
empty results list in case the Course Discovery API fails to return
data.
"""
self
.
mock_course_discovery_api_for_failure
()
request
=
self
.
prepare_request
(
'/api/v2/coupons/course_catalogs/'
)
response
=
CatalogViewSet
()
.
course_catalogs
(
request
)
self
.
assertTrue
(
mock_exception
.
called
)
self
.
assertEqual
(
response
.
data
.
get
(
'results'
),
[])
class
PartnerCatalogViewSetTest
(
CatalogMixin
,
TestCase
):
class
PartnerCatalogViewSetTest
(
CatalogMixin
,
TestCase
):
def
setUp
(
self
):
def
setUp
(
self
):
...
...
ecommerce/extensions/api/v2/tests/views/test_coupons.py
View file @
c9f1d6d0
...
@@ -73,7 +73,6 @@ class CouponViewSetTest(CouponMixin, CourseCatalogTestMixin, TestCase):
...
@@ -73,7 +73,6 @@ class CouponViewSetTest(CouponMixin, CourseCatalogTestMixin, TestCase):
'catalog_query'
:
None
,
'catalog_query'
:
None
,
'course_seat_types'
:
None
,
'course_seat_types'
:
None
,
'email_domains'
:
None
,
'email_domains'
:
None
,
'course_catalog'
:
{
'id'
:
''
,
'name'
:
''
},
}
}
def
setup_site_configuration
(
self
):
def
setup_site_configuration
(
self
):
...
@@ -239,8 +238,7 @@ class CouponViewSetFunctionalTest(CouponMixin, CourseCatalogTestMixin, CourseCat
...
@@ -239,8 +238,7 @@ class CouponViewSetFunctionalTest(CouponMixin, CourseCatalogTestMixin, CourseCat
'start_datetime'
:
str
(
now
()
-
datetime
.
timedelta
(
days
=
10
)),
'start_datetime'
:
str
(
now
()
-
datetime
.
timedelta
(
days
=
10
)),
'stock_record_ids'
:
[
1
,
2
],
'stock_record_ids'
:
[
1
,
2
],
'title'
:
'Tešt čoupon'
,
'title'
:
'Tešt čoupon'
,
'voucher_type'
:
Voucher
.
SINGLE_USE
,
'voucher_type'
:
Voucher
.
SINGLE_USE
'course_catalog'
:
{
'id'
:
''
,
'name'
:
''
},
}
}
self
.
response
=
self
.
client
.
post
(
COUPONS_LINK
,
json
.
dumps
(
self
.
data
),
'application/json'
)
self
.
response
=
self
.
client
.
post
(
COUPONS_LINK
,
json
.
dumps
(
self
.
data
),
'application/json'
)
self
.
coupon
=
Product
.
objects
.
get
(
title
=
self
.
data
[
'title'
])
self
.
coupon
=
Product
.
objects
.
get
(
title
=
self
.
data
[
'title'
])
...
...
ecommerce/extensions/api/v2/views/catalog.py
View file @
c9f1d6d0
...
@@ -13,7 +13,6 @@ from slumber.exceptions import SlumberBaseException
...
@@ -13,7 +13,6 @@ from slumber.exceptions import SlumberBaseException
from
ecommerce.core.constants
import
DEFAULT_CATALOG_PAGE_SIZE
from
ecommerce.core.constants
import
DEFAULT_CATALOG_PAGE_SIZE
from
ecommerce.coupons.utils
import
get_range_catalog_query_results
from
ecommerce.coupons.utils
import
get_range_catalog_query_results
from
ecommerce.extensions.api
import
serializers
from
ecommerce.extensions.api
import
serializers
from
ecommerce.courses.utils
import
get_course_catalogs
Catalog
=
get_model
(
'catalogue'
,
'Catalog'
)
Catalog
=
get_model
(
'catalogue'
,
'Catalog'
)
...
@@ -74,20 +73,3 @@ class CatalogViewSet(NestedViewSetMixin, ReadOnlyModelViewSet):
...
@@ -74,20 +73,3 @@ class CatalogViewSet(NestedViewSetMixin, ReadOnlyModelViewSet):
logger
.
error
(
'Unable to connect to Course Catalog service.'
)
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
)
return
Response
(
status
=
status
.
HTTP_400_BAD_REQUEST
)
return
Response
(
status
=
status
.
HTTP_400_BAD_REQUEST
)
@action
(
is_for_list
=
True
,
methods
=
[
'get'
])
def
course_catalogs
(
self
,
request
):
"""
Returns response with all course catalogs in the format:
["results": {"id": 1, "name": "Dummy Catalog"}]
"""
try
:
results
=
get_course_catalogs
(
site
=
request
.
site
)
except
:
# pylint: disable=bare-except
logger
.
exception
(
'Failed to retrieve course catalogs data from the Course Discovery API.'
)
results
=
[]
# Create catalogs list with sorting by name
catalogs
=
[{
'id'
:
catalog
[
'id'
],
'name'
:
catalog
[
'name'
]}
for
catalog
in
results
]
data
=
{
'results'
:
sorted
(
catalogs
,
key
=
lambda
catalog
:
catalog
.
get
(
'name'
,
''
)
.
lower
())}
return
Response
(
data
=
data
)
ecommerce/extensions/api/v2/views/coupons.py
View file @
c9f1d6d0
This diff is collapsed.
Click to expand it.
ecommerce/extensions/catalogue/tests/test_utils.py
View file @
c9f1d6d0
...
@@ -122,7 +122,6 @@ class CouponCreationTests(CouponMixin, TestCase):
...
@@ -122,7 +122,6 @@ class CouponCreationTests(CouponMixin, TestCase):
catalog_query
=
None
,
catalog_query
=
None
,
category
=
self
.
category
,
category
=
self
.
category
,
code
=
code
,
code
=
code
,
course_catalog
=
None
,
course_seat_types
=
None
,
course_seat_types
=
None
,
email_domains
=
None
,
email_domains
=
None
,
end_datetime
=
'2020-1-1'
,
end_datetime
=
'2020-1-1'
,
...
...
ecommerce/extensions/catalogue/utils.py
View file @
c9f1d6d0
...
@@ -36,8 +36,7 @@ def create_coupon_product(
...
@@ -36,8 +36,7 @@ def create_coupon_product(
quantity
,
quantity
,
start_datetime
,
start_datetime
,
title
,
title
,
voucher_type
,
voucher_type
course_catalog
,
):
):
"""
"""
Creates a coupon product and a stock record for it.
Creates a coupon product and a stock record for it.
...
@@ -50,7 +49,6 @@ def create_coupon_product(
...
@@ -50,7 +49,6 @@ def create_coupon_product(
category (dict): Contains category ID and name.
category (dict): Contains category ID and name.
code (str): Voucher code.
code (str): Voucher code.
course_seat_types (str): Comma-separated list of course seat types.
course_seat_types (str): Comma-separated list of course seat types.
course_catalog (int): Course catalog id from Catalog Service
email_domains (str): Comma-separated list of email domains.
email_domains (str): Comma-separated list of email domains.
end_datetime (Datetime): Voucher end Datetime.
end_datetime (Datetime): Voucher end Datetime.
max_uses (int): Number of Voucher max uses.
max_uses (int): Number of Voucher max uses.
...
@@ -84,7 +82,6 @@ def create_coupon_product(
...
@@ -84,7 +82,6 @@ def create_coupon_product(
catalog_query
=
catalog_query
,
catalog_query
=
catalog_query
,
code
=
code
or
None
,
code
=
code
or
None
,
coupon
=
coupon_product
,
coupon
=
coupon_product
,
course_catalog
=
course_catalog
,
course_seat_types
=
course_seat_types
,
course_seat_types
=
course_seat_types
,
email_domains
=
email_domains
,
email_domains
=
email_domains
,
end_datetime
=
end_datetime
,
end_datetime
=
end_datetime
,
...
...
ecommerce/extensions/offer/admin.py
View file @
c9f1d6d0
...
@@ -2,9 +2,8 @@ from oscar.apps.offer.admin import * # pylint: disable=unused-import,wildcard-i
...
@@ -2,9 +2,8 @@ from oscar.apps.offer.admin import * # pylint: disable=unused-import,wildcard-i
class
RangeAdminExtended
(
admin
.
ModelAdmin
):
class
RangeAdminExtended
(
admin
.
ModelAdmin
):
list_display
=
(
'name'
,
'catalog'
,
'course_catalog'
,
)
list_display
=
(
'name'
,
'catalog'
,)
raw_id_fields
=
(
'catalog'
,)
raw_id_fields
=
(
'catalog'
,)
search_fields
=
[
'name'
,
'course_catalog'
]
admin
.
site
.
unregister
(
Range
)
admin
.
site
.
unregister
(
Range
)
...
...
ecommerce/extensions/offer/migrations/0008_range_course_catalog.py
deleted
100644 → 0
View file @
104f6147
# -*- coding: utf-8 -*-
from
__future__
import
unicode_literals
from
django.db
import
migrations
,
models
class
Migration
(
migrations
.
Migration
):
dependencies
=
[
(
'offer'
,
'0007_auto_20161026_0856'
),
]
operations
=
[
migrations
.
AddField
(
model_name
=
'range'
,
name
=
'course_catalog'
,
field
=
models
.
PositiveIntegerField
(
help_text
=
'Course catalog id from the Catalog Service.'
,
null
=
True
,
blank
=
True
),
),
]
ecommerce/extensions/offer/models.py
View file @
c9f1d6d0
...
@@ -119,16 +119,10 @@ class Range(AbstractRange):
...
@@ -119,16 +119,10 @@ class Range(AbstractRange):
UPDATABLE_RANGE_FIELDS
=
[
UPDATABLE_RANGE_FIELDS
=
[
'catalog_query'
,
'catalog_query'
,
'course_seat_types'
,
'course_seat_types'
,
'course_catalog'
,
]
]
ALLOWED_SEAT_TYPES
=
[
'credit'
,
'professional'
,
'verified'
]
ALLOWED_SEAT_TYPES
=
[
'credit'
,
'professional'
,
'verified'
]
catalog
=
models
.
ForeignKey
(
'catalogue.Catalog'
,
blank
=
True
,
null
=
True
,
related_name
=
'ranges'
)
catalog
=
models
.
ForeignKey
(
'catalogue.Catalog'
,
blank
=
True
,
null
=
True
,
related_name
=
'ranges'
)
catalog_query
=
models
.
TextField
(
blank
=
True
,
null
=
True
)
catalog_query
=
models
.
TextField
(
blank
=
True
,
null
=
True
)
course_catalog
=
models
.
PositiveIntegerField
(
help_text
=
_
(
'Course catalog id from the Catalog Service.'
),
null
=
True
,
blank
=
True
)
course_seat_types
=
models
.
CharField
(
course_seat_types
=
models
.
CharField
(
max_length
=
255
,
max_length
=
255
,
validators
=
[
validate_credit_seat_type
],
validators
=
[
validate_credit_seat_type
],
...
...
ecommerce/extensions/voucher/models.py
View file @
c9f1d6d0
...
@@ -52,13 +52,5 @@ class Voucher(AbstractVoucher):
...
@@ -52,13 +52,5 @@ class Voucher(AbstractVoucher):
logger
.
exception
(
'Failed to create Voucher. Voucher start and end datetime fields must be type datetime.'
)
logger
.
exception
(
'Failed to create Voucher. Voucher start and end datetime fields must be type datetime.'
)
raise
ValidationError
(
_
(
'Voucher start and end datetime fields must be type datetime.'
))
raise
ValidationError
(
_
(
'Voucher start and end datetime fields must be type datetime.'
))
@classmethod
def
does_exist
(
cls
,
code
):
try
:
Voucher
.
objects
.
get
(
code
=
code
)
return
True
except
Voucher
.
DoesNotExist
:
return
False
from
oscar.apps.voucher.models
import
*
# noqa pylint: disable=wildcard-import,unused-wildcard-import,wrong-import-position
from
oscar.apps.voucher.models
import
*
# noqa pylint: disable=wildcard-import,unused-wildcard-import,wrong-import-position
ecommerce/extensions/voucher/tests/test_utils.py
View file @
c9f1d6d0
...
@@ -137,13 +137,6 @@ class UtilTests(CouponMixin, CourseCatalogMockMixin, CourseCatalogTestMixin, Lms
...
@@ -137,13 +137,6 @@ class UtilTests(CouponMixin, CourseCatalogMockMixin, CourseCatalogTestMixin, Lms
course_seat_types
=
course_seat_types
course_seat_types
=
course_seat_types
)
)
def
create_course_catalog_coupon
(
self
,
coupon_title
,
quantity
,
course_catalog
):
return
self
.
create_coupon
(
title
=
coupon_title
,
quantity
=
quantity
,
course_catalog
=
course_catalog
,
)
def
use_voucher
(
self
,
order_num
,
voucher
,
user
):
def
use_voucher
(
self
,
order_num
,
voucher
,
user
):
"""
"""
Mark voucher as used by provided users
Mark voucher as used by provided users
...
@@ -249,39 +242,6 @@ class UtilTests(CouponMixin, CourseCatalogMockMixin, CourseCatalogTestMixin, Lms
...
@@ -249,39 +242,6 @@ class UtilTests(CouponMixin, CourseCatalogMockMixin, CourseCatalogTestMixin, Lms
with
self
.
assertRaises
(
IntegrityError
):
with
self
.
assertRaises
(
IntegrityError
):
create_vouchers
(
**
self
.
data
)
create_vouchers
(
**
self
.
data
)
def
test_create_course_catalog_coupon
(
self
):
"""
Test course catalog coupon voucher creation with specified catalog id.
"""
coupon_title
=
'Course catalog coupon'
quantity
=
1
course_catalog
=
1
course_catalog_coupon
=
self
.
create_course_catalog_coupon
(
coupon_title
=
coupon_title
,
quantity
=
quantity
,
course_catalog
=
course_catalog
,
)
self
.
assertEqual
(
course_catalog_coupon
.
title
,
coupon_title
)
course_catalog_vouchers
=
course_catalog_coupon
.
attr
.
coupon_vouchers
.
vouchers
.
all
()
self
.
assertEqual
(
course_catalog_vouchers
.
count
(),
quantity
)
course_catalog_voucher_range
=
course_catalog_vouchers
.
first
()
.
offers
.
first
()
.
benefit
.
range
self
.
assertEqual
(
course_catalog_voucher_range
.
course_catalog
,
course_catalog
)
self
.
data
.
update
({
'name'
:
coupon_title
,
'benefit_value'
:
course_catalog_vouchers
.
first
()
.
offers
.
first
()
.
benefit
.
value
,
'code'
:
course_catalog_vouchers
.
first
()
.
code
,
'quantity'
:
quantity
,
'course_catalog'
:
course_catalog
,
'catalog'
:
None
,
'course_seat_types'
:
None
})
with
self
.
assertRaises
(
IntegrityError
):
create_vouchers
(
**
self
.
data
)
def
assert_report_first_row
(
self
,
row
,
coupon
,
voucher
):
def
assert_report_first_row
(
self
,
row
,
coupon
,
voucher
):
"""
"""
Verify that the first row fields contain the right data.
Verify that the first row fields contain the right data.
...
...
ecommerce/extensions/voucher/utils.py
View file @
c9f1d6d0
...
@@ -418,33 +418,26 @@ def create_vouchers(
...
@@ -418,33 +418,26 @@ def create_vouchers(
_range
=
None
,
_range
=
None
,
catalog_query
=
None
,
catalog_query
=
None
,
course_seat_types
=
None
,
course_seat_types
=
None
,
email_domains
=
None
,
email_domains
=
None
):
course_catalog
=
None
,
):
"""
"""
Create vouchers.
Create vouchers.
Arguments:
Args:
benefit_type (str): Type of benefit associated with vouchers.
benefit_type (str): Type of benefit associated with vouchers.
benefit_value (Decimal): Value of benefit associated with vouchers.
benefit_value (Decimal): Value of benefit associated with vouchers.
catalog (Catalog): Catalog associated with range of products
catalog (Catalog): Catalog associated with range of products
to which a voucher can be applied to.
to which a voucher can be applied to.
catalog_query (str): ElasticSearch query used by dynamic coupons. Defaults to None.
coupon (Coupon): Coupon entity associated with vouchers.
code (str): Code associated with vouchers. Defaults to None.
end_datetime (datetime): End date for voucher offer.
coupon (Coupon): Coupon entity associated with vouchers.
name (str): Voucher name.
course_catalog (int): Course catalog id from Catalog Service. Defaults to None.
quantity (int): Number of vouchers to be created.
course_seat_types (str): Comma-separated list of course seat types.
start_datetime (datetime): Start date for voucher offer.
email_domains (str): List of email domains to restrict coupons. Defaults to None.
voucher_type (str): Type of voucher.
end_datetime (datetime): End date for voucher offer.
code (str): Code associated with vouchers. Defaults to None.
max_uses (int): Number of Voucher max uses. Defaults to None.
email_domains (str): List of email domains to restrict coupons. Defaults to None.
name (str): Voucher name.
quantity (int): Number of vouchers to be created.
start_datetime (datetime): Start date for voucher offer.
voucher_type (str): Type of voucher.
_range (Range): Product range. Defaults to None.
Returns:
Returns:
List[Voucher]
List[Voucher]
"""
"""
logger
.
info
(
"Creating [
%
d] vouchers product [
%
s]"
,
quantity
,
coupon
.
id
)
logger
.
info
(
"Creating [
%
d] vouchers product [
%
s]"
,
quantity
,
coupon
.
id
)
vouchers
=
[]
vouchers
=
[]
...
@@ -457,13 +450,10 @@ def create_vouchers(
...
@@ -457,13 +450,10 @@ def create_vouchers(
else
:
else
:
logger
.
info
(
"Creating [
%
d] vouchers for coupon [
%
s]"
,
quantity
,
coupon
.
id
)
logger
.
info
(
"Creating [
%
d] vouchers for coupon [
%
s]"
,
quantity
,
coupon
.
id
)
range_name
=
(
_
(
'Range for coupon [{coupon_id}]'
)
.
format
(
coupon_id
=
coupon
.
id
))
range_name
=
(
_
(
'Range for coupon [{coupon_id}]'
)
.
format
(
coupon_id
=
coupon
.
id
))
# make sure course catalog is None if its empty
course_catalog
=
course_catalog
if
course_catalog
else
None
product_range
,
__
=
Range
.
objects
.
get_or_create
(
product_range
,
__
=
Range
.
objects
.
get_or_create
(
name
=
range_name
,
name
=
range_name
,
catalog
=
catalog
,
catalog
=
catalog
,
catalog_query
=
catalog_query
,
catalog_query
=
catalog_query
,
course_catalog
=
course_catalog
,
course_seat_types
=
course_seat_types
,
course_seat_types
=
course_seat_types
,
)
)
...
...
ecommerce/static/js/apps/coupon_admin_app.js
View file @
c9f1d6d0
require
([
require
([
'backbone'
,
'backbone'
,
'collections/category_collection'
,
'collections/category_collection'
,
'collections/catalog_collection'
,
'ecommerce'
,
'ecommerce'
,
'routers/coupon_router'
,
'routers/coupon_router'
,
'utils/navigate'
,
'utils/navigate'
,
],
],
function
(
Backbone
,
function
(
Backbone
,
CategoryCollection
,
CategoryCollection
,
CatalogCollection
,
ecommerce
,
ecommerce
,
CouponRouter
,
CouponRouter
,
navigate
)
{
navigate
)
{
...
@@ -22,10 +20,6 @@ require([
...
@@ -22,10 +20,6 @@ require([
ecommerce
.
coupons
.
categories
=
new
CategoryCollection
();
ecommerce
.
coupons
.
categories
=
new
CategoryCollection
();
ecommerce
.
coupons
.
categories
.
url
=
'/api/v2/coupons/categories/'
;
ecommerce
.
coupons
.
categories
.
url
=
'/api/v2/coupons/categories/'
;
ecommerce
.
coupons
.
categories
.
fetch
({
async
:
false
});
ecommerce
.
coupons
.
categories
.
fetch
({
async
:
false
});
ecommerce
.
coupons
.
catalogs
=
new
CatalogCollection
();
ecommerce
.
coupons
.
catalogs
.
fetch
({
async
:
false
});
couponApp
.
start
();
couponApp
.
start
();
// Handle navbar clicks.
// Handle navbar clicks.
...
...
ecommerce/static/js/collections/catalog_collection.js
deleted
100644 → 0
View file @
104f6147
define
([
'collections/paginated_collection'
,
'models/catalog_model'
],
function
(
PaginatedCollection
,
Catalog
)
{
'use strict'
;
return
PaginatedCollection
.
extend
({
model
:
Catalog
,
url
:
'/api/v2/catalogs/course_catalogs/'
}
);
}
);
ecommerce/static/js/models/catalog_model.js
deleted
100644 → 0
View file @
104f6147
define
([
'backbone.relational'
],
function
()
{
'use strict'
;
return
Backbone
.
RelationalModel
.
extend
({
urlRoot
:
'/api/v2/catalogs/course_catalogs/'
});
}
);
ecommerce/static/js/models/coupon_model.js
View file @
c9f1d6d0
...
@@ -7,9 +7,7 @@ define([
...
@@ -7,9 +7,7 @@ define([
'underscore'
,
'underscore'
,
'moment'
,
'moment'
,
'collections/category_collection'
,
'collections/category_collection'
,
'collections/catalog_collection'
,
'models/category'
,
'models/category'
,
'models/catalog_model'
,
'utils/validation_patterns'
'utils/validation_patterns'
],
],
function
(
Backbone
,
function
(
Backbone
,
...
@@ -26,23 +24,15 @@ define([
...
@@ -26,23 +24,15 @@ define([
required
:
gettext
(
'This field is required.'
),
required
:
gettext
(
'This field is required.'
),
number
:
gettext
(
'This value must be a number.'
),
number
:
gettext
(
'This value must be a number.'
),
date
:
gettext
(
'This value must be a date.'
),
date
:
gettext
(
'This value must be a date.'
),
seat_types
:
gettext
(
'At least one seat type must be selected.'
)
seat_types
:
gettext
(
'At least one seat type must be selected.'
)
,
});
});
_
.
extend
(
Backbone
.
Model
.
prototype
,
Backbone
.
Validation
.
mixin
);
_
.
extend
(
Backbone
.
Model
.
prototype
,
Backbone
.
Validation
.
mixin
);
/* jshint esnext: true */
var
CATALOG_TYPES
=
{
single_course
:
'Single course'
,
multiple_courses
:
'Multiple courses'
,
catalog
:
'Catalog'
};
return
Backbone
.
RelationalModel
.
extend
({
return
Backbone
.
RelationalModel
.
extend
({
urlRoot
:
'/api/v2/coupons/'
,
urlRoot
:
'/api/v2/coupons/'
,
defaults
:
{
defaults
:
{
category
:
{
id
:
3
,
name
:
'Affiliate Promotion'
},
category
:
{
id
:
3
,
name
:
'Affiliate Promotion'
},
course_catalog
:
{
id
:
''
,
name
:
''
},
code
:
''
,
code
:
''
,
course_seats
:
[],
course_seats
:
[],
course_seat_types
:
[],
course_seat_types
:
[],
...
@@ -52,11 +42,9 @@ define([
...
@@ -52,11 +42,9 @@ define([
quantity
:
1
,
quantity
:
1
,
seats
:
[],
seats
:
[],
stock_record_ids
:
[],
stock_record_ids
:
[],
total_value
:
0
total_value
:
0
,
},
},
catalogTypes
:
CATALOG_TYPES
,
validation
:
{
validation
:
{
benefit_value
:
{
benefit_value
:
{
pattern
:
'number'
,
pattern
:
'number'
,
...
@@ -66,12 +54,7 @@ define([
...
@@ -66,12 +54,7 @@ define([
},
},
catalog_query
:
{
catalog_query
:
{
required
:
function
()
{
required
:
function
()
{
return
this
.
get
(
'catalog_type'
)
===
CATALOG_TYPES
.
multiple_courses
;
return
this
.
get
(
'catalog_type'
)
===
'Multiple courses'
;
}
},
course_catalog
:
{
required
:
function
()
{
return
this
.
get
(
'catalog_type'
)
===
CATALOG_TYPES
.
catalog
;
}
}
},
},
category
:
{
required
:
true
},
category
:
{
required
:
true
},
...
@@ -86,11 +69,11 @@ define([
...
@@ -86,11 +69,11 @@ define([
pattern
:
'courseId'
,
pattern
:
'courseId'
,
msg
:
gettext
(
'A valid course ID is required'
),
msg
:
gettext
(
'A valid course ID is required'
),
required
:
function
()
{
required
:
function
()
{
return
this
.
get
(
'catalog_type'
)
===
CATALOG_TYPES
.
single_course
;
return
this
.
get
(
'catalog_type'
)
===
'Single course'
;
}
}
},
},
course_seat_types
:
function
(
val
)
{
course_seat_types
:
function
(
val
)
{
if
(
this
.
get
(
'catalog_type'
)
===
CATALOG_TYPES
.
multiple_courses
&&
val
.
length
===
0
)
{
if
(
this
.
get
(
'catalog_type'
)
===
'Multiple courses'
&&
val
.
length
===
0
)
{
return
Backbone
.
Validation
.
messages
.
seat_types
;
return
Backbone
.
Validation
.
messages
.
seat_types
;
}
}
},
},
...
@@ -150,7 +133,7 @@ define([
...
@@ -150,7 +133,7 @@ define([
// seat_type is for validation only, stock_record_ids holds the values
// seat_type is for validation only, stock_record_ids holds the values
seat_type
:
{
seat_type
:
{
required
:
function
()
{
required
:
function
()
{
return
this
.
get
(
'catalog_type'
)
===
CATALOG_TYPES
.
single_course
;
return
this
.
get
(
'catalog_type'
)
===
'Single course'
;
}
}
},
},
start_date
:
function
(
val
)
{
start_date
:
function
(
val
)
{
...
@@ -168,7 +151,7 @@ define([
...
@@ -168,7 +151,7 @@ define([
return
gettext
(
'Must occur before end date'
);
return
gettext
(
'Must occur before end date'
);
}
}
},
},
title
:
{
required
:
true
}
title
:
{
required
:
true
}
,
},
},
initialize
:
function
()
{
initialize
:
function
()
{
...
@@ -202,29 +185,11 @@ define([
...
@@ -202,29 +185,11 @@ define([
updateSeatData
:
function
()
{
updateSeatData
:
function
()
{
var
seat_data
,
var
seat_data
,
seats
=
this
.
get
(
'seats'
),
seats
=
this
.
get
(
'seats'
);
catalogId
,
catalogType
;
catalogId
=
''
;
this
.
set
(
'catalog_type'
,
this
.
has
(
'catalog_query'
)
?
'Multiple courses'
:
'Single course'
);
if
(
this
.
has
(
'course_catalog'
))
{
if
(
typeof
this
.
get
(
'course_catalog'
)
===
'number'
)
{
catalogId
=
this
.
get
(
'course_catalog'
);
}
else
if
(
!
$
.
isEmptyObject
(
this
.
get
(
'course_catalog'
)))
{
catalogId
=
this
.
get
(
'course_catalog'
).
id
;
}
}
if
(
this
.
has
(
'catalog_query'
)
&&
this
.
get
(
'catalog_query'
)
!==
''
)
{
catalogType
=
this
.
catalogTypes
.
multiple_courses
;
}
else
if
(
catalogId
!==
''
)
{
catalogType
=
this
.
catalogTypes
.
catalog
;
}
else
{
catalogType
=
this
.
catalogTypes
.
single_course
;
}
this
.
set
(
'catalog_type'
,
catalogType
);
if
(
this
.
get
(
'catalog_type'
)
===
this
.
catalogTypes
.
single_course
)
{
if
(
this
.
get
(
'catalog_type'
)
===
'Single course'
)
{
if
(
seats
[
0
])
{
if
(
seats
[
0
])
{
seat_data
=
seats
[
0
].
attribute_values
;
seat_data
=
seats
[
0
].
attribute_values
;
...
@@ -232,7 +197,6 @@ define([
...
@@ -232,7 +197,6 @@ define([
this
.
set
(
'course_id'
,
this
.
getCourseID
(
seat_data
));
this
.
set
(
'course_id'
,
this
.
getCourseID
(
seat_data
));
this
.
updateTotalValue
(
this
.
getSeatPrice
());
this
.
updateTotalValue
(
this
.
getSeatPrice
());
}
}
this
.
set
(
'course_catalog'
,
this
.
defaults
.
course_catalog
);
}
}
},
},
...
@@ -247,7 +211,7 @@ define([
...
@@ -247,7 +211,7 @@ define([
'invoice_number'
:
invoice
.
number
,
'invoice_number'
:
invoice
.
number
,
'invoice_payment_date'
:
invoice
.
payment_date
,
'invoice_payment_date'
:
invoice
.
payment_date
,
'tax_deducted_source'
:
invoice
.
tax_deducted_source
,
'tax_deducted_source'
:
invoice
.
tax_deducted_source
,
'tax_deduction'
:
tax_deducted
'tax_deduction'
:
tax_deducted
,
});
});
},
},
...
...
ecommerce/static/js/test/mock_data/catalogs.js
deleted
100644 → 0
View file @
104f6147
define
([],
function
(){
'use strict'
;
var
catalogs
=
[
{
'id'
:
1
,
'name'
:
'All Courses Catalog'
},
{
'id'
:
2
,
'name'
:
'No Courses Catalog'
},
{
'id'
:
3
,
'name'
:
'edX Catalog'
},
{
'id'
:
4
,
'name'
:
'Test Catalog 1'
},
{
'id'
:
5
,
'name'
:
'Enterprise Catalog'
},
{
'id'
:
6
,
'name'
:
'Test 2 Catalog'
},
{
'id'
:
7
,
'name'
:
'Empty Catalog'
}
];
return
catalogs
;
});
ecommerce/static/js/test/mock_data/coupons.js
View file @
c9f1d6d0
...
@@ -194,7 +194,6 @@ define([], function () {
...
@@ -194,7 +194,6 @@ define([], function () {
'id'
:
4
,
'id'
:
4
,
'name'
:
'TESTCAT'
'name'
:
'TESTCAT'
},
},
course_catalog
:
{},
'price'
:
'100.00'
,
'price'
:
'100.00'
,
'invoice_type'
:
'Prepaid'
,
'invoice_type'
:
'Prepaid'
,
'invoice_discount_type'
:
'Percentage'
,
'invoice_discount_type'
:
'Percentage'
,
...
...
ecommerce/static/js/test/mock_data/selected_catalogs.js
deleted
100644 → 0
View file @
104f6147
define
([],
function
(){
'use strict'
;
var
selected_catalog
=
{
1
:
{
'id'
:
1
,
'name'
:
'Courses Catalog 1'
},
2
:
{
'id'
:
2
,
'name'
:
'Courses Catalog 2'
}
};
return
selected_catalog
;
});
ecommerce/static/js/test/spec-runner.js
View file @
c9f1d6d0
...
@@ -20,8 +20,6 @@ if (!window.gettext) {
...
@@ -20,8 +20,6 @@ if (!window.gettext) {
// Establish the global namespace
// Establish the global namespace
window
.
ecommerce
=
window
.
ecommerce
||
{};
window
.
ecommerce
=
window
.
ecommerce
||
{};
window
.
ecommerce
.
coupons
=
window
.
ecommerce
.
coupons
||
{};
window
.
ecommerce
.
coupons
=
window
.
ecommerce
.
coupons
||
{};
window
.
ecommerce
.
catalogs
=
window
.
ecommerce
.
catalogs
||
{};
window
.
ecommerce
.
categories
=
window
.
ecommerce
.
categories
||
{};
window
.
ecommerce
.
credit
=
window
.
ecommerce
.
credit
||
{};
window
.
ecommerce
.
credit
=
window
.
ecommerce
.
credit
||
{};
// you can automatically get the test files using karma's configs
// you can automatically get the test files using karma's configs
...
...
ecommerce/static/js/test/spec-utils.js
View file @
c9f1d6d0
...
@@ -14,13 +14,7 @@ define([
...
@@ -14,13 +14,7 @@ define([
return
Backbone
.
Model
.
extend
({
return
Backbone
.
Model
.
extend
({
defaults
:
{
defaults
:
{
id
:
null
,
id
:
null
,
category
:
{},
category
:
{}
course_catalog
:
{}
},
catalogTypes
:
{
single_course
:
'Single course'
,
multiple_courses
:
'Multiple courses'
,
catalog
:
'Catalog'
},
},
isValid
:
function
()
{
isValid
:
function
()
{
...
...
ecommerce/static/js/test/specs/collections/catalog_collection_spec.js
deleted
100644 → 0
View file @
104f6147
define
([
'collections/catalog_collection'
,
'test/mock_data/catalogs'
],
function
(
CatalogCollection
,
Mock_Catalogs
)
{
'use strict'
;
var
collection
,
response
=
Mock_Catalogs
;
beforeEach
(
function
()
{
collection
=
new
CatalogCollection
();
});
describe
(
'Catalog collection'
,
function
()
{
describe
(
'parse'
,
function
()
{
it
(
'should fetch the next page of results'
,
function
()
{
spyOn
(
collection
,
'fetch'
).
and
.
returnValue
(
null
);
response
.
next
=
'/api/v2/catalogs/course_catalogs/?page=2'
;
collection
.
parse
(
response
);
expect
(
collection
.
url
).
toEqual
(
response
.
next
);
expect
(
collection
.
fetch
).
toHaveBeenCalledWith
({
remove
:
false
});
});
});
});
}
);
ecommerce/static/js/test/specs/models/coupon_model_spec.js
View file @
c9f1d6d0
...
@@ -81,32 +81,12 @@ define([
...
@@ -81,32 +81,12 @@ define([
model
.
validate
();
model
.
validate
();
expect
(
model
.
isValid
()).
toBeFalsy
();
expect
(
model
.
isValid
()).
toBeFalsy
();
model
.
set
(
'catalog_query'
,
''
);
model
.
set
(
'course_seat_types'
,
[
'verified'
]);
model
.
validate
();
expect
(
model
.
isValid
()).
toBe
(
false
);
model
.
set
(
'catalog_query'
,
'*:*'
);
model
.
set
(
'catalog_query'
,
'*:*'
);
model
.
set
(
'course_seat_types'
,
[
'verified'
]);
model
.
set
(
'course_seat_types'
,
[
'verified'
]);
model
.
validate
();
model
.
validate
();
expect
(
model
.
isValid
()).
toBeTruthy
();
expect
(
model
.
isValid
()).
toBeTruthy
();
});
});
it
(
'should validate course catalog for type Catalog'
,
function
()
{
model
.
set
(
'catalog_type'
,
'Catalog'
);
model
.
set
(
'course_catalog'
,
''
);
model
.
validate
();
expect
(
model
.
isValid
()).
toBe
(
false
);
model
.
set
(
'course_catalog'
,
''
);
model
.
validate
();
expect
(
model
.
isValid
()).
toBe
(
false
);
model
.
set
(
'course_catalog'
,
'1'
);
model
.
validate
();
expect
(
model
.
isValid
()).
toBe
(
true
);
});
it
(
'should validate invoice data.'
,
function
()
{
it
(
'should validate invoice data.'
,
function
()
{
model
.
set
(
'price'
,
'text'
);
model
.
set
(
'price'
,
'text'
);
model
.
validate
();
model
.
validate
();
...
@@ -193,36 +173,6 @@ define([
...
@@ -193,36 +173,6 @@ define([
});
});
});
});
describe
(
'Should Update Seat Data Correctly.'
,
function
()
{
it
(
'should set correct catalog type for each seat.'
,
function
()
{
// Test single course catalog type when a single course is selected for coupon creation.
var
model
=
new
Coupon
({});
model
.
updateSeatData
();
expect
(
model
.
get
(
'catalog_type'
)).
toEqual
(
model
.
catalogTypes
.
single_course
);
// Test course catalog type when an existing course catalog is selected for coupon creation.
model
=
new
Coupon
({
course_catalog
:
{
id
:
1
,
name
:
'Test Catalog'
}
});
model
.
updateSeatData
();
expect
(
model
.
get
(
'catalog_type'
)).
toEqual
(
model
.
catalogTypes
.
catalog
);
model
=
new
Coupon
({
course_catalog
:
1
});
model
.
updateSeatData
();
expect
(
model
.
get
(
'catalog_type'
)).
toEqual
(
model
.
catalogTypes
.
catalog
);
// Test multiple course type when an catalog query is given for coupon creation.
model
=
new
Coupon
({
catalog_query
:
'*:*'
});
model
.
updateSeatData
();
expect
(
model
.
get
(
'catalog_type'
)).
toEqual
(
model
.
catalogTypes
.
multiple_courses
);
});
});
describe
(
'save'
,
function
()
{
describe
(
'save'
,
function
()
{
it
(
'should POST enrollment data'
,
function
()
{
it
(
'should POST enrollment data'
,
function
()
{
var
model
,
args
,
ajaxData
;
var
model
,
args
,
ajaxData
;
...
...
ecommerce/static/js/test/specs/utils/utils_spec.js
View file @
c9f1d6d0
...
@@ -4,7 +4,6 @@ define([
...
@@ -4,7 +4,6 @@ define([
'utils/utils'
,
'utils/utils'
,
'views/coupon_form_view'
,
'views/coupon_form_view'
,
'test/mock_data/categories'
,
'test/mock_data/categories'
,
'test/mock_data/catalogs'
,
'ecommerce'
'ecommerce'
],
],
function
(
Backbone
,
function
(
Backbone
,
...
@@ -12,7 +11,6 @@ define([
...
@@ -12,7 +11,6 @@ define([
Utils
,
Utils
,
CouponFormView
,
CouponFormView
,
Mock_Categories
,
Mock_Categories
,
Mock_Catalogs
,
ecommerce
)
{
ecommerce
)
{
'use strict'
;
'use strict'
;
...
@@ -67,8 +65,7 @@ define([
...
@@ -67,8 +65,7 @@ define([
beforeEach
(
function
()
{
beforeEach
(
function
()
{
ecommerce
.
coupons
=
{
ecommerce
.
coupons
=
{
categories
:
Mock_Categories
,
categories
:
Mock_Categories
catalogs
:
Mock_Catalogs
};
};
});
});
...
...
ecommerce/static/js/test/specs/views/coupon_create_view_spec.js
View file @
c9f1d6d0
...
@@ -4,7 +4,6 @@ define([
...
@@ -4,7 +4,6 @@ define([
'views/alert_view'
,
'views/alert_view'
,
'models/coupon_model'
,
'models/coupon_model'
,
'test/mock_data/categories'
,
'test/mock_data/categories'
,
'test/mock_data/catalogs'
,
'ecommerce'
'ecommerce'
],
],
function
(
$
,
function
(
$
,
...
@@ -12,7 +11,6 @@ define([
...
@@ -12,7 +11,6 @@ define([
AlertView
,
AlertView
,
Coupon
,
Coupon
,
Mock_Categories
,
Mock_Categories
,
Mock_Catalogs
,
ecommerce
)
{
ecommerce
)
{
'use strict'
;
'use strict'
;
...
@@ -22,8 +20,7 @@ define([
...
@@ -22,8 +20,7 @@ define([
beforeEach
(
function
()
{
beforeEach
(
function
()
{
ecommerce
.
coupons
=
{
ecommerce
.
coupons
=
{
categories
:
Mock_Categories
,
categories
:
Mock_Categories
catalogs
:
Mock_Catalogs
};
};
model
=
new
Coupon
();
model
=
new
Coupon
();
view
=
new
CouponCreateEditView
({
model
:
model
,
editing
:
false
}).
render
();
view
=
new
CouponCreateEditView
({
model
:
model
,
editing
:
false
}).
render
();
...
...
ecommerce/static/js/test/specs/views/coupon_form_view_spec.js
View file @
c9f1d6d0
...
@@ -6,8 +6,6 @@ define([
...
@@ -6,8 +6,6 @@ define([
'models/coupon_model'
,
'models/coupon_model'
,
'test/mock_data/categories'
,
'test/mock_data/categories'
,
'test/mock_data/coupons'
,
'test/mock_data/coupons'
,
'test/mock_data/catalogs'
,
'test/mock_data/selected_catalogs'
,
'test/spec-utils'
,
'test/spec-utils'
,
'ecommerce'
,
'ecommerce'
,
'test/custom-matchers'
'test/custom-matchers'
...
@@ -19,8 +17,6 @@ define([
...
@@ -19,8 +17,6 @@ define([
Coupon
,
Coupon
,
Mock_Categories
,
Mock_Categories
,
Mock_Coupons
,
Mock_Coupons
,
Mock_Catalogs
,
Mock_Selected_Catalogs
,
SpecUtils
,
SpecUtils
,
ecommerce
)
{
ecommerce
)
{
'use strict'
;
'use strict'
;
...
@@ -32,10 +28,9 @@ define([
...
@@ -32,10 +28,9 @@ define([
beforeEach
(
function
()
{
beforeEach
(
function
()
{
ecommerce
.
coupons
=
{
ecommerce
.
coupons
=
{
categories
:
Mock_Categories
,
categories
:
Mock_Categories
catalogs
:
Mock_Catalogs
};
};
model
=
new
Coupon
(
{
course_catalog
:
Mock_Catalogs
}
);
model
=
new
Coupon
();
view
=
new
CouponFormView
({
editing
:
false
,
model
:
model
}).
render
();
view
=
new
CouponFormView
({
editing
:
false
,
model
:
model
}).
render
();
});
});
...
@@ -129,50 +124,6 @@ define([
...
@@ -129,50 +124,6 @@ define([
});
});
});
});
describe
(
'course catalogs'
,
function
()
{
it
(
'course catalog drop down should be hidden when catalog is not selected'
,
function
()
{
view
.
$
(
'#single-course'
).
prop
(
'checked'
,
true
).
trigger
(
'change'
);
expect
(
SpecUtils
.
formGroup
(
view
,
'[name=course_catalog]'
)).
not
.
toBeVisible
();
view
.
$
(
'#multiple-courses'
).
prop
(
'checked'
,
true
).
trigger
(
'change'
);
expect
(
SpecUtils
.
formGroup
(
view
,
'[name=course_catalog]'
)).
not
.
toBeVisible
();
view
.
$
(
'#catalog'
).
prop
(
'checked'
,
true
).
trigger
(
'change'
);
expect
(
SpecUtils
.
formGroup
(
view
,
'[name=course_catalog]'
)).
toBeVisible
();
});
it
(
'course catalog is setting properly'
,
function
()
{
view
.
$
(
'#catalog'
).
prop
(
'checked'
,
true
).
trigger
(
'change'
);
view
.
$
(
'[name=course_catalog]'
).
val
(
1
).
trigger
(
'change'
);
expect
(
view
.
$
(
'select[name=course_catalog] option:selected'
).
text
()).
toEqual
(
Mock_Catalogs
[
0
].
name
);
expect
(
view
.
$
(
'[name=course_catalog]'
).
val
()).
toEqual
(
'1'
);
view
.
$
(
'[name=course_catalog]'
).
val
(
2
).
trigger
(
'change'
);
expect
(
view
.
$
(
'select[name=course_catalog] option:selected'
).
text
()).
toEqual
(
Mock_Catalogs
[
1
].
name
);
expect
(
view
.
$
(
'[name=course_catalog]'
).
val
()).
toEqual
(
'2'
);
view
.
$
(
'[name=course_catalog]'
).
val
(
3
).
trigger
(
'change'
);
expect
(
view
.
$
(
'select[name=course_catalog] option:selected'
).
text
()).
toEqual
(
Mock_Catalogs
[
2
].
name
);
expect
(
view
.
$
(
'[name=course_catalog]'
).
val
()).
toEqual
(
'3'
);
});
it
(
'returning right course catalog when selected catalog is number'
,
function
()
{
ecommerce
.
coupons
=
{
categories
:
Mock_Categories
,
catalogs
:
Mock_Selected_Catalogs
};
var
coupon_model
=
new
Coupon
({
course_catalog
:
1
});
var
coupon_form_view
=
new
CouponFormView
({
editing
:
true
,
model
:
coupon_model
}).
render
();
expect
(
coupon_model
.
get
(
'course_catalog'
)).
toEqual
({
id
:
1
,
'name'
:
'Courses Catalog 1'
});
coupon_model
.
set
({
course_catalog
:
2
});
coupon_form_view
.
render
();
expect
(
coupon_model
.
get
(
'course_catalog'
)).
toEqual
({
id
:
2
,
'name'
:
'Courses Catalog 2'
});
});
});
describe
(
'discount code'
,
function
()
{
describe
(
'discount code'
,
function
()
{
var
prepaid_invoice_fields
=
[
var
prepaid_invoice_fields
=
[
'[name=invoice_number]'
,
'[name=invoice_number]'
,
...
...
ecommerce/static/js/views/coupon_detail_view.js
View file @
c9f1d6d0
define
([
define
([
'jquery'
,
'jquery'
,
'backbone'
,
'backbone'
,
'ecommerce'
,
'underscore'
,
'underscore'
,
'underscore.string'
,
'underscore.string'
,
'moment'
,
'moment'
,
...
@@ -12,7 +11,6 @@ define([
...
@@ -12,7 +11,6 @@ define([
],
],
function
(
$
,
function
(
$
,
Backbone
,
Backbone
,
ecommerce
,
_
,
_
,
_s
,
_s
,
moment
,
moment
,
...
@@ -116,8 +114,6 @@ define([
...
@@ -116,8 +114,6 @@ define([
render
:
function
()
{
render
:
function
()
{
var
html
,
var
html
,
category
=
this
.
model
.
get
(
'category'
).
name
,
category
=
this
.
model
.
get
(
'category'
).
name
,
courseCatalog
=
this
.
model
.
get
(
'course_catalog'
),
courseCatalogName
=
''
,
invoice_data
=
this
.
formatInvoiceData
(),
invoice_data
=
this
.
formatInvoiceData
(),
emailDomains
=
this
.
model
.
get
(
'email_domains'
),
emailDomains
=
this
.
model
.
get
(
'email_domains'
),
template_data
,
template_data
,
...
@@ -127,16 +123,9 @@ define([
...
@@ -127,16 +123,9 @@ define([
price
=
_s
.
sprintf
(
'$%s'
,
this
.
model
.
get
(
'price'
));
price
=
_s
.
sprintf
(
'$%s'
,
this
.
model
.
get
(
'price'
));
}
}
if
(
typeof
courseCatalog
===
'number'
)
{
courseCatalogName
=
ecommerce
.
coupons
.
catalogs
.
get
(
courseCatalog
).
get
(
'name'
);
}
else
if
(
!
$
.
isEmptyObject
(
courseCatalog
))
{
courseCatalogName
=
courseCatalog
.
name
;
}
template_data
=
{
template_data
=
{
category
:
category
,
category
:
category
,
coupon
:
this
.
model
.
toJSON
(),
coupon
:
this
.
model
.
toJSON
(),
courseCatalogName
:
courseCatalogName
,
courseSeatType
:
this
.
formatSeatTypes
(),
courseSeatType
:
this
.
formatSeatTypes
(),
discountValue
:
this
.
discountValue
(),
discountValue
:
this
.
discountValue
(),
endDateTime
:
this
.
formatDateTime
(
this
.
model
.
get
(
'end_date'
)),
endDateTime
:
this
.
formatDateTime
(
this
.
model
.
get
(
'end_date'
)),
...
...
ecommerce/static/js/views/coupon_form_view.js
View file @
c9f1d6d0
...
@@ -168,28 +168,6 @@ define([
...
@@ -168,28 +168,6 @@ define([
'input[name=course_seat_types]'
:
{
'input[name=course_seat_types]'
:
{
observe
:
'course_seat_types'
observe
:
'course_seat_types'
},
},
'select[name=course_catalog]'
:
{
observe
:
'course_catalog'
,
selectOptions
:
{
collection
:
function
()
{
return
ecommerce
.
coupons
.
catalogs
;
},
labelPath
:
'name'
,
valuePath
:
'id'
},
setOptions
:
{
validate
:
true
},
onGet
:
function
(
val
)
{
return
val
.
id
;
},
onSet
:
function
(
val
)
{
return
{
id
:
val
,
name
:
$
(
'select[name=course_catalog] option:selected'
).
text
()
};
}
},
'input[name=email_domains]'
:
{
'input[name=email_domains]'
:
{
observe
:
'email_domains'
,
observe
:
'email_domains'
,
onSet
:
function
(
val
)
{
onSet
:
function
(
val
)
{
...
@@ -274,7 +252,6 @@ define([
...
@@ -274,7 +252,6 @@ define([
'category'
,
'category'
,
'client'
,
'client'
,
'course_seat_types'
,
'course_seat_types'
,
'course_catalog'
,
'end_date'
,
'end_date'
,
'invoice_discount_type'
,
'invoice_discount_type'
,
'invoice_discount_value'
,
'invoice_discount_value'
,
...
@@ -440,37 +417,22 @@ define([
...
@@ -440,37 +417,22 @@ define([
},
},
toggleCatalogTypeField
:
function
()
{
toggleCatalogTypeField
:
function
()
{
if
(
this
.
model
.
get
(
'catalog_type'
)
===
this
.
model
.
catalogTypes
.
single_course
)
{
if
(
this
.
model
.
get
(
'catalog_type'
)
===
'Single course'
)
{
this
.
model
.
unset
(
'course_seat_types'
);
this
.
model
.
unset
(
'course_seat_types'
);
this
.
model
.
unset
(
'catalog_query'
);
this
.
model
.
unset
(
'catalog_query'
);
this
.
model
.
set
(
'course_catalog'
,
this
.
model
.
defaults
.
course_catalog
);
this
.
formGroup
(
'[name=catalog_query]'
).
addClass
(
this
.
hiddenClass
);
this
.
formGroup
(
'[name=catalog_query]'
).
addClass
(
this
.
hiddenClass
);
this
.
formGroup
(
'[name=course_seat_types]'
).
addClass
(
this
.
hiddenClass
);
this
.
formGroup
(
'[name=course_seat_types]'
).
addClass
(
this
.
hiddenClass
);
this
.
formGroup
(
'[name=course_id]'
).
removeClass
(
this
.
hiddenClass
);
this
.
formGroup
(
'[name=course_id]'
).
removeClass
(
this
.
hiddenClass
);
this
.
formGroup
(
'[name=seat_type]'
).
removeClass
(
this
.
hiddenClass
);
this
.
formGroup
(
'[name=seat_type]'
).
removeClass
(
this
.
hiddenClass
);
this
.
formGroup
(
'[name=course_catalog]'
).
addClass
(
this
.
hiddenClass
);
}
else
if
(
this
.
model
.
get
(
'catalog_type'
)
===
this
.
model
.
catalogTypes
.
catalog
)
{
this
.
model
.
unset
(
'course_id'
);
this
.
model
.
unset
(
'seat_type'
);
this
.
model
.
unset
(
'stock_record_ids'
);
this
.
model
.
unset
(
'catalog_query'
);
this
.
model
.
unset
(
'course_seat_types'
);
this
.
formGroup
(
'[name=catalog_query]'
).
addClass
(
this
.
hiddenClass
);
this
.
formGroup
(
'[name=course_seat_types]'
).
addClass
(
this
.
hiddenClass
);
this
.
formGroup
(
'[name=course_id]'
).
addClass
(
this
.
hiddenClass
);
this
.
formGroup
(
'[name=seat_type]'
).
addClass
(
this
.
hiddenClass
);
this
.
formGroup
(
'[name=course_catalog]'
).
removeClass
(
this
.
hiddenClass
);
}
else
{
}
else
{
this
.
formGroup
(
'[name=catalog_query]'
).
removeClass
(
this
.
hiddenClass
);
this
.
formGroup
(
'[name=catalog_query]'
).
removeClass
(
this
.
hiddenClass
);
this
.
formGroup
(
'[name=course_seat_types]'
).
removeClass
(
this
.
hiddenClass
);
this
.
formGroup
(
'[name=course_seat_types]'
).
removeClass
(
this
.
hiddenClass
);
this
.
formGroup
(
'[name=course_id]'
).
addClass
(
this
.
hiddenClass
);
this
.
formGroup
(
'[name=course_id]'
).
addClass
(
this
.
hiddenClass
);
this
.
formGroup
(
'[name=seat_type]'
).
addClass
(
this
.
hiddenClass
);
this
.
formGroup
(
'[name=seat_type]'
).
addClass
(
this
.
hiddenClass
);
this
.
formGroup
(
'[name=course_catalog]'
).
addClass
(
this
.
hiddenClass
);
this
.
$
(
'[name=seat_type] option'
).
remove
();
this
.
$
(
'[name=seat_type] option'
).
remove
();
this
.
model
.
unset
(
'course_id'
);
this
.
model
.
unset
(
'course_id'
);
this
.
model
.
unset
(
'seat_type'
);
this
.
model
.
unset
(
'seat_type'
);
this
.
model
.
unset
(
'stock_record_ids'
);
this
.
model
.
unset
(
'stock_record_ids'
);
this
.
model
.
set
(
'course_catalog'
,
this
.
model
.
defaults
.
course_catalog
);
if
(
!
this
.
model
.
get
(
'course_seat_types'
))
{
if
(
!
this
.
model
.
get
(
'course_seat_types'
))
{
this
.
model
.
set
(
'course_seat_types'
,
[]);
this
.
model
.
set
(
'course_seat_types'
,
[]);
...
@@ -652,8 +614,6 @@ define([
...
@@ -652,8 +614,6 @@ define([
render
:
function
()
{
render
:
function
()
{
// Render the parent form/template
// Render the parent form/template
var
catalogId
=
''
;
this
.
$el
.
html
(
this
.
template
(
this
.
model
.
attributes
));
this
.
$el
.
html
(
this
.
template
(
this
.
model
.
attributes
));
this
.
stickit
();
this
.
stickit
();
...
@@ -670,21 +630,6 @@ define([
...
@@ -670,21 +630,6 @@ define([
this
.
$
(
'.non-credit-seats'
).
addClass
(
this
.
hiddenClass
);
this
.
$
(
'.non-credit-seats'
).
addClass
(
this
.
hiddenClass
);
}
}
}
}
if
(
this
.
model
.
has
(
'course_catalog'
))
{
if
(
typeof
this
.
model
.
get
(
'course_catalog'
)
===
'number'
)
{
catalogId
=
this
.
model
.
get
(
'course_catalog'
);
}
else
if
(
!
$
.
isEmptyObject
(
this
.
model
.
get
(
'course_catalog'
)))
{
catalogId
=
this
.
model
.
get
(
'course_catalog'
).
id
;
}
}
if
(
catalogId
!==
''
)
{
this
.
model
.
set
(
'course_catalog'
,
ecommerce
.
coupons
.
catalogs
[
catalogId
]);
}
else
{
this
.
model
.
set
(
'course_catalog'
,
this
.
model
.
defaults
.
course_catalog
);
}
this
.
disableNonEditableFields
();
this
.
disableNonEditableFields
();
this
.
toggleCouponTypeField
();
this
.
toggleCouponTypeField
();
this
.
toggleVoucherTypeField
();
this
.
toggleVoucherTypeField
();
...
@@ -700,7 +645,7 @@ define([
...
@@ -700,7 +645,7 @@ define([
'coupon_type'
:
this
.
codeTypes
[
0
].
value
,
'coupon_type'
:
this
.
codeTypes
[
0
].
value
,
'voucher_type'
:
this
.
voucherTypes
[
0
].
value
,
'voucher_type'
:
this
.
voucherTypes
[
0
].
value
,
'benefit_type'
:
'Percentage'
,
'benefit_type'
:
'Percentage'
,
'catalog_type'
:
this
.
model
.
catalogTypes
.
single_course
,
'catalog_type'
:
'Single course'
,
'invoice_discount_type'
:
'Percentage'
,
'invoice_discount_type'
:
'Percentage'
,
'invoice_type'
:
'Prepaid'
,
'invoice_type'
:
'Prepaid'
,
'tax_deduction'
:
'No'
,
'tax_deduction'
:
'No'
,
...
...
ecommerce/static/templates/coupon_detail.html
View file @
c9f1d6d0
...
@@ -50,12 +50,6 @@
...
@@ -50,12 +50,6 @@
<div
class=
"value"
><
%=
coupon
.
catalog_query
%
></div>
<div
class=
"value"
><
%=
coupon
.
catalog_query
%
></div>
</div>
</div>
<
%}%
>
<
%}%
>
<
%
if
(
courseCatalogName
)
{%
>
<div
class=
"info-item grid-item catalog-name"
>
<div
class=
"heading"
><
%=
gettext
('
Catalog:
')
%
></div>
<div
class=
"value"
><
%=
courseCatalogName
%
></div>
</div>
<
%}%
>
<div
class=
"info-item grid-item date-info"
>
<div
class=
"info-item grid-item date-info"
>
<div
class=
"start-date-info"
>
<div
class=
"start-date-info"
>
<div
class=
"heading"
><
%=
gettext
('
Valid
from:
')
%
></div>
<div
class=
"heading"
><
%=
gettext
('
Valid
from:
')
%
></div>
...
...
ecommerce/static/templates/coupon_form.html
View file @
c9f1d6d0
...
@@ -164,8 +164,6 @@
...
@@ -164,8 +164,6 @@
<label
for=
"single-course"
><
%=
gettext
('
Single
course
')
%
></label>
<label
for=
"single-course"
><
%=
gettext
('
Single
course
')
%
></label>
<input
id=
"multiple-courses"
type=
"radio"
name=
"catalog_type"
value=
"Multiple courses"
>
<input
id=
"multiple-courses"
type=
"radio"
name=
"catalog_type"
value=
"Multiple courses"
>
<label
for=
"multiple-courses"
><
%=
gettext
('
Multiple
courses
')
%
></label>
<label
for=
"multiple-courses"
><
%=
gettext
('
Multiple
courses
')
%
></label>
<input
id=
"catalog"
type=
"radio"
name=
"catalog_type"
value=
"Catalog"
>
<label
for=
"catalog"
><
%=
gettext
('
Catalog
')
%
></label>
</div>
</div>
<p
class=
"help-block"
></p>
<p
class=
"help-block"
></p>
</div>
</div>
...
@@ -206,11 +204,6 @@
...
@@ -206,11 +204,6 @@
</div>
</div>
<div
class=
"catalog_buttons"
></div>
<div
class=
"catalog_buttons"
></div>
</div>
</div>
<div
class=
"form-group course-catalog"
>
<label
for=
"course-catalog"
><
%=
gettext
('
Select
from
course
catalogs:
')
%
>
*
</label>
<select
id=
"course-catalog"
class=
"form-control"
name=
"course_catalog"
></select>
<p
class=
"help-block"
></p>
</div>
<div
class=
"form-group email-domains"
>
<div
class=
"form-group email-domains"
>
<label
for=
"email-domains"
><
%=
gettext
('
Email
domains:
')
%
>
</label>
<label
for=
"email-domains"
><
%=
gettext
('
Email
domains:
')
%
>
</label>
<input
id=
"email-domains"
class=
"form-control"
name=
"email_domains"
maxlength=
"255"
>
<input
id=
"email-domains"
class=
"form-control"
name=
"email_domains"
maxlength=
"255"
>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment