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
fa87793e
Commit
fa87793e
authored
Dec 09, 2013
by
Julia Hansbrough
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fixed UniversityRevenueShare model
parent
1981ee50
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
137 additions
and
66 deletions
+137
-66
lms/djangoapps/shoppingcart/exceptions.py
+8
-0
lms/djangoapps/shoppingcart/models.py
+79
-32
lms/djangoapps/shoppingcart/tests/test_models.py
+49
-32
lms/djangoapps/shoppingcart/tests/test_views.py
+1
-1
lms/djangoapps/verify_student/views.py
+0
-1
No files found.
lms/djangoapps/shoppingcart/exceptions.py
View file @
fa87793e
...
@@ -26,3 +26,11 @@ class AlreadyEnrolledInCourseException(InvalidCartItem):
...
@@ -26,3 +26,11 @@ class AlreadyEnrolledInCourseException(InvalidCartItem):
class
CourseDoesNotExistException
(
InvalidCartItem
):
class
CourseDoesNotExistException
(
InvalidCartItem
):
pass
pass
class
ReportException
(
Exception
):
pass
class
ReportTypeDoesNotExistException
(
ReportException
):
pass
lms/djangoapps/shoppingcart/models.py
View file @
fa87793e
...
@@ -34,7 +34,8 @@ from student.models import CourseEnrollment, unenroll_done
...
@@ -34,7 +34,8 @@ from student.models import CourseEnrollment, unenroll_done
from
verify_student.models
import
SoftwareSecurePhotoVerification
from
verify_student.models
import
SoftwareSecurePhotoVerification
from
.exceptions
import
(
InvalidCartItem
,
PurchasedCallbackException
,
ItemAlreadyInCartException
,
from
.exceptions
import
(
InvalidCartItem
,
PurchasedCallbackException
,
ItemAlreadyInCartException
,
AlreadyEnrolledInCourseException
,
CourseDoesNotExistException
)
AlreadyEnrolledInCourseException
,
CourseDoesNotExistException
,
ReportException
,
ReportTypeDoesNotExistException
)
log
=
logging
.
getLogger
(
"shoppingcart"
)
log
=
logging
.
getLogger
(
"shoppingcart"
)
...
@@ -214,6 +215,7 @@ class OrderItem(models.Model):
...
@@ -214,6 +215,7 @@ class OrderItem(models.Model):
currency
=
models
.
CharField
(
default
=
"usd"
,
max_length
=
8
)
# lower case ISO currency codes
currency
=
models
.
CharField
(
default
=
"usd"
,
max_length
=
8
)
# lower case ISO currency codes
fulfilled_time
=
models
.
DateTimeField
(
null
=
True
)
fulfilled_time
=
models
.
DateTimeField
(
null
=
True
)
refund_requested_time
=
models
.
DateTimeField
(
null
=
True
)
refund_requested_time
=
models
.
DateTimeField
(
null
=
True
)
service_fee
=
models
.
DecimalField
(
default
=
0.0
,
decimal_places
=
2
,
max_digits
=
30
)
# general purpose field, not user-visible. Used for reporting
# general purpose field, not user-visible. Used for reporting
report_comments
=
models
.
TextField
(
default
=
""
)
report_comments
=
models
.
TextField
(
default
=
""
)
...
@@ -570,6 +572,7 @@ class CertificateItem(OrderItem):
...
@@ -570,6 +572,7 @@ class CertificateItem(OrderItem):
"Please do NOT include your credit card information."
)
.
format
(
"Please do NOT include your credit card information."
)
.
format
(
billing_email
=
settings
.
PAYMENT_SUPPORT_EMAIL
)
billing_email
=
settings
.
PAYMENT_SUPPORT_EMAIL
)
class
Report
(
models
.
Model
):
class
Report
(
models
.
Model
):
"""
"""
Base class for making CSV reports related to revenue, enrollments, etc
Base class for making CSV reports related to revenue, enrollments, etc
...
@@ -580,6 +583,9 @@ class Report(models.Model):
...
@@ -580,6 +583,9 @@ class Report(models.Model):
@classmethod
@classmethod
def
initialize_report
(
cls
,
report_type
):
def
initialize_report
(
cls
,
report_type
):
"""
Creates the appropriate type of Report object based on the string report_type.
"""
if
report_type
==
"refund_report"
:
if
report_type
==
"refund_report"
:
return
RefundReport
()
return
RefundReport
()
elif
report_type
==
"itemized_purchase_report"
:
elif
report_type
==
"itemized_purchase_report"
:
...
@@ -589,19 +595,32 @@ class Report(models.Model):
...
@@ -589,19 +595,32 @@ class Report(models.Model):
elif
report_type
==
"certificate_status"
:
elif
report_type
==
"certificate_status"
:
return
CertificateStatusReport
()
return
CertificateStatusReport
()
else
:
else
:
r
eturn
# TODO return an error
r
aise
ReportTypeDoesNotExistException
def
get_query
(
self
,
start_date
,
end_date
):
def
get_query
(
self
,
start_date
,
end_date
):
"""
Performs any database queries necessary to obtain the data for the report.
"""
raise
NotImplementedError
raise
NotImplementedError
def
csv_report_header_row
(
self
,
start_date
,
end_date
):
def
csv_report_header_row
(
self
):
"""
Returns the appropriate header based on the report type.
"""
raise
NotImplementedError
raise
NotImplementedError
def
csv_report_row
(
self
):
def
csv_report_row
(
self
,
item
):
"""
Given the results of the query from get_query, this function generates a single row of a csv.
"""
raise
NotImplementedError
raise
NotImplementedError
@classmethod
@classmethod
def
make_report
(
cls
,
report_type
,
filelike
,
start_date
,
end_date
):
def
make_report
(
cls
,
report_type
,
filelike
,
start_date
,
end_date
):
"""
Given the string report_type, a file object to write to, and start/end date bounds,
generates a CSV report of the appropriate type.
"""
report
=
cls
.
initialize_report
(
report_type
)
report
=
cls
.
initialize_report
(
report_type
)
items
=
report
.
get_query
(
start_date
,
end_date
)
items
=
report
.
get_query
(
start_date
,
end_date
)
writer
=
unicodecsv
.
writer
(
filelike
,
encoding
=
"utf-8"
)
writer
=
unicodecsv
.
writer
(
filelike
,
encoding
=
"utf-8"
)
...
@@ -611,10 +630,13 @@ class Report(models.Model):
...
@@ -611,10 +630,13 @@ class Report(models.Model):
class
RefundReport
(
Report
):
class
RefundReport
(
Report
):
"""
Subclass of Report, used to generate Refund Reports for finance purposes.
"""
def
get_query
(
self
,
start_date
,
end_date
):
def
get_query
(
self
,
start_date
,
end_date
):
return
CertificateItem
.
objects
.
filter
(
return
CertificateItem
.
objects
.
filter
(
status
=
"refunded"
,
status
=
"refunded"
,
)
)
def
csv_report_header_row
(
self
):
def
csv_report_header_row
(
self
):
return
[
return
[
...
@@ -631,18 +653,22 @@ class RefundReport(Report):
...
@@ -631,18 +653,22 @@ class RefundReport(Report):
item
.
order_id
,
item
.
order_id
,
item
.
user
.
get_full_name
(),
item
.
user
.
get_full_name
(),
item
.
fulfilled_time
,
item
.
fulfilled_time
,
item
.
refund_requested_time
,
#
actually may need to use refund_fulfilled here
item
.
refund_requested_time
,
# TODO
actually may need to use refund_fulfilled here
item
.
line_cost
,
item
.
line_cost
,
0
,
# TODO: determine if service_fees field is necessary; if so, add
item
.
service_fee
,
]
]
class
ItemizedPurchaseReport
(
Report
):
class
ItemizedPurchaseReport
(
Report
):
"""
Subclass of Report, used to generate itemized purchase reports.
"""
def
get_query
(
self
,
start_date
,
end_date
):
def
get_query
(
self
,
start_date
,
end_date
):
return
OrderItem
.
objects
.
filter
(
return
OrderItem
.
objects
.
filter
(
status
=
"purchased"
,
status
=
"purchased"
,
fulfilled_time__gte
=
start_date
,
fulfilled_time__gte
=
start_date
,
fulfilled_time__lt
=
end_date
,
fulfilled_time__lt
=
end_date
,
)
.
order_by
(
"fulfilled_time"
)
)
.
order_by
(
"fulfilled_time"
)
def
csv_report_header_row
(
self
):
def
csv_report_header_row
(
self
):
return
[
return
[
...
@@ -672,13 +698,16 @@ class ItemizedPurchaseReport(Report):
...
@@ -672,13 +698,16 @@ class ItemizedPurchaseReport(Report):
class
CertificateStatusReport
(
Report
):
class
CertificateStatusReport
(
Report
):
def
get_query
(
self
,
start_date
,
send_date
):
"""
Subclass of Report, used to generate Certificate Status Reports for ed services.
"""
def
get_query
(
self
,
start_date
,
end_date
):
results
=
[]
results
=
[]
for
course_id
in
settings
.
COURSE_LISTINGS
[
'default'
]:
for
course_id
in
settings
.
COURSE_LISTINGS
[
'default'
]:
cur_course
=
get_course_by_id
(
course_id
)
cur_course
=
get_course_by_id
(
course_id
)
university
=
cur_course
.
org
university
=
cur_course
.
org
course
=
cur_course
.
number
+
" "
+
cur_course
.
display_name
#
TODO add term (i.e. Fall 2013)?
course
=
cur_course
.
number
+
" "
+
cur_course
.
display_name
#
TODO add term (i.e. Fall 2013)?
enrollments
=
CourseEnrollment
.
objects
.
filter
(
course_id
=
course_id
)
enrollments
=
CourseEnrollment
.
objects
.
filter
(
course_id
=
course_id
)
total_enrolled
=
enrollments
.
count
()
total_enrolled
=
enrollments
.
count
()
audit_enrolled
=
enrollments
.
filter
(
mode
=
"audit"
)
.
count
()
audit_enrolled
=
enrollments
.
filter
(
mode
=
"audit"
)
.
count
()
honor_enrolled
=
enrollments
.
filter
(
mode
=
"honor"
)
.
count
()
honor_enrolled
=
enrollments
.
filter
(
mode
=
"honor"
)
.
count
()
...
@@ -686,8 +715,8 @@ class CertificateStatusReport(Report):
...
@@ -686,8 +715,8 @@ class CertificateStatusReport(Report):
verified_enrolled
=
verified_enrollments
.
count
()
verified_enrolled
=
verified_enrollments
.
count
()
gross_rev_temp
=
CertificateItem
.
objects
.
filter
(
course_id
=
course_id
,
mode
=
"verified"
)
.
aggregate
(
Sum
(
'unit_cost'
))
gross_rev_temp
=
CertificateItem
.
objects
.
filter
(
course_id
=
course_id
,
mode
=
"verified"
)
.
aggregate
(
Sum
(
'unit_cost'
))
gross_rev
=
gross_rev_temp
[
'unit_cost__sum'
]
gross_rev
=
gross_rev_temp
[
'unit_cost__sum'
]
gross_rev_over_min
=
gross_rev
-
(
CourseMode
.
objects
.
get
(
course_id
=
course_id
,
mode_slug
=
"verified"
)
.
min_price
*
verified_enrolled
)
gross_rev_over_min
=
gross_rev
-
(
CourseMode
.
objects
.
get
(
course_id
=
course_id
,
mode_slug
=
"verified"
)
.
min_price
*
verified_enrolled
)
num_verified_over_min
=
0
# TODO clarify with billing what exactly this means
num_verified_over_min
=
0
# TODO clarify with billing what exactly this means
refunded_enrollments
=
CertificateItem
.
objects
.
filter
(
course_id
=
'course_id'
,
mode
=
"refunded"
)
refunded_enrollments
=
CertificateItem
.
objects
.
filter
(
course_id
=
'course_id'
,
mode
=
"refunded"
)
number_of_refunds
=
refunded_enrollments
.
count
()
number_of_refunds
=
refunded_enrollments
.
count
()
dollars_refunded_temp
=
refunded_enrollments
.
aggregate
(
Sum
(
'unit_cost'
))
dollars_refunded_temp
=
refunded_enrollments
.
aggregate
(
Sum
(
'unit_cost'
))
...
@@ -697,10 +726,10 @@ class CertificateStatusReport(Report):
...
@@ -697,10 +726,10 @@ class CertificateStatusReport(Report):
dollars_refunded
=
dollars_refunded_temp
[
'unit_cost__sum'
]
dollars_refunded
=
dollars_refunded_temp
[
'unit_cost__sum'
]
result
=
[
result
=
[
university
,
university
,
course
,
course
,
total_enrolled
,
total_enrolled
,
audit_enrolled
,
audit_enrolled
,
honor_enrolled
,
honor_enrolled
,
verified_enrolled
,
verified_enrolled
,
gross_rev
,
gross_rev
,
...
@@ -733,19 +762,39 @@ class CertificateStatusReport(Report):
...
@@ -733,19 +762,39 @@ class CertificateStatusReport(Report):
class
UniversityRevenueShareReport
(
Report
):
class
UniversityRevenueShareReport
(
Report
):
"""
Subclass of Report, used to generate University Revenue Share Reports for finance purposes.
"""
def
get_query
(
self
,
start_date
,
end_date
):
def
get_query
(
self
,
start_date
,
end_date
):
results
=
[]
results
=
[]
for
course_id
in
settings
.
COURSE_LISTINGS
[
'default'
]:
for
course_id
in
settings
.
COURSE_LISTINGS
[
'default'
]:
cur_course
=
get_course_by_id
(
course_id
)
cur_course
=
get_course_by_id
(
course_id
)
university
=
cur_course
.
org
university
=
cur_course
.
org
course
=
cur_course
.
number
+
" "
+
course
.
display_name
course
=
cur_course
.
number
+
" "
+
cur_course
.
display_name
num_transactions
=
0
# TODO clarify with building what transactions are included in this (purchases? refunds? etc)
num_transactions
=
0
# TODO clarify with building what transactions are included in this (purchases? refunds? etc)
total_payments_collected
=
CertificateItem
.
objects
.
filter
(
course_id
=
course_id
,
mode
=
"verified"
)
.
aggregate
(
Sum
(
'unit_cost'
))
#note: we're assuming certitems are the only way to make money right now
all_paid_certs
=
CertificateItem
.
objects
.
filter
(
course_id
=
course_id
,
status
=
"purchased"
)
service_fees
=
0
# TODO add an actual service fees field, in case needed in future
refunded_enrollments
=
CertificateItem
.
objects
.
filter
(
course_id
=
'course_id'
,
mode
=
"refunded"
)
total_payments_collected_temp
=
all_paid_certs
.
aggregate
(
Sum
(
'unit_cost'
))
num_refunds
=
refunded_enrollments
.
objects
.
count
()
if
total_payments_collected_temp
[
'unit_cost__sum'
]
is
None
:
amount_refunds
=
refunded_enrollments
.
objects
.
aggregate
(
Sum
(
'unit_cost'
))
total_payments_collected
=
Decimal
(
0.00
)
else
:
total_payments_collected
=
total_payments_collected_temp
[
'unit_cost__sum'
]
total_service_fees_temp
=
all_paid_certs
.
aggregate
(
Sum
(
'service_fee'
))
if
total_service_fees_temp
[
'service_fee__sum'
]
is
None
:
service_fees
=
Decimal
(
0.00
)
else
:
service_fees
=
total_service_fees_temp
[
'service_fee__sum'
]
refunded_enrollments
=
CertificateItem
.
objects
.
filter
(
course_id
=
course_id
,
status
=
"refunded"
)
num_refunds
=
refunded_enrollments
.
count
()
amount_refunds_temp
=
refunded_enrollments
.
aggregate
(
Sum
(
'unit_cost'
))
if
amount_refunds_temp
[
'unit_cost__sum'
]
is
None
:
amount_refunds
=
Decimal
(
0.00
)
else
:
amount_refunds
=
amount_refunds_temp
[
'unit_cost__sum'
]
result
=
[
result
=
[
university
,
university
,
...
@@ -753,7 +802,6 @@ class UniversityRevenueShareReport(Report):
...
@@ -753,7 +802,6 @@ class UniversityRevenueShareReport(Report):
num_transactions
,
num_transactions
,
total_payments_collected
,
total_payments_collected
,
service_fees
,
service_fees
,
refunded_enrollments
,
num_refunds
,
num_refunds
,
amount_refunds
amount_refunds
]
]
...
@@ -765,12 +813,11 @@ class UniversityRevenueShareReport(Report):
...
@@ -765,12 +813,11 @@ class UniversityRevenueShareReport(Report):
return
[
return
[
"University"
,
"University"
,
"Course"
,
"Course"
,
"Number of Transactions"
,
"Number of Transactions"
,
"Total Payments Collected"
,
"Total Payments Collected"
,
"Service Fees (if any)"
,
"Service Fees (if any)"
,
"Number of Successful Refunds"
,
"Number of Successful Refunds"
,
"Total Amount of Refunds"
,
"Total Amount of Refunds"
,
# note this is restricted by a date range
]
]
def
csv_report_row
(
self
,
item
):
def
csv_report_row
(
self
,
item
):
...
...
lms/djangoapps/shoppingcart/tests/test_models.py
View file @
fa87793e
...
@@ -364,7 +364,6 @@ class RefundReportTest(ModuleStoreTestCase):
...
@@ -364,7 +364,6 @@ class RefundReportTest(ModuleStoreTestCase):
refunded_certs
=
report
.
get_query
(
self
.
now
-
self
.
FIVE_MINS
,
self
.
now
+
self
.
FIVE_MINS
)
refunded_certs
=
report
.
get_query
(
self
.
now
-
self
.
FIVE_MINS
,
self
.
now
+
self
.
FIVE_MINS
)
self
.
assertEqual
(
len
(
refunded_certs
),
1
)
self
.
assertEqual
(
len
(
refunded_certs
),
1
)
self
.
assertIn
(
self
.
cert_item
,
refunded_certs
)
self
.
assertIn
(
self
.
cert_item
,
refunded_certs
)
# TODO no time restrictions yet
test_time
=
datetime
.
datetime
.
now
(
pytz
.
UTC
)
test_time
=
datetime
.
datetime
.
now
(
pytz
.
UTC
)
...
@@ -377,18 +376,13 @@ class RefundReportTest(ModuleStoreTestCase):
...
@@ -377,18 +376,13 @@ class RefundReportTest(ModuleStoreTestCase):
"""
"""
Tests that a generated purchase report CSV is as we expect
Tests that a generated purchase report CSV is as we expect
"""
"""
# coerce the purchase times to self.test_time so that the test can match.
# It's pretty hard to patch datetime.datetime b/c it's a python built-in, which is immutable, so we
# make the times match this way
# TODO test multiple report types
report_type
=
"refund_report"
report_type
=
"refund_report"
report
=
Report
.
initialize_report
(
report_type
)
report
=
Report
.
initialize_report
(
report_type
)
for
item
in
report
.
get_query
(
self
.
now
-
self
.
FIVE_MINS
,
self
.
now
+
self
.
FIVE_MINS
):
for
item
in
report
.
get_query
(
self
.
now
-
self
.
FIVE_MINS
,
self
.
now
+
self
.
FIVE_MINS
):
item
.
fulfilled_time
=
self
.
test_time
item
.
fulfilled_time
=
self
.
test_time
item
.
refund_requested_time
=
self
.
test_time
#
hm do we want to make these different
item
.
refund_requested_time
=
self
.
test_time
#
hm do we want to make these different
item
.
save
()
item
.
save
()
# add annotation to the
csv_file
=
StringIO
.
StringIO
()
csv_file
=
StringIO
.
StringIO
()
Report
.
make_report
(
report_type
,
csv_file
,
self
.
now
-
self
.
FIVE_MINS
,
self
.
now
+
self
.
FIVE_MINS
)
Report
.
make_report
(
report_type
,
csv_file
,
self
.
now
-
self
.
FIVE_MINS
,
self
.
now
+
self
.
FIVE_MINS
)
csv
=
csv_file
.
getvalue
()
csv
=
csv_file
.
getvalue
()
...
@@ -397,10 +391,11 @@ class RefundReportTest(ModuleStoreTestCase):
...
@@ -397,10 +391,11 @@ class RefundReportTest(ModuleStoreTestCase):
self
.
assertEqual
(
csv
.
replace
(
'
\r\n
'
,
'
\n
'
)
.
strip
(),
self
.
CORRECT_CSV
.
strip
())
self
.
assertEqual
(
csv
.
replace
(
'
\r\n
'
,
'
\n
'
)
.
strip
(),
self
.
CORRECT_CSV
.
strip
())
@override_settings
(
MODULESTORE
=
TEST_DATA_MONGO_MODULESTORE
)
@override_settings
(
MODULESTORE
=
TEST_DATA_MONGO_MODULESTORE
)
class
ItemizedPurchaseReportTest
(
ModuleStoreTestCase
):
class
ItemizedPurchaseReportTest
(
ModuleStoreTestCase
):
"""
Tests for the models used to generate itemized purchase reports
"""
FIVE_MINS
=
datetime
.
timedelta
(
minutes
=
5
)
FIVE_MINS
=
datetime
.
timedelta
(
minutes
=
5
)
TEST_ANNOTATION
=
u'Ba
\xfc\u5305
'
TEST_ANNOTATION
=
u'Ba
\xfc\u5305
'
...
@@ -428,15 +423,13 @@ class ItemizedPurchaseReportTest(ModuleStoreTestCase):
...
@@ -428,15 +423,13 @@ class ItemizedPurchaseReportTest(ModuleStoreTestCase):
self
.
now
=
datetime
.
datetime
.
now
(
pytz
.
UTC
)
self
.
now
=
datetime
.
datetime
.
now
(
pytz
.
UTC
)
def
test_purchased_items_btw_dates
(
self
):
def
test_purchased_items_btw_dates
(
self
):
# TODO test multiple report types
report_type
=
"itemized_purchase_report"
report_type
=
"itemized_purchase_report"
report
=
Report
.
initialize_report
(
report_type
)
report
=
Report
.
initialize_report
(
report_type
)
purchases
=
report
.
get_query
(
self
.
now
-
self
.
FIVE_MINS
,
self
.
now
+
self
.
FIVE_MINS
)
purchases
=
report
.
get_query
(
self
.
now
-
self
.
FIVE_MINS
,
self
.
now
+
self
.
FIVE_MINS
)
self
.
assertEqual
(
len
(
purchases
),
2
)
self
.
assertEqual
(
len
(
purchases
),
2
)
self
.
assertIn
(
self
.
reg
.
orderitem_ptr
,
purchases
)
self
.
assertIn
(
self
.
reg
.
orderitem_ptr
,
purchases
)
self
.
assertIn
(
self
.
cert_item
.
orderitem_ptr
,
purchases
)
self
.
assertIn
(
self
.
cert_item
.
orderitem_ptr
,
purchases
)
no_purchases
=
report
.
get_query
(
self
.
now
+
self
.
FIVE_MINS
,
no_purchases
=
report
.
get_query
(
self
.
now
+
self
.
FIVE_MINS
,
self
.
now
+
self
.
FIVE_MINS
+
self
.
FIVE_MINS
)
self
.
now
+
self
.
FIVE_MINS
+
self
.
FIVE_MINS
)
self
.
assertFalse
(
no_purchases
)
self
.
assertFalse
(
no_purchases
)
test_time
=
datetime
.
datetime
.
now
(
pytz
.
UTC
)
test_time
=
datetime
.
datetime
.
now
(
pytz
.
UTC
)
...
@@ -451,17 +444,12 @@ class ItemizedPurchaseReportTest(ModuleStoreTestCase):
...
@@ -451,17 +444,12 @@ class ItemizedPurchaseReportTest(ModuleStoreTestCase):
"""
"""
Tests that a generated purchase report CSV is as we expect
Tests that a generated purchase report CSV is as we expect
"""
"""
# coerce the purchase times to self.test_time so that the test can match.
# It's pretty hard to patch datetime.datetime b/c it's a python built-in, which is immutable, so we
# make the times match this way
# TODO test multiple report types
report_type
=
"itemized_purchase_report"
report_type
=
"itemized_purchase_report"
report
=
Report
.
initialize_report
(
report_type
)
report
=
Report
.
initialize_report
(
report_type
)
for
item
in
report
.
get_query
(
self
.
now
-
self
.
FIVE_MINS
,
self
.
now
+
self
.
FIVE_MINS
):
for
item
in
report
.
get_query
(
self
.
now
-
self
.
FIVE_MINS
,
self
.
now
+
self
.
FIVE_MINS
):
item
.
fulfilled_time
=
self
.
test_time
item
.
fulfilled_time
=
self
.
test_time
item
.
save
()
item
.
save
()
# add annotation to the
csv_file
=
StringIO
.
StringIO
()
csv_file
=
StringIO
.
StringIO
()
Report
.
make_report
(
report_type
,
csv_file
,
self
.
now
-
self
.
FIVE_MINS
,
self
.
now
+
self
.
FIVE_MINS
)
Report
.
make_report
(
report_type
,
csv_file
,
self
.
now
-
self
.
FIVE_MINS
,
self
.
now
+
self
.
FIVE_MINS
)
csv
=
csv_file
.
getvalue
()
csv
=
csv_file
.
getvalue
()
...
@@ -484,9 +472,12 @@ class ItemizedPurchaseReportTest(ModuleStoreTestCase):
...
@@ -484,9 +472,12 @@ class ItemizedPurchaseReportTest(ModuleStoreTestCase):
"""
"""
self
.
assertEqual
(
unicode
(
self
.
annotation
),
u'{} : {}'
.
format
(
self
.
course_id
,
self
.
TEST_ANNOTATION
))
self
.
assertEqual
(
unicode
(
self
.
annotation
),
u'{} : {}'
.
format
(
self
.
course_id
,
self
.
TEST_ANNOTATION
))
# TODO: finish this test class
@override_settings
(
MODULESTORE
=
TEST_DATA_MONGO_MODULESTORE
)
@override_settings
(
MODULESTORE
=
TEST_DATA_MONGO_MODULESTORE
)
class
CertificateStatusReportTest
(
ModuleStoreTestCase
):
class
CertificateStatusReportTest
(
ModuleStoreTestCase
):
"""
Tests for the models used to generate certificate status reports
"""
FIVE_MINS
=
datetime
.
timedelta
(
minutes
=
5
)
FIVE_MINS
=
datetime
.
timedelta
(
minutes
=
5
)
def
setUp
(
self
):
def
setUp
(
self
):
...
@@ -566,28 +557,38 @@ class CertificateStatusReportTest(ModuleStoreTestCase):
...
@@ -566,28 +557,38 @@ class CertificateStatusReportTest(ModuleStoreTestCase):
MITx,999 Robot Super Course,6,3,1,2,80.00,0.00,0,0,0
MITx,999 Robot Super Course,6,3,1,2,80.00,0.00,0,0,0
"""
.
format
(
time_str
=
str
(
test_time
)))
"""
.
format
(
time_str
=
str
(
test_time
)))
# TODO finish these tests. This is just a basic test to start with, making sure the regular
# flow doesn't throw any strange errors while running
def
test_basic
(
self
):
def
test_basic
(
self
):
report_type
=
"certificate_status"
report_type
=
"certificate_status"
report
=
Report
.
initialize_report
(
report_type
)
report
=
Report
.
initialize_report
(
report_type
)
refunded_certs
=
report
.
get_query
(
self
.
now
-
self
.
FIVE_MINS
,
self
.
now
+
self
.
FIVE_MINS
)
csv_file
=
StringIO
.
StringIO
()
csv_file
=
StringIO
.
StringIO
()
report
.
make_report
(
report_type
,
csv_file
,
self
.
now
-
self
.
FIVE_MINS
,
self
.
now
+
self
.
FIVE_MINS
)
report
.
make_report
(
report_type
,
csv_file
,
self
.
now
-
self
.
FIVE_MINS
,
self
.
now
+
self
.
FIVE_MINS
)
csv
=
csv_file
.
getvalue
()
csv
=
csv_file
.
getvalue
()
self
.
assertEqual
(
csv
.
replace
(
'
\r\n
'
,
'
\n
'
)
.
strip
(),
self
.
CORRECT_CSV
.
strip
())
self
.
assertEqual
(
csv
.
replace
(
'
\r\n
'
,
'
\n
'
)
.
strip
(),
self
.
CORRECT_CSV
.
strip
())
# TODO no time restrictions ye
# TODO: finish this test class
@override_settings
(
MODULESTORE
=
TEST_DATA_MONGO_MODULESTORE
)
@override_settings
(
MODULESTORE
=
TEST_DATA_MONGO_MODULESTORE
)
class
UniversityRevenueShareReportTest
(
ModuleStoreTestCase
):
class
UniversityRevenueShareReportTest
(
ModuleStoreTestCase
):
"""
Tests for the models used to generate university revenue share reports
"""
FIVE_MINS
=
datetime
.
timedelta
(
minutes
=
5
)
FIVE_MINS
=
datetime
.
timedelta
(
minutes
=
5
)
def
setUp
(
self
):
def
setUp
(
self
):
self
.
user
=
UserFactory
.
create
()
self
.
user1
=
UserFactory
.
create
()
self
.
user
.
first_name
=
"John"
self
.
user1
.
first_name
=
"John"
self
.
user
.
last_name
=
"Doe"
self
.
user1
.
last_name
=
"Doe"
self
.
user
.
save
()
self
.
user1
.
save
()
self
.
user2
=
UserFactory
.
create
()
self
.
user2
.
first_name
=
"Jane"
self
.
user2
.
last_name
=
"Deer"
self
.
user2
.
save
()
self
.
user3
=
UserFactory
.
create
()
self
.
user3
.
first_name
=
"Simon"
self
.
user3
.
last_name
=
"Blackquill"
self
.
user3
.
save
()
self
.
course_id
=
"MITx/999/Robot_Super_Course"
self
.
course_id
=
"MITx/999/Robot_Super_Course"
self
.
cost
=
40
self
.
cost
=
40
self
.
course
=
CourseFactory
.
create
(
org
=
'MITx'
,
number
=
'999'
,
display_name
=
u'Robot Super Course'
)
self
.
course
=
CourseFactory
.
create
(
org
=
'MITx'
,
number
=
'999'
,
display_name
=
u'Robot Super Course'
)
...
@@ -603,21 +604,37 @@ class UniversityRevenueShareReportTest(ModuleStoreTestCase):
...
@@ -603,21 +604,37 @@ class UniversityRevenueShareReportTest(ModuleStoreTestCase):
min_price
=
self
.
cost
)
min_price
=
self
.
cost
)
course_mode2
.
save
()
course_mode2
.
save
()
self
.
cart
=
Order
.
get_cart_for_user
(
self
.
user
)
# user1 is a verified purchase
self
.
cart
=
Order
.
get_cart_for_user
(
self
.
user1
)
CertificateItem
.
add_to_order
(
self
.
cart
,
self
.
course_id
,
self
.
cost
,
'verified'
)
self
.
cart
.
purchase
()
# user2 & user3 are refunded purchases
self
.
cart
=
Order
.
get_cart_for_user
(
self
.
user2
)
CertificateItem
.
add_to_order
(
self
.
cart
,
self
.
course_id
,
self
.
cost
,
'verified'
)
CertificateItem
.
add_to_order
(
self
.
cart
,
self
.
course_id
,
self
.
cost
,
'verified'
)
self
.
cart
.
purchase
()
self
.
cart
.
purchase
()
CourseEnrollment
.
unenroll
(
self
.
user2
,
self
.
course_id
)
self
.
cart
=
Order
.
get_cart_for_user
(
self
.
user3
)
CertificateItem
.
add_to_order
(
self
.
cart
,
self
.
course_id
,
self
.
cost
,
'verified'
)
self
.
cart
.
purchase
()
CourseEnrollment
.
unenroll
(
self
.
user3
,
self
.
course_id
)
self
.
now
=
datetime
.
datetime
.
now
(
pytz
.
UTC
)
self
.
now
=
datetime
.
datetime
.
now
(
pytz
.
UTC
)
# TODO finish these tests. This is just a basic test to start with, making sure the regular
test_time
=
datetime
.
datetime
.
now
(
pytz
.
UTC
)
# flow doesn't throw any strange errors while running
CORRECT_CSV
=
dedent
(
"""
University,Course,Number of Transactions,Total Payments Collected,Service Fees (if any),Number of Successful Refunds,Total Amount of Refunds
MITx,999 Robot Super Course,0,40.00,0,2,80.00
"""
.
format
(
time_str
=
str
(
test_time
)))
def
test_basic
(
self
):
def
test_basic
(
self
):
report_type
=
"university_revenue_share"
report_type
=
"university_revenue_share"
report
=
Report
.
initialize_report
(
report_type
)
report
=
Report
.
initialize_report
(
report_type
)
refunded_certs
=
report
.
get_query
(
self
.
now
-
self
.
FIVE_MINS
,
self
.
now
+
self
.
FIVE_MINS
)
csv_file
=
StringIO
.
StringIO
()
csv_file
=
StringIO
.
StringIO
()
report
.
make_report
(
report_type
,
csv_file
,
self
.
now
-
self
.
FIVE_MINS
,
self
.
now
+
self
.
FIVE_MINS
)
report
.
make_report
(
report_type
,
csv_file
,
self
.
now
-
self
.
FIVE_MINS
,
self
.
now
+
self
.
FIVE_MINS
)
# TODO no time restrictions yet
csv
=
csv_file
.
getvalue
()
self
.
assertEqual
(
csv
.
replace
(
'
\r\n
'
,
'
\n
'
)
.
strip
(),
self
.
CORRECT_CSV
.
strip
())
@override_settings
(
MODULESTORE
=
TEST_DATA_MONGO_MODULESTORE
)
@override_settings
(
MODULESTORE
=
TEST_DATA_MONGO_MODULESTORE
)
...
...
lms/djangoapps/shoppingcart/tests/test_views.py
View file @
fa87793e
...
@@ -14,7 +14,7 @@ from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
...
@@ -14,7 +14,7 @@ from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from
xmodule.modulestore.tests.factories
import
CourseFactory
from
xmodule.modulestore.tests.factories
import
CourseFactory
from
courseware.tests.tests
import
TEST_DATA_MONGO_MODULESTORE
from
courseware.tests.tests
import
TEST_DATA_MONGO_MODULESTORE
from
shoppingcart.views
import
_can_download_report
,
_get_date_from_str
from
shoppingcart.views
import
_can_download_report
,
_get_date_from_str
from
shoppingcart.models
import
Order
,
CertificateItem
,
PaidCourseRegistration
,
OrderItem
,
Report
from
shoppingcart.models
import
Order
,
CertificateItem
,
PaidCourseRegistration
,
Report
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.models
import
CourseMode
from
course_modes.models
import
CourseMode
...
...
lms/djangoapps/verify_student/views.py
View file @
fa87793e
...
@@ -132,7 +132,6 @@ def create_order(request):
...
@@ -132,7 +132,6 @@ def create_order(request):
"""
"""
Submit PhotoVerification and create a new Order for this verified cert
Submit PhotoVerification and create a new Order for this verified cert
"""
"""
from
nose.tools
import
set_trace
;
set_trace
()
if
not
SoftwareSecurePhotoVerification
.
user_has_valid_or_pending
(
request
.
user
):
if
not
SoftwareSecurePhotoVerification
.
user_has_valid_or_pending
(
request
.
user
):
attempt
=
SoftwareSecurePhotoVerification
(
user
=
request
.
user
)
attempt
=
SoftwareSecurePhotoVerification
(
user
=
request
.
user
)
b64_face_image
=
request
.
POST
[
'face_image'
]
.
split
(
","
)[
1
]
b64_face_image
=
request
.
POST
[
'face_image'
]
.
split
(
","
)[
1
]
...
...
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