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

feat: take exec ed course data from course run instead of additional_metadata (take 2) #912

Merged
merged 1 commit into from
Sep 26, 2024

Conversation

marlonkeating
Copy link
Contributor

Description

Updates references for Exec Ed courses originally contained in the additional_metadata field, to now be taken from course runs. Fixing issues that were found in earlier attempt: #785

Ticket Link

ENT-8248: update custom logic for non-ocm courses in enterprise-catalog

Outstanding Questions

  • Do we still need to process Exec Ed courses differently from OCM courses?

Post-review

  • Squash commits into discrete sets of changes
  • Ensure that once the changes have been deployed to stage, prod is manually deployed

@marlonkeating marlonkeating force-pushed the mkeating/ENT-8248-2 branch 2 times, most recently from 47e3477 to 181df4e Compare September 6, 2024 00:28
Copy link
Member

@adamstankiewicz adamstankiewicz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for updating 😺 @brobro10000 and I did a pair PR review on the changes and left some additional questions/clarifications/suggestions/etc.

Let us know if you want to rubber duck on anything!

enterprise_catalog/apps/api/tests/test_tasks.py Outdated Show resolved Hide resolved
enterprise_catalog/apps/api/tests/test_tasks.py Outdated Show resolved Hide resolved
enterprise_catalog/apps/api/tests/test_tasks.py Outdated Show resolved Hide resolved
Comment on lines 249 to 255
if course_json_metadata.get('course_type') == EXEC_ED_2U_COURSE_TYPE:
additional_metadata = course_json_metadata.get('additional_metadata') or {}
registration_deadline = additional_metadata.get('registration_deadline')
if registration_deadline:
enrollment_end = advertised_course_run.get('end') or {}
if enrollment_end:
enroll_by_deadline_timestamp = datetime.datetime.strptime(
registration_deadline,
enrollment_end,
'%Y-%m-%dT%H:%M:%S%z',
).timestamp()
else:
enroll_by_deadline_timestamp = _get_verified_upgrade_deadline(advertised_course_run)

return enroll_by_deadline_timestamp < localized_utcnow().timestamp()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[clarification] Could we use the normalized_metadata that exists from the course_json_metadata passed into this method? That is, could we refer to the consolidated content metadata across course types already exposed without having to introduce similar conditional branching logic based on course_type?

normalized_metadata has this branching logic abstracted away.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From what I can see we should be able to use normalized_metadata... I just read through https://github.com/openedx/enterprise-catalog/blob/master/docs/decisions/0007-normalized-metadata-course-types.rst, and is it still the position that we aren't making an active effort to change over to using normalized_metadata in business logic, it is available for use where convenient?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When normalized_metadata was introduced, we limited the scope to be an additive-only change, with the plan to incrementally migrate to normalized_metadata anywhere we had existing branching logic between course types (i.e., OCM vs EE) around metadata like dates/price/etc. We have switched over to normalized_metadata in several places already on various consuming services, so this is another incremental opportunity to simplify the existing implementation by relying on the abstraction. The hope is that relying on normalized_metadata makes content metadata easier to reason about when parsing it within business logic such as here.

enterprise_catalog/apps/catalog/tests/test_serializers.py Outdated Show resolved Hide resolved
enterprise_catalog/apps/catalog/tests/test_serializers.py Outdated Show resolved Hide resolved
enterprise_catalog/apps/catalog/algolia_utils.py Outdated Show resolved Hide resolved
@marlonkeating marlonkeating force-pushed the mkeating/ENT-8248-2 branch 3 times, most recently from 6c9fe89 to 47055b6 Compare September 11, 2024 21:34
Copy link
Contributor

@brobro10000 brobro10000 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good on my end, curious about 1 nit though 👍🏽

enterprise_catalog/apps/catalog/algolia_utils.py Outdated Show resolved Hide resolved
return upgrade_deadline or self.course_run_metadata.get('enrollment_end')

enrollment_end = self.course_run_metadata.get('enrollment_end')
return min(filter(None, [upgrade_deadline, enrollment_end]), default=None)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🥳

Comment on lines 33 to 51
def _days_from_now_ts(days_from_now=0):
deadline = _days_from_now(days_from_now)
return {'str': deadline, 'timestamp': to_timestamp(deadline)}


TOMORROW, NEXT_WEEK, NEXT_MONTH = [_days_from_now_ts(days) for days in [1, 7, 30]]
NEXT_MONTH_DATE = _days_from_now(30)


Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🥳

Comment on lines 249 to 255
if 'normalized_metadata' in course_json_metadata:
enroll_by_deadline = course_json_metadata['normalized_metadata']['enroll_by_date']
enroll_by_deadline_timestamp = datetime.datetime.strptime(
enroll_by_deadline,
'%Y-%m-%dT%H:%M:%S%z',
).timestamp()
elif course_json_metadata.get('course_type') == EXEC_ED_2U_COURSE_TYPE:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[curious/suggestion] When will normalized_metadata not exist in course_json_metadata, where the fallback elif is needed? I think the conditional around whether normalized_metadata exists and the fallback elif could probably be removed 🤔 Rationale: normalized_metadata is added to ContentMetadata's json_metadata during the update_content_metadata so I believe it's a fair assumption it will always exist (source).

Given this, I believe the pre-existing Exec Ed vs. OCM checks here and below (i.e., _get_verified_upgrade_deadline) could be removed to only rely on normalized_metadata as the logic below is essentially duplicative of normalized_metadata.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it, removed the check so we're only going by normalized_metadata now.

enterprise_catalog/apps/catalog/algolia_utils.py Outdated Show resolved Hide resolved
@@ -1103,6 +1107,7 @@ def _get_course_run(full_course_run):
'availability': full_course_run.get('availability'),
'start': full_course_run.get('start'),
'end': full_course_run.get('end'),
'enrollment_end': full_course_run.get('enrollment_end'),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[clarification] Is enrollment_end already abstracted into the enroll_by field below? I would consider this enrollment_end deprecated similar to upgrade_deadline, in favor of relying on the transformed "interface" for enroll_by.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point! Removed it.

@@ -130,12 +130,18 @@ def get_end_date(self, obj) -> str: # pylint: disable=unused-argument
def get_enroll_by_date(self, obj) -> str: # pylint: disable=unused-argument
if not self.course_run_metadata:
return None

if self.course.is_exec_ed_2u_course:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice cleanup here to short-circuit for the Exec Ed case!

Copy link
Contributor

@brobro10000 brobro10000 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🥳 LGTM 👍🏽

…metadata attempt 2

fix: calculate enroll_by correctly

test: fix unit tests pt2

fix: use normalized_metadata for deadline check

fix: remove logging

fix: use normalized_metadata for calculating course deadlines
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants