diff --git a/common/djangoapps/student/models.py b/common/djangoapps/student/models.py index cf6c9abbfb..d6f5b35afb 100644 --- a/common/djangoapps/student/models.py +++ b/common/djangoapps/student/models.py @@ -282,6 +282,26 @@ class UserProfile(models.Model): """ return self.profile_image_uploaded_at is not None + @property + def age(self): + """ Convenience method that returns the age given a year_of_birth. """ + year_of_birth = self.year_of_birth + year = datetime.now(UTC).year + if year_of_birth is not None: + return year - year_of_birth + + @property + def level_of_education_display(self): + """ Convenience method that returns the human readable level of education. """ + if self.level_of_education: + return self.__enumerable_to_display(self.LEVEL_OF_EDUCATION_CHOICES, self.level_of_education) + + @property + def gender_display(self): + """ Convenience method that returns the human readable gender. """ + if self.gender: + return self.__enumerable_to_display(self.GENDER_CHOICES, self.gender) + def get_meta(self): # pylint: disable=missing-docstring js_str = self.meta if not js_str: @@ -336,9 +356,17 @@ class UserProfile(models.Model): year_of_birth = self.year_of_birth if year_of_birth is None: return default_requires_consent + if date is None: - date = datetime.now(UTC) - return date.year - year_of_birth <= age_limit + age = self.age + else: + age = date.year - year_of_birth + + return age <= age_limit + + def __enumerable_to_display(self, enumerables, enum_value): + """ Get the human readable value from an enumerable list of key-value pairs. """ + return dict(enumerables)[enum_value] @receiver(pre_save, sender=UserProfile) diff --git a/common/djangoapps/student/tests/test_user_profile_properties.py b/common/djangoapps/student/tests/test_user_profile_properties.py new file mode 100644 index 0000000000..3aac044089 --- /dev/null +++ b/common/djangoapps/student/tests/test_user_profile_properties.py @@ -0,0 +1,79 @@ +"""Unit tests for custom UserProfile properties.""" + +import datetime +import ddt +from django.test import TestCase + +from student.models import UserProfile +from student.tests.factories import UserFactory + + +@ddt.ddt +class UserProfilePropertiesTest(TestCase): + """Unit tests for age, gender_display, and level_of_education_display properties .""" + + password = "test" + + def setUp(self): + super(UserProfilePropertiesTest, self).setUp() + self.user = UserFactory.create(password=self.password) + self.profile = self.user.profile + + def _set_year_of_birth(self, year_of_birth): + """ + Helper method that sets a birth year for the specified user. + """ + self.profile.year_of_birth = year_of_birth + self.profile.save() + + def _set_level_of_education(self, level_of_education): + """ + Helper method that sets a level of education for the specified user. + """ + self.profile.level_of_education = level_of_education + self.profile.save() + + def _set_gender(self, gender): + """ + Helper method that sets a gender for the specified user. + """ + self.profile.gender = gender + self.profile.save() + + @ddt.data(0, 1, 13, 20, 100) + def test_age(self, age): + """Verify the age calculated correctly.""" + current_year = datetime.datetime.now().year + self._set_year_of_birth(current_year - age) + + self.assertEqual(self.profile.age, age) + + def test_age_no_birth_year(self): + """Verify nothing is returned.""" + self.assertIsNone(self.profile.age) + + @ddt.data(*UserProfile.LEVEL_OF_EDUCATION_CHOICES) + @ddt.unpack + def test_display_level_of_education(self, level_enum, display_level): + """Verify the level of education is displayed correctly.""" + self._set_level_of_education(level_enum) + + self.assertEqual(self.profile.level_of_education_display, display_level) + + def test_display_level_of_education_none_set(self): + """Verify nothing is returned.""" + self.assertIsNone(self.profile.level_of_education_display) + + @ddt.data(*UserProfile.GENDER_CHOICES) + @ddt.unpack + def test_display_gender(self, gender_enum, display_gender): + """Verify the gender displayed correctly.""" + self._set_gender(gender_enum) + + self.assertEqual(self.profile.gender_display, display_gender) + + def test_display_gender_none_set(self): + """Verify nothing is returned.""" + self._set_gender(None) + + self.assertIsNone(self.profile.gender_display) diff --git a/common/djangoapps/student/views.py b/common/djangoapps/student/views.py index 0f262df3cc..62aee8270b 100644 --- a/common/djangoapps/student/views.py +++ b/common/djangoapps/student/views.py @@ -1603,10 +1603,28 @@ def create_account_with_params(request, params): # Track the user's registration if settings.FEATURES.get('SEGMENT_IO_LMS') and hasattr(settings, 'SEGMENT_IO_LMS_KEY'): tracking_context = tracker.get_tracker().resolve_context() - analytics.identify(user.id, { - 'email': user.email, - 'username': user.username, - }) + identity_args = [ + user.id, # pylint: disable=no-member + { + 'email': user.email, + 'username': user.username, + 'name': profile.name, + 'age': profile.age, + 'education': profile.level_of_education_display, + 'address': profile.mailing_address, + 'gender': profile.gender_display, + 'country': profile.country, + } + ] + + if hasattr(settings, 'MAILCHIMP_NEW_USER_LIST_ID'): + identity_args.append({ + "MailChimp": { + "listId": settings.MAILCHIMP_NEW_USER_LIST_ID + } + }) + + analytics.identify(*identity_args) analytics.track( user.id, diff --git a/lms/envs/aws.py b/lms/envs/aws.py index 5142fc9d07..11522fd729 100644 --- a/lms/envs/aws.py +++ b/lms/envs/aws.py @@ -470,6 +470,9 @@ ANALYTICS_DATA_TOKEN = AUTH_TOKENS.get("ANALYTICS_DATA_TOKEN", ANALYTICS_DATA_TO ANALYTICS_DASHBOARD_URL = ENV_TOKENS.get("ANALYTICS_DASHBOARD_URL", ANALYTICS_DASHBOARD_URL) ANALYTICS_DASHBOARD_NAME = ENV_TOKENS.get("ANALYTICS_DASHBOARD_NAME", PLATFORM_NAME + " Insights") +# Mailchimp New User List +MAILCHIMP_NEW_USER_LIST_ID = ENV_TOKENS.get("MAILCHIMP_NEW_USER_LIST_ID") + # Zendesk ZENDESK_USER = AUTH_TOKENS.get("ZENDESK_USER") ZENDESK_API_KEY = AUTH_TOKENS.get("ZENDESK_API_KEY")