Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
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
edx-platform
Commits
b682c43d
Commit
b682c43d
authored
Apr 18, 2017
by
Ivan Ivic
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Update Order History page to reflect bundled purchase
LEARNER-381
parent
d9f17435
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
118 additions
and
82 deletions
+118
-82
common/djangoapps/terrain/stubs/ecommerce.py
+3
-7
common/test/acceptance/pages/lms/account_settings.py
+1
-1
common/test/acceptance/tests/lms/test_account_settings.py
+16
-6
lms/djangoapps/commerce/tests/mocks.py
+16
-0
lms/djangoapps/commerce/utils.py
+3
-4
lms/djangoapps/student_account/test/test_views.py
+22
-23
lms/djangoapps/student_account/views.py
+19
-21
lms/static/js/student_account/views/account_settings_factory.js
+2
-2
lms/static/js/student_account/views/account_settings_fields.js
+2
-2
lms/static/sass/views/_account-settings.scss
+23
-11
lms/templates/fields/field_order_history.underscore
+11
-5
No files found.
common/djangoapps/terrain/stubs/ecommerce.py
View file @
b682c43d
...
...
@@ -38,18 +38,14 @@ class StubEcommerceServiceHandler(StubHttpRequestHandler): # pylint: disable=mi
{
'status'
:
'Complete'
,
'number'
:
'Edx-123'
,
'total_excl_tax'
:
'100.0'
,
'total_excl_tax'
:
'100.0
0
'
,
'date_placed'
:
'2016-04-21T23:14:23Z'
,
'lines'
:
[
{
'title'
:
'Test Course'
,
'line_price_excl_tax'
:
'100.00'
,
'product'
:
{
'attribute_values'
:
[
{
'name'
:
'certificate_type'
,
'value'
:
'verified'
}
]
'product_class'
:
'Seat'
}
}
],
...
...
common/test/acceptance/pages/lms/account_settings.py
View file @
b682c43d
...
...
@@ -72,7 +72,7 @@ class AccountSettingsPage(FieldsMixin, PageObject):
def
get_value_of_order_history_row_item
(
self
,
field_id
,
field_name
):
""" Return the text value of the provided order field name."""
query
=
self
.
q
(
css
=
'.u-field-{} .u-field-order-{}'
.
format
(
field_id
,
field_name
))
return
query
.
text
[
0
]
if
query
.
present
else
None
return
query
.
text
if
query
.
present
else
None
def
order_button_is_visible
(
self
,
field_id
):
""" Check that if hovering over the order history row shows the
...
...
common/test/acceptance/tests/lms/test_account_settings.py
View file @
b682c43d
...
...
@@ -489,15 +489,25 @@ class AccountSettingsPageTest(AccountSettingsTestMixin, AcceptanceTest):
# verify that we are on correct tab
self
.
assertTrue
(
self
.
account_settings_page
.
is_order_history_tab_visible
)
expected_order_data
=
{
'
title'
:
'Test Course
'
,
expected_order_data
_first_row
=
{
'
number'
:
'Order Number:
\n
Edx-123
'
,
'date'
:
'Date Placed:
\n
Apr 21, 2016'
,
'price'
:
'Cost:
\n
$100.0'
,
'number'
:
'Order Number:
\n
Edx-123'
'price'
:
'Cost:
\n
$100.00'
,
}
for
field_name
,
value
in
expected_order_data
.
iteritems
():
expected_order_data_second_row
=
{
'number'
:
'Product Name:
\n
Test Course'
,
'date'
:
'Date Placed:
\n
Apr 21, 2016'
,
'price'
:
'Cost:
\n
$100.00'
,
}
for
field_name
,
value
in
expected_order_data_first_row
.
iteritems
():
self
.
assertEqual
(
self
.
account_settings_page
.
get_value_of_order_history_row_item
(
'order-Edx-123'
,
field_name
)[
0
],
value
)
for
field_name
,
value
in
expected_order_data_second_row
.
iteritems
():
self
.
assertEqual
(
self
.
account_settings_page
.
get_value_of_order_history_row_item
(
'order-Edx-123'
,
field_name
),
value
self
.
account_settings_page
.
get_value_of_order_history_row_item
(
'order-Edx-123'
,
field_name
)
[
1
]
,
value
)
self
.
assertTrue
(
self
.
account_settings_page
.
order_button_is_visible
(
'order-Edx-123'
))
...
...
lms/djangoapps/commerce/tests/mocks.py
View file @
b682c43d
...
...
@@ -164,6 +164,22 @@ class mock_get_orders(mock_ecommerce_api_endpoint):
)])
)
]
),
factories
.
OrderFactory
(
lines
=
[
factories
.
OrderLineFactory
(
product
=
factories
.
ProductFactory
(
attribute_values
=
[
factories
.
ProductAttributeFactory
(
name
=
'certificate_type'
,
value
=
'verified'
)])
),
factories
.
OrderLineFactory
(
product
=
factories
.
ProductFactory
(
attribute_values
=
[
factories
.
ProductAttributeFactory
(
name
=
'certificate_type'
,
value
=
'verified'
)])
),
]
)
]
}
...
...
lms/djangoapps/commerce/utils.py
View file @
b682c43d
...
...
@@ -39,11 +39,10 @@ class EcommerceService(object):
Receipt page for the specified Order.
"""
ecommerce_receipt_page_url
=
configuration_helpers
.
get_value
(
'ECOMMERCE_RECEIPT_PAGE_URL'
)
if
ecommerce_receipt_page_url
:
receipt_page_url
=
self
.
get_absolute_ecommerce_url
(
ecommerce_receipt_page_url
)
else
:
receipt_page_url
=
self
.
config
.
receipt_page
return
receipt_page_url
+
order_number
return
self
.
get_absolute_ecommerce_url
(
ecommerce_receipt_page_url
+
order_number
)
return
self
.
config
.
receipt_page
+
order_number
def
is_enabled
(
self
,
user
):
"""
...
...
lms/djangoapps/student_account/test/test_views.py
View file @
b682c43d
...
...
@@ -634,20 +634,21 @@ class AccountSettingsViewTest(ThirdPartyAuthTestMixin, TestCase, ProgramsApiConf
self
.
assertContains
(
response
,
'<li class="item nav-global-01">'
)
def
test_commerce_order_detail
(
self
):
"""
Verify that get_user_orders returns the correct order data.
"""
with
mock_get_orders
():
order_detail
=
get_user_orders
(
self
.
user
)
user_order
=
mock_get_orders
.
default_response
[
'results'
][
0
]
expected
=
[
{
'number'
:
user_order
[
'number'
],
'price'
:
user_order
[
'total_excl_tax'
],
'title'
:
user_order
[
'lines'
][
0
][
'title'
],
for
i
,
order
in
enumerate
(
mock_get_orders
.
default_response
[
'results'
]):
expected
=
{
'number'
:
order
[
'number'
],
'price'
:
order
[
'total_excl_tax'
],
'order_date'
:
'Jan 01, 2016'
,
'receipt_url'
:
'/commerce/checkout/receipt/?orderNum='
+
user_order
[
'number'
]
'receipt_url'
:
'/commerce/checkout/receipt/?orderNum='
+
order
[
'number'
],
'lines'
:
order
[
'lines'
],
}
]
self
.
assertEqual
(
order_detail
,
expected
)
self
.
assertEqual
(
order_detail
[
i
],
expected
)
def
test_commerce_order_detail_exception
(
self
):
with
mock_get_orders
(
exception
=
exceptions
.
HttpNotFoundError
):
...
...
@@ -673,15 +674,18 @@ class AccountSettingsViewTest(ThirdPartyAuthTestMixin, TestCase, ProgramsApiConf
self
.
assertEqual
(
order_detail
,
[])
def
test_
honor_course_order_detail
(
self
):
def
test_
order_history_with_no_product
(
self
):
response
=
{
'results'
:
[
factories
.
OrderFactory
(
lines
=
[
factories
.
OrderLineFactory
(
product
=
None
),
factories
.
OrderLineFactory
(
product
=
factories
.
ProductFactory
(
attribute_values
=
[
factories
.
ProductAttributeFactory
(
name
=
'certificate_type'
,
value
=
'
honor
'
value
=
'
verified
'
)])
)
]
...
...
@@ -691,22 +695,17 @@ class AccountSettingsViewTest(ThirdPartyAuthTestMixin, TestCase, ProgramsApiConf
with
mock_get_orders
(
response
=
response
):
order_detail
=
get_user_orders
(
self
.
user
)
self
.
assertEqual
(
order_detail
,
[]
)
self
.
assertEqual
(
len
(
order_detail
),
1
)
def
test_order_history_with_no_product
(
self
):
def
test_order_history_with_coupon
(
self
):
"""
Verify that get_order_details returns empty receipt_url for coupon product.
"""
response
=
{
'results'
:
[
factories
.
OrderFactory
(
lines
=
[
factories
.
OrderLineFactory
(
product
=
None
),
factories
.
OrderLineFactory
(
product
=
factories
.
ProductFactory
(
attribute_values
=
[
factories
.
ProductAttributeFactory
(
name
=
'certificate_type'
,
value
=
'verified'
)])
)
factories
.
OrderLineFactory
(
product
=
factories
.
ProductFactory
(
product_class
=
'Coupon'
))
]
)
]
...
...
@@ -714,7 +713,7 @@ class AccountSettingsViewTest(ThirdPartyAuthTestMixin, TestCase, ProgramsApiConf
with
mock_get_orders
(
response
=
response
):
order_detail
=
get_user_orders
(
self
.
user
)
self
.
assertEqual
(
len
(
order_detail
),
1
)
self
.
assertEqual
(
order_detail
[
0
][
'receipt_url'
],
''
)
@override_settings
(
SITE_NAME
=
settings
.
MICROSITE_LOGISTRATION_HOSTNAME
)
...
...
lms/djangoapps/student_account/views.py
View file @
b682c43d
...
...
@@ -331,7 +331,6 @@ def get_user_orders(user):
"""
no_data
=
[]
user_orders
=
[]
allowed_course_modes
=
[
'professional'
,
'verified'
,
'credit'
]
commerce_configuration
=
CommerceConfiguration
.
current
()
user_query
=
{
'username'
:
user
.
username
}
...
...
@@ -344,26 +343,25 @@ def get_user_orders(user):
for
order
in
commerce_user_orders
:
if
order
[
'status'
]
.
lower
()
==
'complete'
:
for
line
in
order
[
'lines'
]:
product
=
line
.
get
(
'product'
)
if
product
:
for
attribute
in
product
[
'attribute_values'
]:
if
attribute
[
'name'
]
==
'certificate_type'
and
attribute
[
'value'
]
in
allowed_course_modes
:
try
:
date_placed
=
datetime
.
strptime
(
order
[
'date_placed'
],
"
%
Y-
%
m-
%
dT
%
H:
%
M:
%
SZ"
)
order_data
=
{
'number'
:
order
[
'number'
],
'price'
:
order
[
'total_excl_tax'
],
'title'
:
order
[
'lines'
][
0
][
'title'
],
'order_date'
:
strftime_localized
(
date_placed
.
replace
(
tzinfo
=
pytz
.
UTC
),
'SHORT_DATE'
),
'receipt_url'
:
EcommerceService
()
.
get_receipt_page_url
(
order
[
'number'
])
}
user_orders
.
append
(
order_data
)
except
KeyError
:
log
.
exception
(
'Invalid order structure:
%
r'
,
order
)
return
no_data
date_placed
=
datetime
.
strptime
(
order
[
'date_placed'
],
"
%
Y-
%
m-
%
dT
%
H:
%
M:
%
SZ"
)
order_data
=
{
'number'
:
order
[
'number'
],
'price'
:
order
[
'total_excl_tax'
],
'order_date'
:
strftime_localized
(
date_placed
,
'SHORT_DATE'
),
'receipt_url'
:
EcommerceService
()
.
get_receipt_page_url
(
order
[
'number'
]),
'lines'
:
order
[
'lines'
],
}
# If the order lines contain a product that is not a Seat
# we do not want to display the Order Details button. It
# will break the receipt page if used.
for
order_line
in
order
[
'lines'
]:
product
=
order_line
.
get
(
'product'
)
if
product
and
product
.
get
(
'product_class'
)
!=
'Seat'
:
order_data
[
'receipt_url'
]
=
''
break
user_orders
.
append
(
order_data
)
return
user_orders
...
...
lms/static/js/student_account/views/account_settings_factory.js
View file @
b682c43d
...
...
@@ -229,12 +229,12 @@
}
return
{
'view'
:
new
AccountSettingsFieldViews
.
OrderHistoryFieldView
({
title
:
order
.
title
,
totalPrice
:
order
.
price
,
orderId
:
order
.
number
,
orderDate
:
order
.
order_date
,
receiptUrl
:
order
.
receipt_url
,
valueAttribute
:
'order-'
+
orderNumber
valueAttribute
:
'order-'
+
orderNumber
,
lines
:
order
.
lines
})
};
})
...
...
lms/static/js/student_account/views/account_settings_fields.js
View file @
b682c43d
...
...
@@ -325,12 +325,12 @@
render
:
function
()
{
HtmlUtils
.
setHtml
(
this
.
$el
,
this
.
template
({
title
:
this
.
options
.
title
,
totalPrice
:
this
.
options
.
totalPrice
,
orderId
:
this
.
options
.
orderId
,
orderDate
:
this
.
options
.
orderDate
,
receiptUrl
:
this
.
options
.
receiptUrl
,
valueAttribute
:
this
.
options
.
valueAttribute
valueAttribute
:
this
.
options
.
valueAttribute
,
lines
:
this
.
options
.
lines
}));
this
.
delegateEvents
();
return
this
;
...
...
lms/static/sass/views/_account-settings.scss
View file @
b682c43d
...
...
@@ -193,35 +193,37 @@
display
:
flex
;
align-items
:
center
;
font-size
:
em
(
16
);
color
:
$gray
;
font-weight
:
600
;
color
:
$dark-gray
;
width
:
100%
;
padding-top
:
$baseline
;
padding-bottom
:
$baseline
;
line-height
:
normal
;
flex-direction
:
row
;
flex-wrap
:
wrap
;
span
{
padding
:
$baseline
;
}
.u-field-order-
title
{
.u-field-order-
number
{
@include
float
(
left
);
width
:
26%
;
font-size
:
em
(
20
);
padding-left
:
(
$baseline
*
2
);
width
:
30%
;
}
.u-field-order-
valu
e
{
.u-field-order-
dat
e
{
@include
float
(
left
);
width
:
12%
;
padding-left
:
30px
;
width
:
20%
;
}
.u-field-order-
dat
e
{
.u-field-order-
pric
e
{
@include
float
(
left
);
width
:
1
6
%
;
width
:
1
5
%
;
}
.u-field-order-link
{
width
:
1
5
%
;
width
:
1
0
%
;
padding
:
0
;
.u-field-link
{
...
...
@@ -237,6 +239,16 @@
}
}
.u-field-order-lines
{
@extend
.u-field-order
;
padding
:
5px
0
0
;
font-weight
:
100
;
.u-field-order-number
{
padding
:
20px
10px
20px
30px
;
}
}
.social-field-linked
{
background
:
$m-gray-l4
;
box-shadow
:
0
1px
2px
1px
$shadow-l2
;
...
...
@@ -290,7 +302,7 @@
font-weight
:
$font-semibold
;
}
}
.u-field-message
{
position
:
relative
;
padding
:
24px
0
0
(
$baseline
*
5
);
...
...
lms/templates/fields/field_order_history.underscore
View file @
b682c43d
<div class="field u-field-order" <% if (receiptUrl) { %> role="group" aria-labelledby="order-title-<%- orderId %>" <% } else { %> aria-hidden="true" <% } %>>
<span class="u-field-order-title" <% if (receiptUrl) { %> id="order-title-<%- orderId %>" <% } %>><%- title %></span>
<span class="u-field-order-date"><span class="sr">Date Placed: </span><%- orderDate %></span>
<span class="u-field-order-value u-field-order-price"><span class="sr">Cost: </span><% if (!isNaN(parseFloat(totalPrice))) { %>$<% } %><%- totalPrice %></span>
<span class="u-field-order-value u-field-order-number"><span class="sr">Order Number: </span><%- orderId %></span>
<span class="u-field-order-number"><span class="sr"><%- gettext('Order Number') %>: </span><%- orderId %></span>
<span class="u-field-order-date"><span class="sr"><%- gettext('Date Placed') %>: </span><%- orderDate %></span>
<span class="u-field-order-price"><span class="sr"><%- gettext('Cost') %>: </span><% if (!isNaN(parseFloat(totalPrice))) { %>$<% } %><%- totalPrice %></span>
<span class="u-field-order-link">
<% if (receiptUrl) { %>
<a class="u-field-link" target="_blank" href="<%- receiptUrl %>"><%- gettext('Order Details') %><span class="sr">
for
<%- orderId %></span></a>
<a class="u-field-link" target="_blank" href="<%- receiptUrl %>"><%- gettext('Order Details') %><span class="sr">
<%- gettext('for') %>
<%- orderId %></span></a>
<% } %>
</span>
<% _.each(lines, function(item){ %>
<div class="field u-field-order-lines">
<span class="u-field-order-number"><span class="sr"><%- gettext('Product Name') %>: </span><%- item.title %></span>
<span class="u-field-order-date"><span class="sr"><%- gettext('Date Placed') %>: </span><%- orderDate %></span>
<span class="u-field-order-price"><span class="sr"><%- gettext('Cost') %>: </span><% if (!isNaN(parseFloat(item.line_price_excl_tax))) { %>$<% } %><%- item.line_price_excl_tax %></span>
</div>
<% }); %>
</div>
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