Commit 78289321 by Simon Chen

Fix second bug with Program total price calculation ECOM-7023

parent 735a635a
......@@ -810,6 +810,28 @@ class Program(TimeStampedModel):
def seat_types(self):
return set(seat.type for seat in self.seats)
def _select_for_total_price(self, selected_seat, candidate_seat):
"""
A helper function to determine which course_run seat is best suitable to be used to calculate
the program total price. A seat is most suitable if the related course_run is now enrollable,
has not ended, and the enrollment_start date is most recent
"""
end_valid = candidate_seat.course_run.end is None or \
candidate_seat.course_run.end >= datetime.datetime.now(pytz.UTC)
selected_enrollment_start = selected_seat.course_run.enrollment_start or \
pytz.utc.localize(datetime.datetime.min)
# Only select the candidate seat if the candidate seat has no enrollment start,
# or make sure the candidate course_run is enrollable and
# the candidate seat enrollment start is most recent
enrollment_start_valid = candidate_seat.course_run.enrollment_start is None or (
candidate_seat.course_run.enrollment_start > selected_enrollment_start and
candidate_seat.course_run.enrollment_start < datetime.datetime.now(pytz.UTC)
)
return end_valid and enrollment_start_valid
def _get_total_price_by_currency(self):
"""
This helper function returns the total program price indexed by the currency
......@@ -832,12 +854,7 @@ class Program(TimeStampedModel):
# 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 or datetime.datetime.min) and
seat.course_run.enrollment_start < datetime.datetime.now(pytz.UTC))):
elif self._select_for_total_price(selected_seat, seat):
# 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
......
......@@ -513,20 +513,27 @@ class ProgramTests(MarketingSitePublisherTestMixin):
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)
course_runs_same_course = factories.CourseRunFactory.create_batch(3, 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
day_separation = 1
for course_run in course_runs_same_course:
if set_all_dates or day_diff > 1:
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()
if set_all_dates or day_separation < 2:
course_run.enrollment_start = datetime.datetime.now() - datetime.timedelta(days=day_separation)
course_run.end = datetime.datetime.now() + datetime.timedelta(weeks=day_separation)
else:
course_run.enrollment_start = None
course_run.end = None
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
factories.SeatFactory(
type='verified',
currency=currency,
course_run=course_run,
price=(day_separation * 100))
day_separation += 1
applicable_seat_types = SeatType.objects.filter(slug__in=['verified'])
program_type = factories.ProgramTypeFactory(applicable_seat_types=applicable_seat_types)
......@@ -543,7 +550,7 @@ class ProgramTests(MarketingSitePublisherTestMixin):
"""
program = self.create_program_with_multiple_course_runs()
expected_price_ranges = [{'currency': 'USD', 'min': Decimal(10), 'max': Decimal(200), 'total': Decimal(130)}]
expected_price_ranges = [{'currency': 'USD', 'min': Decimal(10), 'max': Decimal(300), 'total': Decimal(130)}]
self.assertEqual(program.price_ranges, expected_price_ranges)
def test_price_ranges_with_multiple_course_runs_and_none_dates(self):
......@@ -553,7 +560,7 @@ class ProgramTests(MarketingSitePublisherTestMixin):
"""
program = self.create_program_with_multiple_course_runs(set_all_dates=False)
expected_price_ranges = [{'currency': 'USD', 'min': Decimal(10), 'max': Decimal(200), 'total': Decimal(230)}]
expected_price_ranges = [{'currency': 'USD', 'min': Decimal(10), 'max': Decimal(300), 'total': Decimal(130)}]
self.assertEqual(program.price_ranges, expected_price_ranges)
def test_staff(self):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment