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
bfd104ac
Commit
bfd104ac
authored
Jul 05, 2016
by
Marko Jevtic
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Remove API constants
parent
b98bfc7f
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
125 additions
and
184 deletions
+125
-184
ecommerce/coupons/views.py
+1
-2
ecommerce/extensions/api/constants.py
+0
-52
ecommerce/extensions/api/data.py
+4
-5
ecommerce/extensions/api/v2/tests/views/test_baskets.py
+1
-2
ecommerce/extensions/api/v2/tests/views/test_coupons.py
+17
-17
ecommerce/extensions/api/v2/views/baskets.py
+14
-15
ecommerce/extensions/api/v2/views/coupons.py
+40
-66
ecommerce/extensions/api/v2/views/orders.py
+1
-2
ecommerce/extensions/checkout/mixins.py
+9
-10
ecommerce/extensions/offer/models.py
+4
-0
ecommerce/extensions/voucher/models.py
+14
-0
ecommerce/invoice/models.py
+8
-0
ecommerce/tests/mixins.py
+12
-13
No files found.
ecommerce/coupons/views.py
View file @
bfd104ac
...
@@ -18,7 +18,6 @@ from oscar.core.loading import get_class, get_model
...
@@ -18,7 +18,6 @@ from oscar.core.loading import get_class, get_model
from
ecommerce.core.url_utils
import
get_ecommerce_url
from
ecommerce.core.url_utils
import
get_ecommerce_url
from
ecommerce.core.views
import
StaffOnlyMixin
from
ecommerce.core.views
import
StaffOnlyMixin
from
ecommerce.extensions.api
import
exceptions
from
ecommerce.extensions.api
import
exceptions
from
ecommerce.extensions.api.constants
import
APIConstants
as
AC
from
ecommerce.extensions.basket.utils
import
prepare_basket
from
ecommerce.extensions.basket.utils
import
prepare_basket
from
ecommerce.extensions.checkout.mixins
import
EdxOrderPlacementMixin
from
ecommerce.extensions.checkout.mixins
import
EdxOrderPlacementMixin
...
@@ -184,7 +183,7 @@ class CouponRedeemView(EdxOrderPlacementMixin, View):
...
@@ -184,7 +183,7 @@ class CouponRedeemView(EdxOrderPlacementMixin, View):
return
render
(
request
,
template_name
,
{
'error'
:
_
(
'You are already enrolled in the course.'
)})
return
render
(
request
,
template_name
,
{
'error'
:
_
(
'You are already enrolled in the course.'
)})
basket
=
prepare_basket
(
request
,
product
,
voucher
)
basket
=
prepare_basket
(
request
,
product
,
voucher
)
if
basket
.
total_excl_tax
==
AC
.
FREE
:
if
basket
.
total_excl_tax
==
0
:
self
.
place_free_order
(
basket
)
self
.
place_free_order
(
basket
)
else
:
else
:
return
HttpResponseRedirect
(
reverse
(
'basket:summary'
))
return
HttpResponseRedirect
(
reverse
(
'basket:summary'
))
...
...
ecommerce/extensions/api/constants.py
deleted
100644 → 0
View file @
b98bfc7f
"""Ecommerce API constants."""
class
APIDictionaryKeys
(
object
):
"""Dictionary keys used repeatedly in the ecommerce API."""
BASKET_ID
=
u'id'
BENEFIT_TYPE
=
u'benefit_type'
BENEFIT_VALUE
=
u'benefit_value'
CATEGORY_IDS
=
u'category_ids'
CHECKOUT
=
u'checkout'
CLIENT
=
u'client'
CODE
=
u'code'
COUPON_ID
=
u'coupon_id'
END_DATE
=
u'end_date'
NOTE
=
u'note'
ORDER
=
u'order'
ORDER_NUMBER
=
u'number'
ORDER_TOTAL
=
u'total'
PAYMENT_DATA
=
u'payment_data'
PAYMENT_FORM_DATA
=
u'payment_form_data'
PAYMENT_PAGE_URL
=
u'payment_page_url'
PAYMENT_PROCESSOR_NAME
=
u'payment_processor_name'
PRICE
=
u'price'
PRODUCTS
=
u'products'
QUANTITY
=
u'quantity'
SHIPPING_CHARGE
=
u'shipping_charge'
SHIPPING_METHOD
=
u'shipping_method'
START_DATE
=
u'start_date'
STOCK_RECORD_IDS
=
u'stock_record_ids'
SKU
=
u'sku'
TITLE
=
u'title'
VOUCHER_TYPE
=
u'voucher_type'
class
APIConstants
(
object
):
"""Constants used throughout the ecommerce API."""
FREE
=
0
KEYS
=
APIDictionaryKeys
()
UPDATEABLE_VOUCHER_FIELDS
=
[
{
'request_data_key'
:
KEYS
.
END_DATE
,
'attribute'
:
'end_datetime'
},
{
'request_data_key'
:
KEYS
.
START_DATE
,
'attribute'
:
'start_datetime'
},
{
'request_data_key'
:
KEYS
.
TITLE
,
'attribute'
:
'name'
}
]
ecommerce/extensions/api/data.py
View file @
bfd104ac
...
@@ -4,7 +4,6 @@ import logging
...
@@ -4,7 +4,6 @@ import logging
from
oscar.core.loading
import
get_model
,
get_class
from
oscar.core.loading
import
get_model
,
get_class
from
ecommerce.extensions.api
import
exceptions
from
ecommerce.extensions.api
import
exceptions
from
ecommerce.extensions.api.constants
import
APIConstants
as
AC
NoShippingRequired
=
get_class
(
'shipping.methods'
,
'NoShippingRequired'
)
NoShippingRequired
=
get_class
(
'shipping.methods'
,
'NoShippingRequired'
)
OrderTotalCalculator
=
get_class
(
'checkout.calculators'
,
'OrderTotalCalculator'
)
OrderTotalCalculator
=
get_class
(
'checkout.calculators'
,
'OrderTotalCalculator'
)
...
@@ -39,10 +38,10 @@ def get_order_metadata(basket):
...
@@ -39,10 +38,10 @@ def get_order_metadata(basket):
total
=
OrderTotalCalculator
()
.
calculate
(
basket
,
shipping_charge
)
total
=
OrderTotalCalculator
()
.
calculate
(
basket
,
shipping_charge
)
metadata
=
{
metadata
=
{
AC
.
KEYS
.
ORDER_NUMBER
:
basket
.
order_number
,
'number'
:
basket
.
order_number
,
AC
.
KEYS
.
SHIPPING_METHOD
:
shipping_method
,
'shipping_method'
:
shipping_method
,
AC
.
KEYS
.
SHIPPING_CHARGE
:
shipping_charge
,
'shipping_charge'
:
shipping_charge
,
AC
.
KEYS
.
ORDER_TOTAL
:
total
,
'total'
:
total
,
}
}
return
metadata
return
metadata
ecommerce/extensions/api/v2/tests/views/test_baskets.py
View file @
bfd104ac
...
@@ -14,7 +14,6 @@ from oscar.test.factories import BasketFactory
...
@@ -14,7 +14,6 @@ from oscar.test.factories import BasketFactory
from
rest_framework.throttling
import
UserRateThrottle
from
rest_framework.throttling
import
UserRateThrottle
from
ecommerce.extensions.api
import
exceptions
as
api_exceptions
from
ecommerce.extensions.api
import
exceptions
as
api_exceptions
from
ecommerce.extensions.api.constants
import
APIConstants
as
AC
from
ecommerce.extensions.api.v2.tests.views
import
OrderDetailViewTestMixin
,
JSON_CONTENT_TYPE
from
ecommerce.extensions.api.v2.tests.views
import
OrderDetailViewTestMixin
,
JSON_CONTENT_TYPE
from
ecommerce.extensions.api.v2.views.baskets
import
BasketCreateView
from
ecommerce.extensions.api.v2.views.baskets
import
BasketCreateView
from
ecommerce.extensions.payment
import
exceptions
as
payment_exceptions
from
ecommerce.extensions.payment
import
exceptions
as
payment_exceptions
...
@@ -139,7 +138,7 @@ class BasketCreateViewTests(BasketCreationMixin, ThrottlingMixin, TransactionTes
...
@@ -139,7 +138,7 @@ class BasketCreateViewTests(BasketCreationMixin, ThrottlingMixin, TransactionTes
def
test_sku_missing
(
self
):
def
test_sku_missing
(
self
):
"""Test that requests without a SKU fail with appropriate messaging."""
"""Test that requests without a SKU fail with appropriate messaging."""
request_data
=
{
AC
.
KEYS
.
PRODUCTS
:
[{
'not-sku'
:
'foo'
}]}
request_data
=
{
'products'
:
[{
'not-sku'
:
'foo'
}]}
response
=
self
.
client
.
post
(
response
=
self
.
client
.
post
(
self
.
PATH
,
self
.
PATH
,
data
=
json
.
dumps
(
request_data
),
data
=
json
.
dumps
(
request_data
),
...
...
ecommerce/extensions/api/v2/tests/views/test_coupons.py
View file @
bfd104ac
...
@@ -18,7 +18,6 @@ from rest_framework import status
...
@@ -18,7 +18,6 @@ from rest_framework import status
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
,
CouponMixin
from
ecommerce.coupons.tests.mixins
import
CourseCatalogMockMixin
,
CouponMixin
from
ecommerce.courses.tests.factories
import
CourseFactory
from
ecommerce.courses.tests.factories
import
CourseFactory
from
ecommerce.extensions.api.constants
import
APIConstants
as
AC
from
ecommerce.extensions.api.v2.views.coupons
import
CouponViewSet
from
ecommerce.extensions.api.v2.views.coupons
import
CouponViewSet
from
ecommerce.extensions.catalogue.tests.mixins
import
CourseCatalogTestMixin
from
ecommerce.extensions.catalogue.tests.mixins
import
CourseCatalogTestMixin
from
ecommerce.extensions.voucher.models
import
CouponVouchers
from
ecommerce.extensions.voucher.models
import
CouponVouchers
...
@@ -230,9 +229,10 @@ class CouponViewSetTest(CouponMixin, CourseCatalogTestMixin, TestCase):
...
@@ -230,9 +229,10 @@ class CouponViewSetTest(CouponMixin, CourseCatalogTestMixin, TestCase):
"""Test the order creation."""
"""Test the order creation."""
self
.
create_coupon
(
partner
=
self
.
partner
)
self
.
create_coupon
(
partner
=
self
.
partner
)
self
.
assertEqual
(
self
.
response_data
[
AC
.
KEYS
.
BASKET_ID
],
1
)
self
.
assertDictEqual
(
self
.
assertEqual
(
self
.
response_data
[
AC
.
KEYS
.
ORDER
],
1
)
self
.
response_data
,
self
.
assertEqual
(
self
.
response_data
[
AC
.
KEYS
.
PAYMENT_DATA
][
AC
.
KEYS
.
PAYMENT_PROCESSOR_NAME
],
'Invoice'
)
{
'payment_data'
:
{
'payment_processor_name'
:
'Invoice'
},
'id'
:
1
,
'order'
:
1
,
'coupon_id'
:
3
}
)
self
.
assertEqual
(
Order
.
objects
.
count
(),
1
)
self
.
assertEqual
(
Order
.
objects
.
count
(),
1
)
self
.
assertEqual
(
Order
.
objects
.
first
()
.
status
,
'Complete'
)
self
.
assertEqual
(
Order
.
objects
.
first
()
.
status
,
'Complete'
)
...
@@ -243,7 +243,7 @@ class CouponViewSetTest(CouponMixin, CourseCatalogTestMixin, TestCase):
...
@@ -243,7 +243,7 @@ class CouponViewSetTest(CouponMixin, CourseCatalogTestMixin, TestCase):
"""Test the update data dictionary"""
"""Test the update data dictionary"""
data
=
{}
data
=
{}
for
field
in
AC
.
UPDATEABLE_VOUCHER_FIELDS
:
for
field
in
CouponVouchers
.
UPDATEABLE_VOUCHER_FIELDS
:
CouponViewSet
()
.
create_update_data_dict
(
CouponViewSet
()
.
create_update_data_dict
(
request_data
=
self
.
coupon_data
,
request_data
=
self
.
coupon_data
,
request_data_key
=
field
[
'request_data_key'
],
request_data_key
=
field
[
'request_data_key'
],
...
@@ -333,10 +333,10 @@ class CouponViewSetFunctionalTest(CouponMixin, CourseCatalogTestMixin, CourseCat
...
@@ -333,10 +333,10 @@ class CouponViewSetFunctionalTest(CouponMixin, CourseCatalogTestMixin, CourseCat
"""Test the response data given after the order was created."""
"""Test the response data given after the order was created."""
self
.
assertEqual
(
self
.
response
.
status_code
,
200
)
self
.
assertEqual
(
self
.
response
.
status_code
,
200
)
response_data
=
json
.
loads
(
self
.
response
.
content
)
response_data
=
json
.
loads
(
self
.
response
.
content
)
self
.
assert
Equal
(
response_data
[
AC
.
KEYS
.
COUPON_ID
],
5
)
self
.
assert
DictEqual
(
self
.
assertEqual
(
response_data
[
AC
.
KEYS
.
BASKET_ID
],
1
)
response_data
,
self
.
assertEqual
(
response_data
[
AC
.
KEYS
.
ORDER
],
1
)
{
'payment_data'
:
{
'payment_processor_name'
:
'Invoice'
},
'id'
:
1
,
'order'
:
1
,
'coupon_id'
:
5
}
self
.
assertEqual
(
response_data
[
AC
.
KEYS
.
PAYMENT_DATA
][
AC
.
KEYS
.
PAYMENT_PROCESSOR_NAME
],
'Invoice'
)
)
def
test_order
(
self
):
def
test_order
(
self
):
"""Test the order data after order creation."""
"""Test the order data after order creation."""
...
@@ -394,7 +394,7 @@ class CouponViewSetFunctionalTest(CouponMixin, CourseCatalogTestMixin, CourseCat
...
@@ -394,7 +394,7 @@ class CouponViewSetFunctionalTest(CouponMixin, CourseCatalogTestMixin, CourseCat
"""Test updating a coupon's title."""
"""Test updating a coupon's title."""
data
=
{
data
=
{
'id'
:
self
.
coupon
.
id
,
'id'
:
self
.
coupon
.
id
,
AC
.
KEYS
.
TITLE
:
'New title'
'title'
:
'New title'
}
}
response_data
=
self
.
get_response_json
(
response_data
=
self
.
get_response_json
(
'PUT'
,
'PUT'
,
...
@@ -412,8 +412,8 @@ class CouponViewSetFunctionalTest(CouponMixin, CourseCatalogTestMixin, CourseCat
...
@@ -412,8 +412,8 @@ class CouponViewSetFunctionalTest(CouponMixin, CourseCatalogTestMixin, CourseCat
"""Test that updating a coupons date updates all of it's voucher dates."""
"""Test that updating a coupons date updates all of it's voucher dates."""
data
=
{
data
=
{
'id'
:
self
.
coupon
.
id
,
'id'
:
self
.
coupon
.
id
,
AC
.
KEYS
.
START_DATE
:
'2030-01-01'
,
'start_date'
:
'2030-01-01'
,
AC
.
KEYS
.
END_DATE
:
'2035-01-01'
'end_date'
:
'2035-01-01'
}
}
response_data
=
self
.
get_response_json
(
response_data
=
self
.
get_response_json
(
'PUT'
,
'PUT'
,
...
@@ -433,7 +433,7 @@ class CouponViewSetFunctionalTest(CouponMixin, CourseCatalogTestMixin, CourseCat
...
@@ -433,7 +433,7 @@ class CouponViewSetFunctionalTest(CouponMixin, CourseCatalogTestMixin, CourseCat
path
=
reverse
(
'api:v2:coupons-detail'
,
kwargs
=
{
'pk'
:
self
.
coupon
.
id
})
path
=
reverse
(
'api:v2:coupons-detail'
,
kwargs
=
{
'pk'
:
self
.
coupon
.
id
})
data
=
{
data
=
{
'id'
:
self
.
coupon
.
id
,
'id'
:
self
.
coupon
.
id
,
AC
.
KEYS
.
BENEFIT_VALUE
:
50
'benefit_value'
:
50
}
}
self
.
client
.
put
(
path
,
json
.
dumps
(
data
),
'application/json'
)
self
.
client
.
put
(
path
,
json
.
dumps
(
data
),
'application/json'
)
...
@@ -447,7 +447,7 @@ class CouponViewSetFunctionalTest(CouponMixin, CourseCatalogTestMixin, CourseCat
...
@@ -447,7 +447,7 @@ class CouponViewSetFunctionalTest(CouponMixin, CourseCatalogTestMixin, CourseCat
path
=
reverse
(
'api:v2:coupons-detail'
,
kwargs
=
{
'pk'
:
self
.
coupon
.
id
})
path
=
reverse
(
'api:v2:coupons-detail'
,
kwargs
=
{
'pk'
:
self
.
coupon
.
id
})
data
=
{
data
=
{
'id'
:
self
.
coupon
.
id
,
'id'
:
self
.
coupon
.
id
,
AC
.
KEYS
.
CATEGORY_IDS
:
[
category
.
id
]
'category_ids'
:
[
category
.
id
]
}
}
self
.
client
.
put
(
path
,
json
.
dumps
(
data
),
'application/json'
)
self
.
client
.
put
(
path
,
json
.
dumps
(
data
),
'application/json'
)
...
@@ -461,7 +461,7 @@ class CouponViewSetFunctionalTest(CouponMixin, CourseCatalogTestMixin, CourseCat
...
@@ -461,7 +461,7 @@ class CouponViewSetFunctionalTest(CouponMixin, CourseCatalogTestMixin, CourseCat
client
=
'Člient 123'
client
=
'Člient 123'
data
=
{
data
=
{
'id'
:
self
.
coupon
.
id
,
'id'
:
self
.
coupon
.
id
,
AC
.
KEYS
.
CLIENT
:
client
'client'
:
client
}
}
self
.
client
.
put
(
path
,
json
.
dumps
(
data
),
'application/json'
)
self
.
client
.
put
(
path
,
json
.
dumps
(
data
),
'application/json'
)
...
@@ -475,7 +475,7 @@ class CouponViewSetFunctionalTest(CouponMixin, CourseCatalogTestMixin, CourseCat
...
@@ -475,7 +475,7 @@ class CouponViewSetFunctionalTest(CouponMixin, CourseCatalogTestMixin, CourseCat
path
=
reverse
(
'api:v2:coupons-detail'
,
kwargs
=
{
'pk'
:
self
.
coupon
.
id
})
path
=
reverse
(
'api:v2:coupons-detail'
,
kwargs
=
{
'pk'
:
self
.
coupon
.
id
})
data
=
{
data
=
{
'id'
:
self
.
coupon
.
id
,
'id'
:
self
.
coupon
.
id
,
AC
.
KEYS
.
PRICE
:
77
'price'
:
77
}
}
self
.
client
.
put
(
path
,
json
.
dumps
(
data
),
'application/json'
)
self
.
client
.
put
(
path
,
json
.
dumps
(
data
),
'application/json'
)
...
@@ -489,7 +489,7 @@ class CouponViewSetFunctionalTest(CouponMixin, CourseCatalogTestMixin, CourseCat
...
@@ -489,7 +489,7 @@ class CouponViewSetFunctionalTest(CouponMixin, CourseCatalogTestMixin, CourseCat
note
=
'Thiš iš the tešt note.'
note
=
'Thiš iš the tešt note.'
data
=
{
data
=
{
'id'
:
self
.
coupon
.
id
,
'id'
:
self
.
coupon
.
id
,
AC
.
KEYS
.
NOTE
:
note
'note'
:
note
}
}
self
.
client
.
put
(
path
,
json
.
dumps
(
data
),
'application/json'
)
self
.
client
.
put
(
path
,
json
.
dumps
(
data
),
'application/json'
)
...
...
ecommerce/extensions/api/v2/views/baskets.py
View file @
bfd104ac
...
@@ -14,7 +14,6 @@ from rest_framework.response import Response
...
@@ -14,7 +14,6 @@ from rest_framework.response import Response
from
ecommerce.extensions.analytics.utils
import
audit_log
from
ecommerce.extensions.analytics.utils
import
audit_log
from
ecommerce.extensions.api
import
data
as
data_api
,
exceptions
as
api_exceptions
from
ecommerce.extensions.api
import
data
as
data_api
,
exceptions
as
api_exceptions
from
ecommerce.extensions.api.constants
import
APIConstants
as
AC
from
ecommerce.extensions.api.serializers
import
OrderSerializer
from
ecommerce.extensions.api.serializers
import
OrderSerializer
from
ecommerce.extensions.checkout.mixins
import
EdxOrderPlacementMixin
from
ecommerce.extensions.checkout.mixins
import
EdxOrderPlacementMixin
from
ecommerce.extensions.payment
import
exceptions
as
payment_exceptions
from
ecommerce.extensions.payment
import
exceptions
as
payment_exceptions
...
@@ -134,11 +133,11 @@ class BasketCreateView(EdxOrderPlacementMixin, generics.CreateAPIView):
...
@@ -134,11 +133,11 @@ class BasketCreateView(EdxOrderPlacementMixin, generics.CreateAPIView):
basket
=
Basket
.
create_basket
(
request
.
site
,
request
.
user
)
basket
=
Basket
.
create_basket
(
request
.
site
,
request
.
user
)
basket_id
=
basket
.
id
basket_id
=
basket
.
id
requested_products
=
request
.
data
.
get
(
AC
.
KEYS
.
PRODUCTS
)
requested_products
=
request
.
data
.
get
(
'products'
)
if
requested_products
:
if
requested_products
:
for
requested_product
in
requested_products
:
for
requested_product
in
requested_products
:
# Ensure the requested products exist
# Ensure the requested products exist
sku
=
requested_product
.
get
(
AC
.
KEYS
.
SKU
)
sku
=
requested_product
.
get
(
'sku'
)
if
sku
:
if
sku
:
try
:
try
:
product
=
data_api
.
get_product
(
sku
)
product
=
data_api
.
get_product
(
sku
)
...
@@ -173,9 +172,9 @@ class BasketCreateView(EdxOrderPlacementMixin, generics.CreateAPIView):
...
@@ -173,9 +172,9 @@ class BasketCreateView(EdxOrderPlacementMixin, generics.CreateAPIView):
api_exceptions
.
PRODUCT_OBJECTS_MISSING_USER_MESSAGE
api_exceptions
.
PRODUCT_OBJECTS_MISSING_USER_MESSAGE
)
)
if
request
.
data
.
get
(
AC
.
KEYS
.
CHECKOUT
)
is
True
:
if
request
.
data
.
get
(
'checkout'
)
is
True
:
# Begin the checkout process, if requested, with the requested payment processor.
# Begin the checkout process, if requested, with the requested payment processor.
payment_processor_name
=
request
.
data
.
get
(
AC
.
KEYS
.
PAYMENT_PROCESSOR_NAME
)
payment_processor_name
=
request
.
data
.
get
(
'payment_processor_name'
)
if
payment_processor_name
:
if
payment_processor_name
:
try
:
try
:
payment_processor
=
get_processor_class_by_name
(
payment_processor_name
)
payment_processor
=
get_processor_class_by_name
(
payment_processor_name
)
...
@@ -229,20 +228,20 @@ class BasketCreateView(EdxOrderPlacementMixin, generics.CreateAPIView):
...
@@ -229,20 +228,20 @@ class BasketCreateView(EdxOrderPlacementMixin, generics.CreateAPIView):
response_data
=
self
.
_generate_basic_response
(
basket
)
response_data
=
self
.
_generate_basic_response
(
basket
)
if
basket
.
total_excl_tax
==
AC
.
FREE
:
if
basket
.
total_excl_tax
==
0
:
order
=
self
.
place_free_order
(
basket
)
order
=
self
.
place_free_order
(
basket
)
# Note: Our order serializer could be used here, but in an effort to pare down the information
# Note: Our order serializer could be used here, but in an effort to pare down the information
# returned by this endpoint, simply returning the order number will suffice for now.
# returned by this endpoint, simply returning the order number will suffice for now.
response_data
[
AC
.
KEYS
.
ORDER
]
=
{
AC
.
KEYS
.
ORDER_NUMBER
:
order
.
number
}
response_data
[
'order'
]
=
{
'number'
:
order
.
number
}
else
:
else
:
parameters
=
payment_processor
.
get_transaction_parameters
(
basket
,
request
=
self
.
request
)
parameters
=
payment_processor
.
get_transaction_parameters
(
basket
,
request
=
self
.
request
)
payment_page_url
=
parameters
.
pop
(
'payment_page_url'
)
payment_page_url
=
parameters
.
pop
(
'payment_page_url'
)
response_data
[
AC
.
KEYS
.
PAYMENT_DATA
]
=
{
response_data
[
'payment_data'
]
=
{
AC
.
KEYS
.
PAYMENT_PROCESSOR_NAME
:
payment_processor
.
NAME
,
'payment_processor_name'
:
payment_processor
.
NAME
,
AC
.
KEYS
.
PAYMENT_FORM_DATA
:
parameters
,
'payment_form_data'
:
parameters
,
AC
.
KEYS
.
PAYMENT_PAGE_URL
:
payment_page_url
,
'payment_page_url'
:
payment_page_url
,
}
}
return
response_data
return
response_data
...
@@ -261,9 +260,9 @@ class BasketCreateView(EdxOrderPlacementMixin, generics.CreateAPIView):
...
@@ -261,9 +260,9 @@ class BasketCreateView(EdxOrderPlacementMixin, generics.CreateAPIView):
# Note: A basket serializer could be used here, but in an effort to pare down the information
# Note: A basket serializer could be used here, but in an effort to pare down the information
# returned by this endpoint, simply returning the basket ID will suffice for now.
# returned by this endpoint, simply returning the basket ID will suffice for now.
response_data
=
{
response_data
=
{
AC
.
KEYS
.
BASKET_ID
:
basket
.
id
,
'id'
:
basket
.
id
,
AC
.
KEYS
.
ORDER
:
None
,
'order'
:
None
,
AC
.
KEYS
.
PAYMENT_DATA
:
None
,
'payment_data'
:
None
,
}
}
return
response_data
return
response_data
...
@@ -284,7 +283,7 @@ class OrderByBasketRetrieveView(generics.RetrieveAPIView):
...
@@ -284,7 +283,7 @@ class OrderByBasketRetrieveView(generics.RetrieveAPIView):
"""Allow the viewing of Orders by Basket. """
"""Allow the viewing of Orders by Basket. """
permission_classes
=
(
IsAuthenticated
,)
permission_classes
=
(
IsAuthenticated
,)
serializer_class
=
OrderSerializer
serializer_class
=
OrderSerializer
lookup_field
=
AC
.
KEYS
.
ORDER_NUMBER
lookup_field
=
'number'
queryset
=
Order
.
objects
.
all
()
queryset
=
Order
.
objects
.
all
()
def
dispatch
(
self
,
request
,
*
args
,
**
kwargs
):
def
dispatch
(
self
,
request
,
*
args
,
**
kwargs
):
...
...
ecommerce/extensions/api/v2/views/coupons.py
View file @
bfd104ac
...
@@ -16,7 +16,6 @@ from rest_framework.response import Response
...
@@ -16,7 +16,6 @@ from rest_framework.response import Response
from
ecommerce.core.models
import
BusinessClient
from
ecommerce.core.models
import
BusinessClient
from
ecommerce.coupons.utils
import
prepare_course_seat_types
from
ecommerce.coupons.utils
import
prepare_course_seat_types
from
ecommerce.extensions.api
import
data
as
data_api
from
ecommerce.extensions.api
import
data
as
data_api
from
ecommerce.extensions.api.constants
import
APIConstants
as
AC
from
ecommerce.extensions.api.filters
import
ProductFilter
from
ecommerce.extensions.api.filters
import
ProductFilter
from
ecommerce.extensions.api.serializers
import
CategorySerializer
,
CouponSerializer
,
CouponListSerializer
from
ecommerce.extensions.api.serializers
import
CategorySerializer
,
CouponSerializer
,
CouponListSerializer
from
ecommerce.extensions.basket.utils
import
prepare_basket
from
ecommerce.extensions.basket.utils
import
prepare_basket
...
@@ -39,31 +38,6 @@ Range = Range = get_model('offer', 'Range')
...
@@ -39,31 +38,6 @@ Range = Range = get_model('offer', 'Range')
StockRecord
=
get_model
(
'partner'
,
'StockRecord'
)
StockRecord
=
get_model
(
'partner'
,
'StockRecord'
)
Voucher
=
get_model
(
'voucher'
,
'Voucher'
)
Voucher
=
get_model
(
'voucher'
,
'Voucher'
)
CATALOG_QUERY
=
'catalog_query'
CLIENT
=
'client'
COURSE_SEAT_TYPES
=
'course_seat_types'
EMAIL_DOMAINS
=
'email_domains'
INVOICE_DISCOUNT_TYPE
=
'invoice_discount_type'
INVOICE_DISCOUNT_VALUE
=
'invoice_discount_value'
INVOICE_NUMBER
=
'invoice_number'
INVOICE_PAYMENT_DATE
=
'invoice_payment_date'
INVOICE_TYPE
=
'invoice_type'
TAX_DEDUCTED_SOURCE
=
'tax_deducted_source'
UPDATEABLE_INVOICE_FIELDS
=
[
INVOICE_DISCOUNT_TYPE
,
INVOICE_DISCOUNT_VALUE
,
INVOICE_NUMBER
,
INVOICE_PAYMENT_DATE
,
INVOICE_TYPE
,
TAX_DEDUCTED_SOURCE
,
]
UPDATABLE_RANGE_FIELDS
=
[
CATALOG_QUERY
,
COURSE_SEAT_TYPES
,
]
class
CouponViewSet
(
EdxOrderPlacementMixin
,
viewsets
.
ModelViewSet
):
class
CouponViewSet
(
EdxOrderPlacementMixin
,
viewsets
.
ModelViewSet
):
""" Coupon resource. """
""" Coupon resource. """
...
@@ -81,7 +55,7 @@ class CouponViewSet(EdxOrderPlacementMixin, viewsets.ModelViewSet):
...
@@ -81,7 +55,7 @@ class CouponViewSet(EdxOrderPlacementMixin, viewsets.ModelViewSet):
""" Retrieve the invoice information from the request data. """
""" Retrieve the invoice information from the request data. """
invoice_data
=
{}
invoice_data
=
{}
for
field
in
UPDATEABLE_INVOICE_FIELDS
:
for
field
in
Invoice
.
UPDATEABLE_INVOICE_FIELDS
:
self
.
create_update_data_dict
(
self
.
create_update_data_dict
(
request_data
=
request_data
,
request_data
=
request_data
,
request_data_key
=
field
,
request_data_key
=
field
,
...
@@ -113,25 +87,25 @@ class CouponViewSet(EdxOrderPlacementMixin, viewsets.ModelViewSet):
...
@@ -113,25 +87,25 @@ class CouponViewSet(EdxOrderPlacementMixin, viewsets.ModelViewSet):
500 if an error occurs when attempting to create a coupon.
500 if an error occurs when attempting to create a coupon.
"""
"""
with
transaction
.
atomic
():
with
transaction
.
atomic
():
title
=
request
.
data
[
AC
.
KEYS
.
TITLE
]
title
=
request
.
data
.
get
(
'title'
)
client_username
=
request
.
data
[
CLIENT
]
client_username
=
request
.
data
.
get
(
'client'
)
stock_record_ids
=
request
.
data
.
get
(
AC
.
KEYS
.
STOCK_RECORD_IDS
)
stock_record_ids
=
request
.
data
.
get
(
'stock_record_ids'
)
start_date
=
dateutil
.
parser
.
parse
(
request
.
data
[
AC
.
KEYS
.
START_DATE
]
)
start_date
=
dateutil
.
parser
.
parse
(
request
.
data
.
get
(
'start_date'
)
)
end_date
=
dateutil
.
parser
.
parse
(
request
.
data
[
AC
.
KEYS
.
END_DATE
]
)
end_date
=
dateutil
.
parser
.
parse
(
request
.
data
.
get
(
'end_date'
)
)
code
=
request
.
data
[
AC
.
KEYS
.
CODE
]
code
=
request
.
data
.
get
(
'code'
)
benefit_type
=
request
.
data
[
AC
.
KEYS
.
BENEFIT_TYPE
]
benefit_type
=
request
.
data
.
get
(
'benefit_type'
)
benefit_value
=
request
.
data
[
AC
.
KEYS
.
BENEFIT_VALUE
]
benefit_value
=
request
.
data
.
get
(
'benefit_value'
)
voucher_type
=
request
.
data
[
AC
.
KEYS
.
VOUCHER_TYPE
]
voucher_type
=
request
.
data
.
get
(
'voucher_type'
)
quantity
=
request
.
data
[
AC
.
KEYS
.
QUANTITY
]
quantity
=
request
.
data
.
get
(
'quantity'
)
price
=
request
.
data
[
AC
.
KEYS
.
PRICE
]
price
=
request
.
data
.
get
(
'price'
)
partner
=
request
.
site
.
siteconfiguration
.
partner
partner
=
request
.
site
.
siteconfiguration
.
partner
categories
=
Category
.
objects
.
filter
(
id__in
=
request
.
data
[
AC
.
KEYS
.
CATEGORY_IDS
]
)
categories
=
Category
.
objects
.
filter
(
id__in
=
request
.
data
.
get
(
'category_ids'
)
)
client
,
__
=
BusinessClient
.
objects
.
get_or_create
(
name
=
client_username
)
client
,
__
=
BusinessClient
.
objects
.
get_or_create
(
name
=
client_username
)
note
=
request
.
data
.
get
(
'note'
)
note
=
request
.
data
.
get
(
'note'
)
max_uses
=
request
.
data
.
get
(
'max_uses'
)
max_uses
=
request
.
data
.
get
(
'max_uses'
)
catalog_query
=
request
.
data
.
get
(
CATALOG_QUERY
)
catalog_query
=
request
.
data
.
get
(
'catalog_query'
)
course_seat_types
=
request
.
data
.
get
(
COURSE_SEAT_TYPES
)
course_seat_types
=
request
.
data
.
get
(
'course_seat_types'
)
email_domains
=
request
.
data
.
get
(
EMAIL_DOMAINS
)
email_domains
=
request
.
data
.
get
(
'email_domains'
)
if
code
:
if
code
:
try
:
try
:
...
@@ -294,23 +268,23 @@ class CouponViewSet(EdxOrderPlacementMixin, viewsets.ModelViewSet):
...
@@ -294,23 +268,23 @@ class CouponViewSet(EdxOrderPlacementMixin, viewsets.ModelViewSet):
order_metadata
=
data_api
.
get_order_metadata
(
basket
)
order_metadata
=
data_api
.
get_order_metadata
(
basket
)
response_data
=
{
response_data
=
{
AC
.
KEYS
.
COUPON_ID
:
coupon_id
,
'coupon_id'
:
coupon_id
,
AC
.
KEYS
.
BASKET_ID
:
basket
.
id
,
'id'
:
basket
.
id
,
AC
.
KEYS
.
ORDER
:
None
,
'order'
:
None
,
AC
.
KEYS
.
PAYMENT_DATA
:
None
,
'payment_data'
:
None
,
}
}
basket
.
freeze
()
basket
.
freeze
()
order
=
self
.
handle_order_placement
(
order
=
self
.
handle_order_placement
(
order_number
=
order_metadata
[
AC
.
KEYS
.
ORDER_NUMBER
],
user
=
basket
.
owner
,
basket
=
basket
,
basket
=
basket
,
shipping_address
=
None
,
shipping_method
=
order_metadata
[
AC
.
KEYS
.
SHIPPING_METHOD
],
shipping_charge
=
order_metadata
[
AC
.
KEYS
.
SHIPPING_CHARGE
],
billing_address
=
None
,
billing_address
=
None
,
order_total
=
order_metadata
[
AC
.
KEYS
.
ORDER_TOTAL
],
order_number
=
order_metadata
[
'number'
],
request
=
request
order_total
=
order_metadata
[
'total'
],
request
=
request
,
shipping_address
=
None
,
shipping_charge
=
order_metadata
[
'shipping_charge'
],
shipping_method
=
order_metadata
[
'shipping_method'
],
user
=
basket
.
owner
)
)
# Invoice payment processor invocation.
# Invoice payment processor invocation.
...
@@ -318,14 +292,14 @@ class CouponViewSet(EdxOrderPlacementMixin, viewsets.ModelViewSet):
...
@@ -318,14 +292,14 @@ class CouponViewSet(EdxOrderPlacementMixin, viewsets.ModelViewSet):
payment_processor
()
.
handle_processor_response
(
payment_processor
()
.
handle_processor_response
(
response
=
{},
order
=
order
,
business_client
=
client
,
invoice_data
=
invoice_data
response
=
{},
order
=
order
,
business_client
=
client
,
invoice_data
=
invoice_data
)
)
response_data
[
AC
.
KEYS
.
PAYMENT_DATA
]
=
{
response_data
[
'payment_data'
]
=
{
AC
.
KEYS
.
PAYMENT_PROCESSOR_NAME
:
'Invoice'
'payment_processor_name'
:
'Invoice'
}
}
response_data
[
AC
.
KEYS
.
ORDER
]
=
order
.
id
response_data
[
'order'
]
=
order
.
id
logger
.
info
(
logger
.
info
(
'Created new order number [
%
s] from basket [
%
d]'
,
'Created new order number [
%
s] from basket [
%
d]'
,
order_metadata
[
AC
.
KEYS
.
ORDER_NUMBER
],
order_metadata
[
'number'
],
basket
.
id
basket
.
id
)
)
...
@@ -340,7 +314,7 @@ class CouponViewSet(EdxOrderPlacementMixin, viewsets.ModelViewSet):
...
@@ -340,7 +314,7 @@ class CouponViewSet(EdxOrderPlacementMixin, viewsets.ModelViewSet):
baskets
=
Basket
.
objects
.
filter
(
lines__product_id
=
coupon
.
id
,
status
=
Basket
.
SUBMITTED
)
baskets
=
Basket
.
objects
.
filter
(
lines__product_id
=
coupon
.
id
,
status
=
Basket
.
SUBMITTED
)
data
=
{}
data
=
{}
for
field
in
AC
.
UPDATEABLE_VOUCHER_FIELDS
:
for
field
in
CouponVouchers
.
UPDATEABLE_VOUCHER_FIELDS
:
self
.
create_update_data_dict
(
self
.
create_update_data_dict
(
request_data
=
request
.
data
,
request_data
=
request
.
data
,
request_data_key
=
field
[
'request_data_key'
],
request_data_key
=
field
[
'request_data_key'
],
...
@@ -353,7 +327,7 @@ class CouponViewSet(EdxOrderPlacementMixin, viewsets.ModelViewSet):
...
@@ -353,7 +327,7 @@ class CouponViewSet(EdxOrderPlacementMixin, viewsets.ModelViewSet):
range_data
=
{}
range_data
=
{}
for
field
in
UPDATABLE_RANGE_FIELDS
:
for
field
in
Range
.
UPDATABLE_RANGE_FIELDS
:
self
.
create_update_data_dict
(
self
.
create_update_data_dict
(
request_data
=
request
.
data
,
request_data
=
request
.
data
,
request_data_key
=
field
,
request_data_key
=
field
,
...
@@ -365,28 +339,28 @@ class CouponViewSet(EdxOrderPlacementMixin, viewsets.ModelViewSet):
...
@@ -365,28 +339,28 @@ class CouponViewSet(EdxOrderPlacementMixin, viewsets.ModelViewSet):
voucher_range
=
vouchers
.
first
()
.
offers
.
first
()
.
benefit
.
range
voucher_range
=
vouchers
.
first
()
.
offers
.
first
()
.
benefit
.
range
Range
.
objects
.
filter
(
id
=
voucher_range
.
id
)
.
update
(
**
range_data
)
Range
.
objects
.
filter
(
id
=
voucher_range
.
id
)
.
update
(
**
range_data
)
benefit_value
=
request
.
data
.
get
(
AC
.
KEYS
.
BENEFIT_VALUE
,
'
'
)
benefit_value
=
request
.
data
.
get
(
'benefit_value
'
)
if
benefit_value
:
if
benefit_value
:
self
.
update_coupon_benefit_value
(
benefit_value
=
benefit_value
,
vouchers
=
vouchers
,
coupon
=
coupon
)
self
.
update_coupon_benefit_value
(
benefit_value
=
benefit_value
,
vouchers
=
vouchers
,
coupon
=
coupon
)
category_ids
=
request
.
data
.
get
(
AC
.
KEYS
.
CATEGORY_IDS
,
'
'
)
category_ids
=
request
.
data
.
get
(
'category_ids
'
)
if
category_ids
:
if
category_ids
:
self
.
update_coupon_category
(
category_ids
=
category_ids
,
coupon
=
coupon
)
self
.
update_coupon_category
(
category_ids
=
category_ids
,
coupon
=
coupon
)
client_username
=
request
.
data
.
get
(
AC
.
KEYS
.
CLIENT
,
'
'
)
client_username
=
request
.
data
.
get
(
'client
'
)
if
client_username
:
if
client_username
:
self
.
update_coupon_client
(
baskets
=
baskets
,
client_username
=
client_username
)
self
.
update_coupon_client
(
baskets
=
baskets
,
client_username
=
client_username
)
coupon_price
=
request
.
data
.
get
(
AC
.
KEYS
.
PRICE
,
'
'
)
coupon_price
=
request
.
data
.
get
(
'price
'
)
if
coupon_price
:
if
coupon_price
:
StockRecord
.
objects
.
filter
(
product
=
coupon
)
.
update
(
price_excl_tax
=
coupon_price
)
StockRecord
.
objects
.
filter
(
product
=
coupon
)
.
update
(
price_excl_tax
=
coupon_price
)
note
=
request
.
data
.
get
(
AC
.
KEYS
.
NOTE
,
None
)
note
=
request
.
data
.
get
(
'note'
)
if
note
is
not
None
:
if
note
is
not
None
:
coupon
.
attr
.
note
=
note
coupon
.
attr
.
note
=
note
coupon
.
save
()
coupon
.
save
()
email_domains
=
request
.
data
.
get
(
EMAIL_DOMAINS
)
email_domains
=
request
.
data
.
get
(
'email_domains'
)
# Need to update for individual vouchers because in case of multiple
# Need to update for individual vouchers because in case of multiple
# multi-use voucher each voucher will have individual offer.
# multi-use voucher each voucher will have individual offer.
for
voucher
in
vouchers
.
all
():
for
voucher
in
vouchers
.
all
():
...
@@ -409,7 +383,7 @@ class CouponViewSet(EdxOrderPlacementMixin, viewsets.ModelViewSet):
...
@@ -409,7 +383,7 @@ class CouponViewSet(EdxOrderPlacementMixin, viewsets.ModelViewSet):
if
request_data_key
in
request_data
:
if
request_data_key
in
request_data
:
value
=
request_data
.
get
(
request_data_key
)
value
=
request_data
.
get
(
request_data_key
)
update_dict
[
update_dict_key
]
=
prepare_course_seat_types
(
value
)
\
update_dict
[
update_dict_key
]
=
prepare_course_seat_types
(
value
)
\
if
update_dict_key
==
COURSE_SEAT_TYPES
else
value
if
update_dict_key
==
'course_seat_types'
else
value
def
update_coupon_benefit_value
(
self
,
benefit_value
,
coupon
,
vouchers
):
def
update_coupon_benefit_value
(
self
,
benefit_value
,
coupon
,
vouchers
):
"""
"""
...
...
ecommerce/extensions/api/v2/views/orders.py
View file @
bfd104ac
...
@@ -9,7 +9,6 @@ from rest_framework.permissions import IsAuthenticated, DjangoModelPermissions
...
@@ -9,7 +9,6 @@ from rest_framework.permissions import IsAuthenticated, DjangoModelPermissions
from
rest_framework.response
import
Response
from
rest_framework.response
import
Response
from
ecommerce.extensions.api
import
serializers
from
ecommerce.extensions.api
import
serializers
from
ecommerce.extensions.api.constants
import
APIConstants
as
AC
from
ecommerce.extensions.api.filters
import
OrderFilter
from
ecommerce.extensions.api.filters
import
OrderFilter
from
ecommerce.extensions.api.permissions
import
IsStaffOrOwner
from
ecommerce.extensions.api.permissions
import
IsStaffOrOwner
from
ecommerce.extensions.api.throttles
import
ServiceUserThrottle
from
ecommerce.extensions.api.throttles
import
ServiceUserThrottle
...
@@ -21,7 +20,7 @@ Order = get_model('order', 'Order')
...
@@ -21,7 +20,7 @@ Order = get_model('order', 'Order')
class
OrderViewSet
(
viewsets
.
ReadOnlyModelViewSet
):
class
OrderViewSet
(
viewsets
.
ReadOnlyModelViewSet
):
lookup_field
=
AC
.
KEYS
.
ORDER_NUMBER
lookup_field
=
'number'
permission_classes
=
(
IsAuthenticated
,
IsStaffOrOwner
,
DjangoModelPermissions
,)
permission_classes
=
(
IsAuthenticated
,
IsStaffOrOwner
,
DjangoModelPermissions
,)
queryset
=
Order
.
objects
.
all
()
queryset
=
Order
.
objects
.
all
()
serializer_class
=
serializers
.
OrderSerializer
serializer_class
=
serializers
.
OrderSerializer
...
...
ecommerce/extensions/checkout/mixins.py
View file @
bfd104ac
...
@@ -12,7 +12,6 @@ import waffle
...
@@ -12,7 +12,6 @@ import waffle
from
ecommerce.extensions.analytics.utils
import
audit_log
from
ecommerce.extensions.analytics.utils
import
audit_log
from
ecommerce.extensions.api
import
data
as
data_api
from
ecommerce.extensions.api
import
data
as
data_api
from
ecommerce.extensions.api.constants
import
APIConstants
as
AC
from
ecommerce.extensions.checkout.exceptions
import
BasketNotFreeError
from
ecommerce.extensions.checkout.exceptions
import
BasketNotFreeError
from
ecommerce.extensions.customer.utils
import
Dispatcher
from
ecommerce.extensions.customer.utils
import
Dispatcher
...
@@ -132,7 +131,7 @@ class EdxOrderPlacementMixin(OrderPlacementMixin):
...
@@ -132,7 +131,7 @@ class EdxOrderPlacementMixin(OrderPlacementMixin):
BasketNotFreeError: if the basket is not free.
BasketNotFreeError: if the basket is not free.
"""
"""
if
basket
.
total_incl_tax
!=
AC
.
FREE
:
if
basket
.
total_incl_tax
!=
0
:
raise
BasketNotFreeError
raise
BasketNotFreeError
basket
.
freeze
()
basket
.
freeze
()
...
@@ -141,22 +140,22 @@ class EdxOrderPlacementMixin(OrderPlacementMixin):
...
@@ -141,22 +140,22 @@ class EdxOrderPlacementMixin(OrderPlacementMixin):
logger
.
info
(
logger
.
info
(
'Preparing to place order [
%
s] for the contents of basket [
%
d]'
,
'Preparing to place order [
%
s] for the contents of basket [
%
d]'
,
order_metadata
[
AC
.
KEYS
.
ORDER_NUMBER
],
order_metadata
[
'number'
],
basket
.
id
,
basket
.
id
,
)
)
# Place an order. If order placement succeeds, the order is committed
# Place an order. If order placement succeeds, the order is committed
# to the database so that it can be fulfilled asynchronously.
# to the database so that it can be fulfilled asynchronously.
order
=
self
.
handle_order_placement
(
order
=
self
.
handle_order_placement
(
order_number
=
order_metadata
[
AC
.
KEYS
.
ORDER_NUMBER
],
user
=
basket
.
owner
,
basket
=
basket
,
basket
=
basket
,
shipping_address
=
None
,
shipping_method
=
order_metadata
[
AC
.
KEYS
.
SHIPPING_METHOD
],
shipping_charge
=
order_metadata
[
AC
.
KEYS
.
SHIPPING_CHARGE
],
billing_address
=
None
,
billing_address
=
None
,
order_total
=
order_metadata
[
AC
.
KEYS
.
ORDER_TOTAL
],
order_number
=
order_metadata
[
'number'
],
request
=
request
order_total
=
order_metadata
[
'total'
],
request
=
request
,
shipping_address
=
None
,
shipping_charge
=
order_metadata
[
'shipping_charge'
],
shipping_method
=
order_metadata
[
'shipping_method'
],
user
=
basket
.
owner
)
)
return
order
return
order
...
...
ecommerce/extensions/offer/models.py
View file @
bfd104ac
...
@@ -32,6 +32,10 @@ class ConditionalOffer(AbstractConditionalOffer):
...
@@ -32,6 +32,10 @@ class ConditionalOffer(AbstractConditionalOffer):
class
Range
(
AbstractRange
):
class
Range
(
AbstractRange
):
UPDATABLE_RANGE_FIELDS
=
[
'catalog_query'
,
'course_seat_types'
,
]
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
.
CharField
(
max_length
=
255
,
blank
=
True
,
null
=
True
)
catalog_query
=
models
.
CharField
(
max_length
=
255
,
blank
=
True
,
null
=
True
)
course_seat_types
=
models
.
CharField
(
max_length
=
255
,
blank
=
True
,
null
=
True
)
course_seat_types
=
models
.
CharField
(
max_length
=
255
,
blank
=
True
,
null
=
True
)
...
...
ecommerce/extensions/voucher/models.py
View file @
bfd104ac
...
@@ -3,6 +3,20 @@ from django.db import models
...
@@ -3,6 +3,20 @@ from django.db import models
class
CouponVouchers
(
models
.
Model
):
class
CouponVouchers
(
models
.
Model
):
UPDATEABLE_VOUCHER_FIELDS
=
[
{
'request_data_key'
:
'end_date'
,
'attribute'
:
'end_datetime'
},
{
'request_data_key'
:
'start_date'
,
'attribute'
:
'start_datetime'
},
{
'request_data_key'
:
'title'
,
'attribute'
:
'name'
}
]
coupon
=
models
.
ForeignKey
(
'catalogue.Product'
,
related_name
=
'coupon_vouchers'
)
coupon
=
models
.
ForeignKey
(
'catalogue.Product'
,
related_name
=
'coupon_vouchers'
)
vouchers
=
models
.
ManyToManyField
(
'voucher.Voucher'
,
blank
=
True
,
related_name
=
'coupon_vouchers'
)
vouchers
=
models
.
ManyToManyField
(
'voucher.Voucher'
,
blank
=
True
,
related_name
=
'coupon_vouchers'
)
...
...
ecommerce/invoice/models.py
View file @
bfd104ac
...
@@ -22,6 +22,14 @@ class Invoice(TimeStampedModel):
...
@@ -22,6 +22,14 @@ class Invoice(TimeStampedModel):
(
PERCENTAGE
,
_
(
'Percentage'
)),
(
PERCENTAGE
,
_
(
'Percentage'
)),
(
FIXED
,
_
(
'Fixed'
))
(
FIXED
,
_
(
'Fixed'
))
)
)
UPDATEABLE_INVOICE_FIELDS
=
[
'invoice_discount_type'
,
'invoice_discount_value'
,
'invoice_number'
,
'invoice_payment_date'
,
'invoice_type'
,
'tax_deducted_source'
,
]
basket
=
models
.
ForeignKey
(
'basket.Basket'
,
null
=
True
,
blank
=
True
)
basket
=
models
.
ForeignKey
(
'basket.Basket'
,
null
=
True
,
blank
=
True
)
order
=
models
.
ForeignKey
(
'order.Order'
,
null
=
True
,
blank
=
False
)
order
=
models
.
ForeignKey
(
'order.Order'
,
null
=
True
,
blank
=
False
)
business_client
=
models
.
ForeignKey
(
'core.BusinessClient'
,
null
=
True
,
blank
=
False
)
business_client
=
models
.
ForeignKey
(
'core.BusinessClient'
,
null
=
True
,
blank
=
False
)
...
...
ecommerce/tests/mixins.py
View file @
bfd104ac
...
@@ -19,7 +19,6 @@ from threadlocals.threadlocals import set_thread_variable
...
@@ -19,7 +19,6 @@ from threadlocals.threadlocals import set_thread_variable
from
ecommerce.core.url_utils
import
get_lms_url
from
ecommerce.core.url_utils
import
get_lms_url
from
ecommerce.courses.utils
import
mode_for_seat
from
ecommerce.courses.utils
import
mode_for_seat
from
ecommerce.extensions.api.constants
import
APIConstants
as
AC
from
ecommerce.extensions.fulfillment.signals
import
SHIPPING_EVENT_NAME
from
ecommerce.extensions.fulfillment.signals
import
SHIPPING_EVENT_NAME
from
ecommerce.tests.factories
import
SiteConfigurationFactory
from
ecommerce.tests.factories
import
SiteConfigurationFactory
...
@@ -121,15 +120,15 @@ class BasketCreationMixin(UserMixin, JwtMixin):
...
@@ -121,15 +120,15 @@ class BasketCreationMixin(UserMixin, JwtMixin):
"""Issue a POST request to the basket creation endpoint."""
"""Issue a POST request to the basket creation endpoint."""
request_data
=
{}
request_data
=
{}
if
skus
:
if
skus
:
request_data
[
AC
.
KEYS
.
PRODUCTS
]
=
[]
request_data
[
'products'
]
=
[]
for
sku
in
skus
:
for
sku
in
skus
:
request_data
[
AC
.
KEYS
.
PRODUCTS
]
.
append
({
AC
.
KEYS
.
SKU
:
sku
})
request_data
[
'products'
]
.
append
({
'sku'
:
sku
})
if
checkout
:
if
checkout
:
request_data
[
AC
.
KEYS
.
CHECKOUT
]
=
checkout
request_data
[
'checkout'
]
=
checkout
if
payment_processor_name
:
if
payment_processor_name
:
request_data
[
AC
.
KEYS
.
PAYMENT_PROCESSOR_NAME
]
=
payment_processor_name
request_data
[
'payment_processor_name'
]
=
payment_processor_name
if
auth
:
if
auth
:
response
=
self
.
client
.
post
(
response
=
self
.
client
.
post
(
...
@@ -173,16 +172,16 @@ class BasketCreationMixin(UserMixin, JwtMixin):
...
@@ -173,16 +172,16 @@ class BasketCreationMixin(UserMixin, JwtMixin):
))
))
if
requires_payment
:
if
requires_payment
:
self
.
assertIsNone
(
response
.
data
[
AC
.
KEYS
.
ORDER
])
self
.
assertIsNone
(
response
.
data
[
'order'
])
self
.
assertIsNotNone
(
response
.
data
[
AC
.
KEYS
.
PAYMENT_DATA
][
AC
.
KEYS
.
PAYMENT_PROCESSOR_NAME
])
self
.
assertIsNotNone
(
response
.
data
[
'payment_data'
][
'payment_processor_name'
])
self
.
assertIsNotNone
(
response
.
data
[
AC
.
KEYS
.
PAYMENT_DATA
][
AC
.
KEYS
.
PAYMENT_FORM_DATA
])
self
.
assertIsNotNone
(
response
.
data
[
'payment_data'
][
'payment_form_data'
])
self
.
assertIsNotNone
(
response
.
data
[
AC
.
KEYS
.
PAYMENT_DATA
][
AC
.
KEYS
.
PAYMENT_PAGE_URL
])
self
.
assertIsNotNone
(
response
.
data
[
'payment_data'
][
'payment_page_url'
])
else
:
else
:
self
.
assertEqual
(
response
.
data
[
AC
.
KEYS
.
ORDER
][
AC
.
KEYS
.
ORDER_NUMBER
],
Order
.
objects
.
get
()
.
number
)
self
.
assertEqual
(
response
.
data
[
'order'
][
'number'
],
Order
.
objects
.
get
()
.
number
)
self
.
assertIsNone
(
response
.
data
[
AC
.
KEYS
.
PAYMENT_DATA
])
self
.
assertIsNone
(
response
.
data
[
'payment_data'
])
else
:
else
:
self
.
assertIsNone
(
response
.
data
[
AC
.
KEYS
.
ORDER
])
self
.
assertIsNone
(
response
.
data
[
'order'
])
self
.
assertIsNone
(
response
.
data
[
AC
.
KEYS
.
PAYMENT_DATA
])
self
.
assertIsNone
(
response
.
data
[
'payment_data'
])
class
BusinessIntelligenceMixin
(
object
):
class
BusinessIntelligenceMixin
(
object
):
...
...
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