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: create DefaultEnterpriseEnrollmentRealization during bulk enrollment #2276

Merged
merged 2 commits into from
Nov 6, 2024

Conversation

adamstankiewicz
Copy link
Member

@adamstankiewicz adamstankiewicz commented Oct 30, 2024

Description

Goal: When using the bulk enrollment API to auto-enroll learners in default enterprise enrollment intentions, related DefaultEnterpriseEnrollmentRealization records should be created.

ENT-9684

CHANGELOG

  • Extended the enroll_learners_in_courses POST API within EnterpriseCustomerViewSet to (optionally) accept a new property is_default_auto_enrollment: <boolean> on each bulk enrollment attempt. When is_default_auto_enrollment is True and the enrollment has succeeded:

    • Perform a lookup of DefaultEnterpriseEnrollmentIntention records that exist for the enterprise customer.
    • Find a matching DefaultEnterpriseEnrollmentIntention to the associated EnterpriseCourseEnrollment based on matching course run key for the intention and course id in the enrollment.
    • If a matching DefaultEnterpriseEnrollmentIntention is found, gets/creates DefaultEnterpriseEnrollmentRealization record for the intended_enrollment and realized_enrollment.
  • Updated DefaultEnterpriseEnrollmentRealization model to alter the realized_enrollment field to be a OneToOneField instead of a ForeignKey. This change makes it have more parity with the related models like LicensedEnterpriseCourseEnrollment and LearnerCreditEnterpriseCourseEnrollment.

  • Added property default_enterprise_enrollment_realization to EnterpriseCourseEnrollment model, similar to the existing license and learner_credit_fulfillment properties.

  • Resolves deprecation warning with SoftDeleteableModel related to the DefaultEnterpriseEnrollmentIntention model.

DeprecationWarning: ModelBase.objects model manager will include soft-deleted objects in an upcoming release; please use ModelBase.available_objects to continue excluding soft-deleted objects. See https://django-model-utils.readthedocs.io/en/stable/models.html#softdeletablemodel for more information.

  • Renames a field in the metadata dictionary returned by the DefaultEnterpriseEnrollmentIntentionViewSet (learner_status action).
    • I.e., total_default_enterprise_course_enrollments -> total_default_enterprise_enrollment_intentions

Merge checklist:

  • Any new requirements are in the right place (do not manually modify the requirements/*.txt files)
    • base.in if needed in production but edx-platform doesn't install it
    • test-master.in if edx-platform pins it, with a matching version
    • make upgrade && make requirements have been run to regenerate requirements
  • make static has been run to update webpack bundling if any static content was updated
  • ./manage.py makemigrations has been run
    • Checkout the Database Migration Confluence page for helpful tips on creating migrations.
    • Note: This must be run if you modified any models.
      • It may or may not make a migration depending on exactly what you modified, but it should still be run.
    • This should be run from either a venv with all the lms/edx-enterprise requirements installed or if you checked out edx-enterprise into the src directory used by lms, you can run this command through an lms shell.
      • It would be ./manage.py lms makemigrations in the shell.
  • Version bumped
  • Changelog record added
  • Translations updated (see docs/internationalization.rst but also this isn't blocking for merge atm)

Post merge:

  • Tag pushed and a new version released
    • Note: Assets will be added automatically. You just need to provide a tag (should match your version number) and title and description.
  • After versioned build finishes in GitHub Actions, verify version has been pushed to PyPI
    • Each step in the release build has a condition flag that checks if the rest of the steps are done and if so will deploy to PyPi.
      (so basically once your build finishes, after maybe a minute you should see the new version in PyPi automatically (on refresh))
  • PR created in edx-platform to upgrade dependencies (including edx-enterprise)
    • Trigger the 'Upgrade one Python dependency' action against master in edx-platform with new version number to generate version bump PR
    • This must be done after the version is visible in PyPi as make upgrade in edx-platform will look for the latest version in PyPi.
    • Note: the edx-enterprise constraint in edx-platform must also be bumped to the latest version in PyPi.

Copy link
Contributor

@iloveagent57 iloveagent57 left a comment

Choose a reason for hiding this comment

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

Looks great, one question about that positive test case.

default_enrollment_intentions_for_customer = models.DefaultEnterpriseEnrollmentIntention.objects.filter(
enterprise_customer=enterprise_customer_uuid,
default_enrollment_intentions_for_customer = (
models.DefaultEnterpriseEnrollmentIntention.available_objects.filter(
Copy link
Contributor

Choose a reason for hiding this comment

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

Breadcrumb for future readers on SoftDeletableModel, TIL!

Note that relying on the default objects manager to filter out not-deleted instances is deprecated. objects will include deleted objects in a future release. Until then, the recommended course of action is to use the manager all_objects when you want to include all instances.
https://django-model-utils.readthedocs.io/en/latest/models.html#softdeletablemodel

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, I think the future change to always need to rely on available_objects was inspired by this issue thread.

Comment on lines +1963 to +1985
if not default_enterprise_enrollment_intention:
LOGGER.info(
"No default enrollment intention found for enterprise course enrollment %s",
enterprise_course_enrollment.id
)
return None

default_enterprise_enrollment_realization, created = (
default_enterprise_enrollment_realization_model().objects.get_or_create(
intended_enrollment=default_enterprise_enrollment_intention,
realized_enrollment=enterprise_course_enrollment,
)
)

if created:
LOGGER.info(
"Created default enterprise enrollment realization for default enrollment "
"intention %s and enterprise course enrollment %s",
default_enterprise_enrollment_intention.uuid,
enterprise_course_enrollment.id
)

return default_enterprise_enrollment_intention, default_enterprise_enrollment_realization
Copy link
Contributor

Choose a reason for hiding this comment

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

chefs kiss

]
},
'fulfillment_source': LicensedEnterpriseCourseEnrollment,
'expected_enrollment_realization_count': 0,
Copy link
Contributor

Choose a reason for hiding this comment

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

Shouldn't this test create a new realization?

Copy link
Member Author

@adamstankiewicz adamstankiewicz Oct 31, 2024

Choose a reason for hiding this comment

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

D'oh, you're correct! This wasn't working properly as I had not added is_default_auto_enrollment to EnrollmentsInfoSerializer, so the field wasn't included during processing, always falling back to is_default_auto_enrollment=False.

Updated/fixed via 24886e1

@adamstankiewicz adamstankiewicz merged commit ad4d01c into master Nov 6, 2024
8 checks passed
@adamstankiewicz adamstankiewicz deleted the ags/ent-9684 branch November 6, 2024 14:55
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.

2 participants