Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
C
course-discovery
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
course-discovery
Commits
0d37014e
Commit
0d37014e
authored
Feb 16, 2017
by
Simon Chen
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add program total price to the price_ranges array ECOM-7023
parent
759512a8
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
113 additions
and
1 deletions
+113
-1
course_discovery/apps/course_metadata/models.py
+57
-0
course_discovery/apps/course_metadata/tests/test_models.py
+56
-1
No files found.
course_discovery/apps/course_metadata/models.py
View file @
0d37014e
...
...
@@ -810,18 +810,75 @@ class Program(TimeStampedModel):
def
seat_types
(
self
):
return
set
(
seat
.
type
for
seat
in
self
.
seats
)
def
_get_total_price_by_currency
(
self
):
"""
This helper function returns the total program price indexed by the currency
"""
currencies_with_total
=
defaultdict
()
course_map
=
defaultdict
(
list
)
for
seat
in
self
.
seats
:
course_uuid
=
seat
.
course_run
.
course
.
uuid
# Identify the most relevant course_run seat for a course.
# And use the price of the seat to represent the price of the course
selected_seats
=
course_map
.
get
(
course_uuid
)
if
not
selected_seats
:
# if we do not have this course yet, create the seats array
course_map
[
course_uuid
]
=
[
seat
]
else
:
add_seat
=
False
seats_to_remove
=
[]
for
selected_seat
in
selected_seats
:
if
seat
.
currency
!=
selected_seat
.
currency
:
# If the candidate seat has a different currency than the one in the array,
# always add to the array
add_seat
=
True
elif
((
seat
.
course_run
.
end
is
None
or
seat
.
course_run
.
end
>=
datetime
.
datetime
.
now
(
pytz
.
UTC
))
and
(
seat
.
course_run
.
enrollment_start
is
None
or
seat
.
course_run
.
enrollment_start
>
selected_seat
.
course_run
.
enrollment_start
and
seat
.
course_run
.
enrollment_start
<
datetime
.
datetime
.
now
(
pytz
.
UTC
))):
# If the seat has same currency, the course has not ended,
# and the course is enrollable, then choose the new seat associated with the course instead,
# and mark the original seat in the array to be removed
logger
.
info
(
"Use course_run {} instead of course_run {} for total program price calculation"
.
format
(
seat
.
course_run
.
key
,
selected_seat
.
course_run
.
key
)
)
add_seat
=
True
seats_to_remove
.
append
(
selected_seat
)
if
add_seat
:
course_map
[
course_uuid
]
.
append
(
seat
)
for
seat
in
seats_to_remove
:
# Now remove the seats that should not be counted for calculation for program total
course_map
[
course_uuid
]
.
remove
(
seat
)
# Now calculate the total price of the program indexed by currency
for
course_seats
in
course_map
.
values
():
for
seat
in
course_seats
:
current_total
=
currencies_with_total
.
get
(
seat
.
currency
,
0
)
current_total
+=
seat
.
price
currencies_with_total
[
seat
.
currency
]
=
current_total
return
currencies_with_total
@property
def
price_ranges
(
self
):
currencies
=
defaultdict
(
list
)
for
seat
in
self
.
seats
:
currencies
[
seat
.
currency
]
.
append
(
seat
.
price
)
total_by_currency
=
self
.
_get_total_price_by_currency
()
price_ranges
=
[]
for
currency
,
prices
in
currencies
.
items
():
price_ranges
.
append
({
'currency'
:
currency
.
code
,
'min'
:
min
(
prices
),
'max'
:
max
(
prices
),
'total'
:
total_by_currency
.
get
(
currency
,
0
)
})
return
price_ranges
...
...
course_discovery/apps/course_metadata/tests/test_models.py
View file @
0d37014e
import
datetime
import
itertools
from
decimal
import
Decimal
...
...
@@ -485,9 +486,63 @@ class ProgramTests(MarketingSitePublisherTestMixin):
self
.
assertIsNone
(
self
.
program
.
start
)
def
test_price_ranges
(
self
):
""" Verify the price_ranges property of the program is returning expected price values """
program
=
self
.
create_program_with_seats
()
expected_price_ranges
=
[{
'currency'
:
'USD'
,
'min'
:
Decimal
(
100
),
'max'
:
Decimal
(
600
)}]
expected_price_ranges
=
[{
'currency'
:
'USD'
,
'min'
:
Decimal
(
100
),
'max'
:
Decimal
(
600
),
'total'
:
Decimal
(
600
)}]
self
.
assertEqual
(
program
.
price_ranges
,
expected_price_ranges
)
def
test_price_ranges_multiple_course
(
self
):
""" Verifies the price_range property of a program with multiple courses """
currency
=
Currency
.
objects
.
get
(
code
=
'USD'
)
test_price
=
100
for
course_run
in
self
.
course_runs
:
factories
.
SeatFactory
(
type
=
'audit'
,
currency
=
currency
,
course_run
=
course_run
,
price
=
0
)
factories
.
SeatFactory
(
type
=
'verified'
,
currency
=
currency
,
course_run
=
course_run
,
price
=
test_price
)
test_price
+=
100
applicable_seat_types
=
SeatType
.
objects
.
filter
(
slug__in
=
[
'verified'
])
program_type
=
factories
.
ProgramTypeFactory
(
applicable_seat_types
=
applicable_seat_types
)
self
.
program
.
type
=
program_type
expected_price_ranges
=
[{
'currency'
:
'USD'
,
'min'
:
Decimal
(
100
),
'max'
:
Decimal
(
300
),
'total'
:
Decimal
(
600
)}]
self
.
assertEqual
(
self
.
program
.
price_ranges
,
expected_price_ranges
)
def
create_program_with_multiple_course_runs
(
self
):
currency
=
Currency
.
objects
.
get
(
code
=
'USD'
)
single_course_course_runs
=
factories
.
CourseRunFactory
.
create_batch
(
3
)
course
=
factories
.
CourseFactory
()
course_runs_same_course
=
factories
.
CourseRunFactory
.
create_batch
(
2
,
course
=
course
)
for
course_run
in
single_course_course_runs
:
factories
.
SeatFactory
(
type
=
'audit'
,
currency
=
currency
,
course_run
=
course_run
,
price
=
0
)
factories
.
SeatFactory
(
type
=
'verified'
,
currency
=
currency
,
course_run
=
course_run
,
price
=
10
)
day_diff
=
1
for
course_run
in
course_runs_same_course
:
course_run
.
enrollment_start
=
datetime
.
datetime
.
now
()
-
datetime
.
timedelta
(
days
=
day_diff
)
course_run
.
end
=
datetime
.
datetime
.
now
()
+
datetime
.
timedelta
(
weeks
=
day_diff
)
course_run
.
save
()
factories
.
SeatFactory
(
type
=
'audit'
,
currency
=
currency
,
course_run
=
course_run
,
price
=
0
)
factories
.
SeatFactory
(
type
=
'verified'
,
currency
=
currency
,
course_run
=
course_run
,
price
=
(
day_diff
*
100
))
day_diff
+=
1
applicable_seat_types
=
SeatType
.
objects
.
filter
(
slug__in
=
[
'verified'
])
program_type
=
factories
.
ProgramTypeFactory
(
applicable_seat_types
=
applicable_seat_types
)
program_courses
=
[
course_run
.
course
for
course_run
in
single_course_course_runs
]
program_courses
.
append
(
course
)
return
factories
.
ProgramFactory
(
type
=
program_type
,
courses
=
program_courses
)
def
test_price_ranges_with_multiple_course_runs
(
self
):
"""
Verifies the price_range property of a program with multiple courses,
and a course with multiple runs
"""
program
=
self
.
create_program_with_multiple_course_runs
()
expected_price_ranges
=
[{
'currency'
:
'USD'
,
'min'
:
Decimal
(
10
),
'max'
:
Decimal
(
200
),
'total'
:
Decimal
(
130
)}]
self
.
assertEqual
(
program
.
price_ranges
,
expected_price_ranges
)
def
test_staff
(
self
):
...
...
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