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
a9c73d24
Commit
a9c73d24
authored
Sep 05, 2014
by
Will Daly
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Set order status to "paying" before redirecting to the external payment processor.
parent
9c942d7e
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
87 additions
and
4 deletions
+87
-4
lms/djangoapps/shoppingcart/models.py
+34
-0
lms/djangoapps/shoppingcart/tests/test_models.py
+32
-0
lms/djangoapps/verify_student/tests/test_views.py
+12
-4
lms/djangoapps/verify_student/views.py
+9
-0
No files found.
lms/djangoapps/shoppingcart/models.py
View file @
a9c73d24
...
@@ -40,8 +40,18 @@ from microsite_configuration import microsite
...
@@ -40,8 +40,18 @@ from microsite_configuration import microsite
log
=
logging
.
getLogger
(
"shoppingcart"
)
log
=
logging
.
getLogger
(
"shoppingcart"
)
ORDER_STATUSES
=
(
ORDER_STATUSES
=
(
# The user is selecting what he/she wants to purchase.
(
'cart'
,
'cart'
),
(
'cart'
,
'cart'
),
# The user has been sent to the external payment processor.
# At this point, the order should NOT be modified.
# If the user returns to the payment flow, he/she will start a new order.
(
'paying'
,
'paying'
),
# The user has successfully purchased the items in the order.
(
'purchased'
,
'purchased'
),
(
'purchased'
,
'purchased'
),
# The user's order has been refunded.
(
'refunded'
,
'refunded'
),
(
'refunded'
,
'refunded'
),
)
)
...
@@ -129,6 +139,22 @@ class Order(models.Model):
...
@@ -129,6 +139,22 @@ class Order(models.Model):
"""
"""
self
.
orderitem_set
.
all
()
.
delete
()
self
.
orderitem_set
.
all
()
.
delete
()
@transaction.commit_on_success
def
start_purchase
(
self
):
"""
Start the purchase process. This will set the order status to "paying",
at which point it should no longer be modified.
Future calls to `Order.get_cart_for_user()` will filter out orders with
status "paying", effectively creating a new (empty) cart.
"""
if
self
.
status
==
'cart'
:
self
.
status
=
'paying'
self
.
save
()
for
item
in
OrderItem
.
objects
.
filter
(
order
=
self
)
.
select_subclasses
():
item
.
start_purchase
()
def
purchase
(
self
,
first
=
''
,
last
=
''
,
street1
=
''
,
street2
=
''
,
city
=
''
,
state
=
''
,
postalcode
=
''
,
def
purchase
(
self
,
first
=
''
,
last
=
''
,
street1
=
''
,
street2
=
''
,
city
=
''
,
state
=
''
,
postalcode
=
''
,
country
=
''
,
ccnum
=
''
,
cardtype
=
''
,
processor_reply_dump
=
''
):
country
=
''
,
ccnum
=
''
,
cardtype
=
''
,
processor_reply_dump
=
''
):
"""
"""
...
@@ -269,6 +295,14 @@ class OrderItem(models.Model):
...
@@ -269,6 +295,14 @@ class OrderItem(models.Model):
self
.
fulfilled_time
=
datetime
.
now
(
pytz
.
utc
)
self
.
fulfilled_time
=
datetime
.
now
(
pytz
.
utc
)
self
.
save
()
self
.
save
()
def
start_purchase
(
self
):
"""
Start the purchase process. This will set the order item status to "paying",
at which point it should no longer be modified.
"""
self
.
status
=
'paying'
self
.
save
()
def
purchased_callback
(
self
):
def
purchased_callback
(
self
):
"""
"""
This is called on each inventory item in the shopping cart when the
This is called on each inventory item in the shopping cart when the
...
...
lms/djangoapps/shoppingcart/tests/test_models.py
View file @
a9c73d24
...
@@ -102,6 +102,38 @@ class OrderTest(ModuleStoreTestCase):
...
@@ -102,6 +102,38 @@ class OrderTest(ModuleStoreTestCase):
self
.
assertEquals
(
cart
.
orderitem_set
.
count
(),
len
(
course_costs
))
self
.
assertEquals
(
cart
.
orderitem_set
.
count
(),
len
(
course_costs
))
self
.
assertEquals
(
cart
.
total_cost
,
sum
(
cost
for
_course
,
cost
in
course_costs
))
self
.
assertEquals
(
cart
.
total_cost
,
sum
(
cost
for
_course
,
cost
in
course_costs
))
def
test_start_purchase
(
self
):
# Start the purchase, which will mark the cart as "paying"
cart
=
Order
.
get_cart_for_user
(
user
=
self
.
user
)
CertificateItem
.
add_to_order
(
cart
,
self
.
course_key
,
self
.
cost
,
'honor'
,
currency
=
'usd'
)
cart
.
start_purchase
()
self
.
assertEqual
(
cart
.
status
,
'paying'
)
for
item
in
cart
.
orderitem_set
.
all
():
self
.
assertEqual
(
item
.
status
,
'paying'
)
# Starting the purchase should be idempotent
cart
.
start_purchase
()
self
.
assertEqual
(
cart
.
status
,
'paying'
)
for
item
in
cart
.
orderitem_set
.
all
():
self
.
assertEqual
(
item
.
status
,
'paying'
)
# If we retrieve the cart for the user, we should get a different order
next_cart
=
Order
.
get_cart_for_user
(
user
=
self
.
user
)
self
.
assertNotEqual
(
cart
,
next_cart
)
self
.
assertEqual
(
next_cart
.
status
,
'cart'
)
# Complete the first purchase
cart
.
purchase
()
self
.
assertEqual
(
cart
.
status
,
'purchased'
)
for
item
in
cart
.
orderitem_set
.
all
():
self
.
assertEqual
(
item
.
status
,
'purchased'
)
# Starting the purchase again should be a no-op
cart
.
start_purchase
()
self
.
assertEqual
(
cart
.
status
,
'purchased'
)
for
item
in
cart
.
orderitem_set
.
all
():
self
.
assertEqual
(
item
.
status
,
'purchased'
)
def
test_purchase
(
self
):
def
test_purchase
(
self
):
# This test is for testing the subclassing functionality of OrderItem, but in
# This test is for testing the subclassing functionality of OrderItem, but in
# order to do this, we end up testing the specific functionality of
# order to do this, we end up testing the specific functionality of
...
...
lms/djangoapps/verify_student/tests/test_views.py
View file @
a9c73d24
...
@@ -31,8 +31,8 @@ from opaque_keys.edx.locations import SlashSeparatedCourseKey
...
@@ -31,8 +31,8 @@ from opaque_keys.edx.locations import SlashSeparatedCourseKey
from
student.tests.factories
import
UserFactory
from
student.tests.factories
import
UserFactory
from
student.models
import
CourseEnrollment
from
student.models
import
CourseEnrollment
from
course_modes.tests.factories
import
CourseModeFactory
from
course_modes.tests.factories
import
CourseModeFactory
from
courseware.tests.tests
import
TEST_DATA_MONGO_MODULESTORE
from
course_modes.models
import
CourseMode
from
course_modes.models
import
CourseMode
from
shoppingcart.models
import
Order
,
CertificateItem
from
verify_student.views
import
render_to_response
from
verify_student.views
import
render_to_response
from
verify_student.models
import
SoftwareSecurePhotoVerification
from
verify_student.models
import
SoftwareSecurePhotoVerification
from
reverification.tests.factories
import
MidcourseReverificationWindowFactory
from
reverification.tests.factories
import
MidcourseReverificationWindowFactory
...
@@ -66,8 +66,8 @@ class StartView(TestCase):
...
@@ -66,8 +66,8 @@ class StartView(TestCase):
self
.
assertHttpForbidden
(
self
.
client
.
get
(
self
.
start_url
()))
self
.
assertHttpForbidden
(
self
.
client
.
get
(
self
.
start_url
()))
@override_settings
(
MODULESTORE
=
TEST_DATA_MONGO_MODULESTORE
)
@override_settings
(
MODULESTORE
=
MODULESTORE_CONFIG
)
class
TestCreateOrderView
(
TestCase
):
class
TestCreateOrderView
(
ModuleStore
TestCase
):
"""
"""
Tests for the create_order view of verified course registration process
Tests for the create_order view of verified course registration process
"""
"""
...
@@ -75,7 +75,7 @@ class TestCreateOrderView(TestCase):
...
@@ -75,7 +75,7 @@ class TestCreateOrderView(TestCase):
self
.
user
=
UserFactory
.
create
(
username
=
"rusty"
,
password
=
"test"
)
self
.
user
=
UserFactory
.
create
(
username
=
"rusty"
,
password
=
"test"
)
self
.
client
.
login
(
username
=
"rusty"
,
password
=
"test"
)
self
.
client
.
login
(
username
=
"rusty"
,
password
=
"test"
)
self
.
course_id
=
'Robot/999/Test_Course'
self
.
course_id
=
'Robot/999/Test_Course'
CourseFactory
.
create
(
org
=
'Robot'
,
number
=
'999'
,
display_name
=
'Test Course'
)
self
.
course
=
CourseFactory
.
create
(
org
=
'Robot'
,
number
=
'999'
,
display_name
=
'Test Course'
)
verified_mode
=
CourseMode
(
verified_mode
=
CourseMode
(
course_id
=
SlashSeparatedCourseKey
(
"Robot"
,
"999"
,
'Test_Course'
),
course_id
=
SlashSeparatedCourseKey
(
"Robot"
,
"999"
,
'Test_Course'
),
mode_slug
=
"verified"
,
mode_slug
=
"verified"
,
...
@@ -156,6 +156,14 @@ class TestCreateOrderView(TestCase):
...
@@ -156,6 +156,14 @@ class TestCreateOrderView(TestCase):
self
.
assertTrue
(
json_response
.
get
(
'success'
))
self
.
assertTrue
(
json_response
.
get
(
'success'
))
self
.
assertIsNotNone
(
json_response
.
get
(
'orderNumber'
))
self
.
assertIsNotNone
(
json_response
.
get
(
'orderNumber'
))
# Verify that the order exists and is configured correctly
order
=
Order
.
objects
.
get
(
user
=
self
.
user
)
self
.
assertEqual
(
order
.
status
,
'paying'
)
item
=
CertificateItem
.
objects
.
get
(
order
=
order
)
self
.
assertEqual
(
item
.
status
,
'paying'
)
self
.
assertEqual
(
item
.
course_id
,
self
.
course
.
id
)
self
.
assertEqual
(
item
.
mode
,
'verified'
)
@override_settings
(
MODULESTORE
=
MODULESTORE_CONFIG
)
@override_settings
(
MODULESTORE
=
MODULESTORE_CONFIG
)
class
TestVerifyView
(
ModuleStoreTestCase
):
class
TestVerifyView
(
ModuleStoreTestCase
):
...
...
lms/djangoapps/verify_student/views.py
View file @
a9c73d24
...
@@ -227,6 +227,15 @@ def create_order(request):
...
@@ -227,6 +227,15 @@ def create_order(request):
enrollment_mode
=
current_mode
.
slug
enrollment_mode
=
current_mode
.
slug
CertificateItem
.
add_to_order
(
cart
,
course_id
,
amount
,
enrollment_mode
)
CertificateItem
.
add_to_order
(
cart
,
course_id
,
amount
,
enrollment_mode
)
# Change the order's status so that we don't accidentally modify it later.
# We need to do this to ensure that the parameters we send to the payment system
# match what we store in the database.
# (Ordinarily we would do this client-side when the user submits the form, but since
# the JavaScript on this page does that immediately, we make the change here instead.
# This avoids a second AJAX call and some additional complication of the JavaScript.)
# If a user later re-enters the verification / payment flow, she will create a new order.
cart
.
start_purchase
()
callback_url
=
request
.
build_absolute_uri
(
callback_url
=
request
.
build_absolute_uri
(
reverse
(
"shoppingcart.views.postpay_callback"
)
reverse
(
"shoppingcart.views.postpay_callback"
)
)
)
...
...
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