diff --git a/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+student+registration+demographics+captured+v1_schema.avsc b/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+student+registration+demographics+captured+v1_schema.avsc new file mode 100644 index 00000000..306ae5d3 --- /dev/null +++ b/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+student+registration+demographics+captured+v1_schema.avsc @@ -0,0 +1,63 @@ +{ + "name": "CloudEvent", + "type": "record", + "doc": "Avro Event Format for CloudEvents created with openedx_events/schema", + "fields": [ + { + "name": "demographics", + "type": { + "name": "RegistrationDemographicsData", + "type": "record", + "fields": [ + { + "name": "user", + "type": { + "name": "UserData", + "type": "record", + "fields": [ + { + "name": "id", + "type": "long" + }, + { + "name": "is_active", + "type": "boolean" + }, + { + "name": "pii", + "type": { + "name": "UserPersonalData", + "type": "record", + "fields": [ + { + "name": "username", + "type": "string" + }, + { + "name": "email", + "type": "string" + }, + { + "name": "name", + "type": "string" + } + ] + } + } + ] + } + }, + { + "name": "pronouns", + "type": "string" + }, + { + "name": "department", + "type": "string" + } + ] + } + } + ], + "namespace": "org.openedx.learning.student.registration.demographics.captured.v1" +} \ No newline at end of file diff --git a/openedx_events/learning/data.py b/openedx_events/learning/data.py index a0be3a9e..a4aba806 100644 --- a/openedx_events/learning/data.py +++ b/openedx_events/learning/data.py @@ -693,3 +693,29 @@ class LtiProviderLaunchData: course_key = attr.ib(type=CourseKey) usage_key = attr.ib(type=UsageKey) launch_params = attr.ib(type=LtiProviderLaunchParamsData) + + +@attr.s(frozen=True) +class RegistrationDemographicsData: + """ + Attributes defined for Open edX registration demographics object. + + Fired alongside a successful registration when a deployment has + enabled an authn-form plugin slot that collects optional demographic + information about the learner. + + Both ``pronouns`` and ``department`` default to the empty string so + receivers can be written without ``hasattr`` / ``None`` checks; a + deployment that has not enabled demographics collection simply never + fires the signal at all. + + Arguments: + user (UserData): the just-registered user. + pronouns (str): free-text pronouns string. Empty if not provided. + department (str): department key from the operator-configured + allowlist. Empty if not provided. + """ + + user = attr.ib(type=UserData) + pronouns = attr.ib(type=str, default="") + department = attr.ib(type=str, default="") diff --git a/openedx_events/learning/signals.py b/openedx_events/learning/signals.py index 89bdce85..0b006a3d 100644 --- a/openedx_events/learning/signals.py +++ b/openedx_events/learning/signals.py @@ -25,6 +25,7 @@ ORASubmissionData, PersistentCourseGradeData, ProgramCertificateData, + RegistrationDemographicsData, UserData, UserNotificationData, VerificationAttemptData, @@ -517,3 +518,16 @@ "launch_data": LtiProviderLaunchData, } ) + + +# .. event_type: org.openedx.learning.student.registration.demographics.captured.v1 +# .. event_name: REGISTRATION_DEMOGRAPHICS_CAPTURED +# .. event_description: emitted after STUDENT_REGISTRATION_COMPLETED when an +# authn-form plugin slot has collected optional demographic fields. +# .. event_data: RegistrationDemographicsData +REGISTRATION_DEMOGRAPHICS_CAPTURED = OpenEdxPublicSignal( + event_type="org.openedx.learning.student.registration.demographics.captured.v1", + data={ + "demographics": RegistrationDemographicsData, + } +)