Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release 0.160.6 #3179

Open
wants to merge 2 commits into
base: release
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions RELEASE.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
Release Notes
=============

Version 0.160.6
---------------

- feat: skip non usd emeritus courses (#3174)

Version 0.160.5 (Released October 07, 2024)
---------------

Expand Down
46 changes: 39 additions & 7 deletions courses/sync_external_courses/emeritus_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ class EmeritusKeyMap(Enum):
REPORT_NAMES = ["Batch"]
PLATFORM_NAME = "Emeritus"
DATE_FORMAT = "%Y-%m-%d"
REQUIRED_FIELDS = [
"course_title",
"course_code",
"course_run_code",
"list_currency",
]
COURSE_PAGE_SUBHEAD = "Delivered in collaboration with Emeritus."
WHO_SHOULD_ENROLL_PAGE_HEADING = "WHO SHOULD ENROLL"
LEARNING_OUTCOMES_PAGE_HEADING = "WHAT YOU WILL LEARN"
Expand Down Expand Up @@ -81,6 +87,7 @@ def __init__(self, emeritus_course_json):
if emeritus_course_json.get("list_price")
else None
)
self.list_currency = emeritus_course_json.get("list_currency")

self.start_date = strip_datetime(
emeritus_course_json.get("start_date"), EmeritusKeyMap.DATE_FORMAT.value
Expand Down Expand Up @@ -123,6 +130,33 @@ def __init__(self, emeritus_course_json):
else []
)

def validate_required_fields(self):
"""
Validates the course data.
"""
for field in EmeritusKeyMap.REQUIRED_FIELDS.value:
if not getattr(self, field, None):
log.info(f"Missing required field {field}") # noqa: G004
return False
return True

def validate_list_currency(self):
"""
Validates that the price is in USD.

We only support `USD`. To support any other currency, we will have to manage the conversion to `USD`.
"""
if self.list_currency != "USD":
log.info(f"Invalid currency: {self.list_currency}.") # noqa: G004
return False
return True

def validate_end_date(self):
"""
Validates that the course end date is in the future.
"""
return self.end_date and now_in_utc() < self.end_date


def fetch_emeritus_courses():
"""
Expand Down Expand Up @@ -225,19 +259,17 @@ def update_emeritus_course_runs(emeritus_courses): # noqa: C901, PLR0915
emeritus_course.course_run_code,
)
)
# If course_title, course_code, or course_run_code is missing, skip.
if not (
emeritus_course.course_title
and emeritus_course.course_code
and emeritus_course.course_run_code
if (
not emeritus_course.validate_required_fields()
or not emeritus_course.validate_list_currency()
):
log.info(
f"Missing required course data. Skipping... Course data: {json.dumps(emeritus_course_json)}" # noqa: G004
f"Skipping due to bad data... Course data: {json.dumps(emeritus_course_json)}" # noqa: G004
)
stats["course_runs_skipped"].add(emeritus_course.course_run_code)
continue

if now_in_utc() > emeritus_course.end_date:
if not emeritus_course.validate_end_date():
log.info(
f"Course run is expired, Skipping... Course data: {json.dumps(emeritus_course_json)}" # noqa: G004
)
Expand Down
96 changes: 94 additions & 2 deletions courses/sync_external_courses/emeritus_api_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
)
from ecommerce.factories import ProductFactory, ProductVersionFactory
from mitxpro.test_utils import MockResponse
from mitxpro.utils import clean_url
from mitxpro.utils import clean_url, now_in_utc


@pytest.fixture
Expand Down Expand Up @@ -92,6 +92,17 @@ def emeritus_course_data_with_null_price(emeritus_course_data):
return emeritus_course_json


@pytest.fixture
def emeritus_course_data_with_non_usd_price(emeritus_course_data):
"""
Emeritus course JSON with non USD price.
"""
emeritus_course_json = emeritus_course_data.copy()
emeritus_course_json["list_currency"] = "INR"
emeritus_course_json["course_run_code"] = "MO-INRC-98-10#1"
return emeritus_course_json


@pytest.mark.parametrize(
("emeritus_course_run_code", "expected_course_run_tag"),
[
Expand Down Expand Up @@ -430,6 +441,7 @@ def test_update_emeritus_course_runs( # noqa: PLR0915
emeritus_expired_course_data,
emeritus_course_with_bad_data,
emeritus_course_data_with_null_price,
emeritus_course_data_with_non_usd_price,
):
"""
Tests that `update_emeritus_course_runs` creates new courses and updates existing.
Expand Down Expand Up @@ -477,6 +489,7 @@ def test_update_emeritus_course_runs( # noqa: PLR0915
emeritus_course_runs.append(emeritus_expired_course_data)
emeritus_course_runs.append(emeritus_course_with_bad_data)
emeritus_course_runs.append(emeritus_course_data_with_null_price)
emeritus_course_runs.append(emeritus_course_data_with_non_usd_price)
stats = update_emeritus_course_runs(emeritus_course_runs)
courses = Course.objects.filter(platform=platform)

Expand All @@ -489,7 +502,7 @@ def test_update_emeritus_course_runs( # noqa: PLR0915
num_products_created = 2 if create_existing_data else 4
num_product_versions_created = 2 if create_existing_data else 4
assert len(courses) == 4
assert len(stats["course_runs_skipped"]) == 1
assert len(stats["course_runs_skipped"]) == 2
assert len(stats["course_runs_expired"]) == 1
assert len(stats["courses_created"]) == num_courses_created
assert len(stats["existing_courses"]) == num_existing_courses
Expand Down Expand Up @@ -725,3 +738,82 @@ def test_save_page_revision(is_draft_page, has_unpublished_changes):

if has_unpublished_changes:
assert external_course_page.has_unpublished_changes


@pytest.mark.parametrize(
("title", "course_code", "course_run_code", "is_valid"),
[
(
"Internet of Things (IoT): Design and Applications",
"MO-DBIP",
"MO-DBIP.ELE-99-07#1",
True,
),
("", "MO-DBIP", "MO-DBIP.ELE-99-07#1", False),
(None, "MO-DBIP", "MO-DBIP.ELE-99-07#1", False),
(
"Internet of Things (IoT): Design and Applications",
"",
"MO-DBIP.ELE-99-07#1",
False,
),
(
"Internet of Things (IoT): Design and Applications",
None,
"MO-DBIP.ELE-99-07#1",
False,
),
("Internet of Things (IoT): Design and Applications", "MO-DBIP", "", False),
("Internet of Things (IoT): Design and Applications", "MO-DBIP", None, False),
("", "", "", False),
(None, None, None, False),
],
)
def test_emeritus_course_validate_required_fields(
emeritus_course_data, title, course_code, course_run_code, is_valid
):
"""
Tests that EmeritusCourse.validate_required_fields validates required fields.
"""
emeritus_course = EmeritusCourse(emeritus_course_data)
emeritus_course.course_title = title
emeritus_course.course_code = course_code
emeritus_course.course_run_code = course_run_code
assert emeritus_course.validate_required_fields() == is_valid


@pytest.mark.parametrize(
("list_currency", "is_valid"),
[
("USD", True),
("INR", False),
("EUR", False),
("GBP", False),
("PKR", False),
],
)
def test_emeritus_course_validate_list_currency(
emeritus_course_data, list_currency, is_valid
):
"""
Tests that the `USD` is the only valid currency for the Emeritus courses.
"""
emeritus_course = EmeritusCourse(emeritus_course_data)
emeritus_course.list_currency = list_currency
assert emeritus_course.validate_list_currency() == is_valid


@pytest.mark.parametrize(
("end_date", "is_valid"),
[
(now_in_utc() + timedelta(days=1), True),
(now_in_utc() - timedelta(days=1), False),
],
)
def test_emeritus_course_validate_end_date(emeritus_course_data, end_date, is_valid):
"""
Tests that the valid end date is in the future for Emeritus courses.
"""
emeritus_course = EmeritusCourse(emeritus_course_data)
emeritus_course.end_date = end_date
assert emeritus_course.validate_end_date() == is_valid
4 changes: 2 additions & 2 deletions courses/sync_external_courses/test_data/batch_test.json
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@
"end_date": "2099-12-29",
"Category": "Healthcare",
"list_price": 7650,
"list_currency": null,
"list_currency": "USD",
"total_weeks": 28,
"product_family": "SEPO",
"product_sub_type": "Online",
Expand All @@ -151,7 +151,7 @@
"end_date": "2099-02-23",
"Category": "Technology",
"list_price": 7650,
"list_currency": null,
"list_currency": "USD",
"total_weeks": 29,
"product_family": "SEPO",
"product_sub_type": "Online",
Expand Down
2 changes: 1 addition & 1 deletion mitxpro/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
from mitxpro.celery_utils import OffsettingSchedule
from mitxpro.sentry import init_sentry

VERSION = "0.160.5"
VERSION = "0.160.6"

env.reset()

Expand Down
Loading