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
9ef91591
Commit
9ef91591
authored
Apr 20, 2017
by
Ivan Ivic
Committed by
GitHub
Apr 20, 2017
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #14906 from edx/iivic/LEARNER-381
Update Order History page to reflect bundled purchase
parents
205f0723
b682c43d
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 @
9ef91591
...
...
@@ -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 @
9ef91591
...
...
@@ -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 @
9ef91591
...
...
@@ -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 @
9ef91591
...
...
@@ -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 @
9ef91591
...
...
@@ -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 @
9ef91591
...
...
@@ -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 @
9ef91591
...
...
@@ -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 @
9ef91591
...
...
@@ -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 @
9ef91591
...
...
@@ -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 @
9ef91591
...
...
@@ -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 @
9ef91591
<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