diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 76d6137c..c49ab2c7 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -14,6 +14,14 @@ Change Log Unreleased ---------- +[9.12.0] - 2024-07-31 +--------------------- + +Added +~~~~~~~ + +* Added new enterprise signal ``LEARNER_CREDIT_COURSE_ENROLLMENT_REVOKED``. + [9.11.0] - 2024-05-15 --------------------- diff --git a/openedx_events/__init__.py b/openedx_events/__init__.py index 99ce4e4a..434522ad 100644 --- a/openedx_events/__init__.py +++ b/openedx_events/__init__.py @@ -5,4 +5,4 @@ more information about the project. """ -__version__ = "9.11.0" +__version__ = "9.12.0" diff --git a/openedx_events/enterprise/data.py b/openedx_events/enterprise/data.py index c3b3d1f6..7e9283b6 100644 --- a/openedx_events/enterprise/data.py +++ b/openedx_events/enterprise/data.py @@ -94,3 +94,122 @@ class LedgerTransaction(BaseLedgerTransaction): parent_content_key = attr.ib(type=str, default=None) fulfillment_identifier = attr.ib(type=str, default=None) reversal = attr.ib(type=LedgerTransactionReversal, default=None) + + +@attr.s(frozen=True) +class EnterpriseCustomerUser: + """ + Attributes of an ``enterprise.EnterpriseCustomerUser`` record. + + Django model definition: https://github.com/openedx/edx-enterprise/blob/cc873d6/enterprise/models.py#L1036 + + Arguments: + id (int): Primary identifier of the record. + created (datetime): When the record was created. + modified (datetime): When the record was last modified. + enterprise_customer_uuid (UUID): The enterprise customer to which the user is linked. + user_id (int): The LMS user ID corresponding to this enterprise user. + active (bool): The active enterprise user for the given LMS user. + linked (bool): This enterprise user has been linked to an enterprise customer. + is_relinkable (bool): When set to False, the user cannot be relinked to the enterprise. + invite_key (UUID): Invite key used to link a learner to an enterprise. + should_inactivate_other_customers (bool): When enabled along with `active`, all other linked enterprise + customers for this user will be marked as inactive upon save. + """ + + id = attr.ib(type=int) + created = attr.ib(type=datetime) + modified = attr.ib(type=datetime) + enterprise_customer_uuid = attr.ib(type=UUID) + user_id = attr.ib(type=int) + active = attr.ib(type=bool) + linked = attr.ib(type=bool) + is_relinkable = attr.ib(type=bool) + invite_key = attr.ib(type=UUID) + should_inactivate_other_customers = attr.ib(type=bool) + + +@attr.s(frozen=True) +class EnterpriseCourseEnrollment: + """ + Attributes of an ``enterprise.EnterpriseCourseEnrollment`` record. + + Django model definition: https://github.com/openedx/edx-enterprise/blob/cc873d6/enterprise/models.py#L1983 + + Arguments: + id (int): Primary identifier of the record. + created (datetime): When the record was created. + modified (datetime): When the record was last modified. + enterprise_customer_user (EnterpriseCustomerUser): The enterprise learner to which this enrollment is attached. + course_id (CourseKey): The ID of the course in which the learner was enrolled. + saved_for_later (bool): Specifies whether a user marked this course as saved for later in the learner portal. + source_slug (str): DB slug for the source of the enrollment, e.g. "enrollment_task", "management_command", etc. + unenrolled (bool): Specifies whether the related LMS course enrollment object was unenrolled. + unenrolled_at (datetime): Specifies when the related LMS course enrollment object was unenrolled. + """ + + id = attr.ib(type=int) + created = attr.ib(type=datetime) + modified = attr.ib(type=datetime) + enterprise_customer_user = attr.ib(type=EnterpriseCustomerUser) + course_id = attr.ib(type=CourseKey) + saved_for_later = attr.ib(type=bool) + source_slug = attr.ib(type=str) + unenrolled = attr.ib(type=bool) + unenrolled_at = attr.ib(type=datetime) + + +@attr.s(frozen=True) +class BaseEnterpriseFulfillment: + """ + Defines the common attributes of enterprise fulfillment classes, i.e. ``enterprise.EnterpriseFulfillmentSource``. + + Django model definition: https://github.com/openedx/edx-enterprise/blob/cc873d6/enterprise/models.py#L2213 + + Arguments: + uuid (str): Primary identifier of the record. + created (datetime): When the record was created. + modified (datetime): When the record was last modified. + fulfillment_type (str): Subsidy fulfillment type, typical values: "license", "learner_credit", "coupon_code". + enterprise_course_entitlement_uuid (UUID): The course entitlement the associated subsidy is for. + enterprise_course_enrollment (EnterpriseCourseEnrollment): The course enrollment the associated subsidy is for. + is_revoked (bool): Whether the enterprise subsidy is revoked, e.g., when a user's license is revoked. + """ + + uuid = attr.ib(type=UUID) + created = attr.ib(type=datetime) + modified = attr.ib(type=datetime) + fulfillment_type = attr.ib(type=str) + enterprise_course_entitlement_uuid = attr.ib(type=UUID) + enterprise_course_enrollment = attr.ib(type=EnterpriseCourseEnrollment) + is_revoked = attr.ib(type=bool) + + +@attr.s(frozen=True) +class LearnerCreditEnterpriseCourseEnrollment(BaseEnterpriseFulfillment): + """ + Attributes of an ``enterprise.LearnerCreditEnterpriseCourseEnrollment`` record. + + Django model definition: https://github.com/openedx/edx-enterprise/blob/cc873d6/enterprise/models.py#L2325 + + Arguments: + (All of the same from BaseEnterpriseFulfillment plus the following:) + transaction_id (UUID): Ledgered transaction UUID to associate with this learner credit fulfillment. + """ + + transaction_id = attr.ib(type=UUID) + + +@attr.s(frozen=True) +class LicensedEnterpriseCourseEnrollment(BaseEnterpriseFulfillment): + """ + Attributes of an ``enterprise.LicensedEnterpriseCourseEnrollment`` record. + + Django model definition: https://github.com/openedx/edx-enterprise/blob/cc873d6/enterprise/models.py#L2355 + + Arguments: + (All of the same from BaseEnterpriseFulfillment plus the following:) + license_uuid (UUID): License UUID to associate with this enterprise license fulfillment. + """ + + license_uuid = attr.ib(type=UUID) diff --git a/openedx_events/enterprise/signals.py b/openedx_events/enterprise/signals.py index 50c8a3b7..ee16b910 100644 --- a/openedx_events/enterprise/signals.py +++ b/openedx_events/enterprise/signals.py @@ -8,7 +8,7 @@ docs/decisions/0003-events-payload.rst """ -from openedx_events.enterprise.data import LedgerTransaction, SubsidyRedemption +from openedx_events.enterprise.data import LearnerCreditEnterpriseCourseEnrollment, LedgerTransaction, SubsidyRedemption from openedx_events.tooling import OpenEdxPublicSignal # .. event_type: org.openedx.enterprise.subsidy.redeemed.v1 @@ -84,3 +84,16 @@ "ledger_transaction": LedgerTransaction, } ) + + +# .. event_type: org.openedx.enterprise.learner_credit_course_enrollment.revoked.v1 +# .. event_name: LEARNER_CREDIT_COURSE_ENROLLMENT_REVOKED +# .. event_description: emitted when a LearnerCreditEnterpriseCourseEnrollment is revoked. This most often happens when +# an enterprise learner unenrolls from a course which was LC-subsidized. +# .. event_data: LearnerCreditEnterpriseCourseEnrollment +LEARNER_CREDIT_COURSE_ENROLLMENT_REVOKED = OpenEdxPublicSignal( + event_type="org.openedx.enterprise.learner_credit_course_enrollment.revoked.v1", + data={ + "learner_credit_course_enrollment": LearnerCreditEnterpriseCourseEnrollment, + } +) diff --git a/openedx_events/event_bus/avro/tests/schemas/org+openedx+enterprise+learner_credit_course_enrollment+revoked+v1_schema.avsc b/openedx_events/event_bus/avro/tests/schemas/org+openedx+enterprise+learner_credit_course_enrollment+revoked+v1_schema.avsc new file mode 100644 index 00000000..75fb19ef --- /dev/null +++ b/openedx_events/event_bus/avro/tests/schemas/org+openedx+enterprise+learner_credit_course_enrollment+revoked+v1_schema.avsc @@ -0,0 +1,135 @@ +{ + "name": "CloudEvent", + "type": "record", + "doc": "Avro Event Format for CloudEvents created with openedx_events/schema", + "fields": [ + { + "name": "learner_credit_course_enrollment", + "type": { + "name": "LearnerCreditEnterpriseCourseEnrollment", + "type": "record", + "fields": [ + { + "name": "uuid", + "type": "string" + }, + { + "name": "created", + "type": "string" + }, + { + "name": "modified", + "type": "string" + }, + { + "name": "fulfillment_type", + "type": "string" + }, + { + "name": "enterprise_course_entitlement_uuid", + "type": "string" + }, + { + "name": "enterprise_course_enrollment", + "type": { + "name": "EnterpriseCourseEnrollment", + "type": "record", + "fields": [ + { + "name": "id", + "type": "long" + }, + { + "name": "created", + "type": "string" + }, + { + "name": "modified", + "type": "string" + }, + { + "name": "enterprise_customer_user", + "type": { + "name": "EnterpriseCustomerUser", + "type": "record", + "fields": [ + { + "name": "id", + "type": "long" + }, + { + "name": "created", + "type": "string" + }, + { + "name": "modified", + "type": "string" + }, + { + "name": "enterprise_customer_uuid", + "type": "string" + }, + { + "name": "user_id", + "type": "long" + }, + { + "name": "active", + "type": "boolean" + }, + { + "name": "linked", + "type": "boolean" + }, + { + "name": "is_relinkable", + "type": "boolean" + }, + { + "name": "invite_key", + "type": "string" + }, + { + "name": "should_inactivate_other_customers", + "type": "boolean" + } + ] + } + }, + { + "name": "course_id", + "type": "string" + }, + { + "name": "saved_for_later", + "type": "boolean" + }, + { + "name": "source_slug", + "type": "string" + }, + { + "name": "unenrolled", + "type": "boolean" + }, + { + "name": "unenrolled_at", + "type": "string" + } + ] + } + }, + { + "name": "is_revoked", + "type": "boolean" + }, + { + "name": "transaction_id", + "type": "string" + } + ] + } + } + ], + "namespace": "org.openedx.enterprise.learner_credit_course_enrollment.revoked.v1" +} \ No newline at end of file