From 5c8100a2fa5eed262f1978c1838d11ee8eaf2be4 Mon Sep 17 00:00:00 2001 From: Bryann Valderrama Date: Wed, 4 Dec 2024 16:34:30 -0500 Subject: [PATCH 01/25] chore: upgrade requirements based on redwood --- requirements/base.txt | 12 ++++++------ requirements/constraints.txt | 2 +- requirements/django.txt | 2 +- requirements/test.txt | 10 +++++----- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/requirements/base.txt b/requirements/base.txt index d0320b2..0ffde05 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -4,19 +4,19 @@ # # make upgrade # -amqp==2.6.1 # via kombu -billiard==3.6.4.0 # via celery -celery==4.4.7 # via -c requirements/constraints.txt, -r requirements/base.in +amqp==5.2.0 # via kombu +billiard==4.2.0 # via celery +celery==5.4.0 # via -c requirements/constraints.txt, -r requirements/base.in django==2.2.25 # via -c requirements/constraints.txt, edx-opaque-keys, openedx-filters edx-opaque-keys[django]==2.2.0 # via -c requirements/constraints.txt, -r requirements/base.in -kombu==4.6.11 # via celery +kombu==5.3.4 # via celery openedx-filters==1.8.1 # via -c requirements/constraints.txt, -r requirements/base.in -openedx-events==9.10.0 +openedx-events==9.15.0 pbr==5.10.0 # via stevedore pymongo==4.2.0 # via edx-opaque-keys pytz==2022.2.1 # via celery, django six==1.16.0 # via -r requirements/base.in sqlparse==0.4.2 # via django stevedore==4.0.0 # via edx-opaque-keys -vine==1.3.0 # via amqp, celery +vine==5.1.0 # via amqp, celery web-fragments==2.0.0 # via -r requirements/base.in diff --git a/requirements/constraints.txt b/requirements/constraints.txt index 628d734..f646a7b 100644 --- a/requirements/constraints.txt +++ b/requirements/constraints.txt @@ -3,6 +3,6 @@ celery<5.0 Django==2.2.25 edx-opaque-keys[django]==2.2.0 openedx-filters==1.8.1 -openedx-events==9.10.0 +openedx-events==9.15.0 pip-tools<5.4 click==7.1.2 diff --git a/requirements/django.txt b/requirements/django.txt index f6c201b..652a7c2 100644 --- a/requirements/django.txt +++ b/requirements/django.txt @@ -1,2 +1,2 @@ -celery==4.4.7 # via -c requirements/constraints.txt, -r requirements/base.txt +celery==5.4.0 # via -c requirements/constraints.txt, -r requirements/base.txt django==2.2.25 # via -c requirements/constraints.txt, -r requirements/base.txt, edx-opaque-keys, openedx-filters diff --git a/requirements/test.txt b/requirements/test.txt index 258393d..7b4e875 100644 --- a/requirements/test.txt +++ b/requirements/test.txt @@ -4,10 +4,10 @@ # # make upgrade # -amqp==2.6.1 # via -r requirements/base.txt, kombu +amqp==5.2.0 # via -r requirements/base.txt, kombu astroid==2.12.9 # via pylint, pylint-celery attrs==22.1.0 # via pytest -billiard==3.6.4.0 # via -r requirements/base.txt, celery +billiard==4.2.0 # via -r requirements/base.txt, celery click-log==0.4.0 # via edx-lint click==7.1.2 # via -c requirements/constraints.txt, click-log, code-annotations, edx-lint code-annotations==1.3.0 # via edx-lint @@ -18,12 +18,12 @@ edx-opaque-keys[django]==2.2.0 # via -c requirements/constraints.txt, -r requir iniconfig==1.1.1 # via pytest isort==5.10.1 # via pylint jinja2==3.1.2 # via code-annotations -kombu==4.6.11 # via -r requirements/base.txt, celery +kombu==5.3.4 # via -r requirements/base.txt, celery lazy-object-proxy==1.7.1 # via astroid markupsafe==2.1.1 # via jinja2 mccabe==0.7.0 # via pylint openedx-filters==1.8.1 # via -c requirements/constraints.txt, -r requirements/base.txt -openedx-events==9.10.0 +openedx-events==9.15.0 packaging==21.3 # via pytest pbr==5.10.0 # via -r requirements/base.txt, stevedore platformdirs==2.5.2 # via pylint @@ -47,6 +47,6 @@ text-unidecode==1.3 # via python-slugify tomli==2.0.1 # via pylint, pytest tomlkit==0.11.4 # via pylint typing-extensions==4.3.0 # via astroid, pylint -vine==1.3.0 # via -r requirements/base.txt, amqp, celery +vine==5.1.0 # via -r requirements/base.txt, amqp, celery web-fragments==2.0.0 # via -r requirements/base.txt wrapt==1.14.1 # via astroid From 4d2dea1dec92a8c8953d24f627321ae81b9f70ea Mon Sep 17 00:00:00 2001 From: Bryann Valderrama Date: Wed, 4 Dec 2024 16:35:01 -0500 Subject: [PATCH 02/25] feat: create filter definition for schedule nudge emails --- nau_openedx_extensions/filters/definition.py | 38 ++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 nau_openedx_extensions/filters/definition.py diff --git a/nau_openedx_extensions/filters/definition.py b/nau_openedx_extensions/filters/definition.py new file mode 100644 index 0000000..38dcef6 --- /dev/null +++ b/nau_openedx_extensions/filters/definition.py @@ -0,0 +1,38 @@ +"""Filters definition module.""" + +from openedx_filters.exceptions import OpenEdxFilterException +from openedx_filters.tooling import OpenEdxPublicFilter + + +class ScheduleNudgeEmailStarted(OpenEdxPublicFilter): + """ + Custom class used to create schedule email filters and its custom methods. + """ + + filter_type = "org.openedx.learning.schedule.nudge.email.started.v1" + + class InvalidSchedule(OpenEdxFilterException): + """ + Custom class used to stop the submission view render process. + """ + + def __init__(self, message: str, schedules): + """ + Override init that defines specific arguments used in the submission view render process. + + Arguments: + message (str): error message for the exception. + schedules (QuerySet): schedules to be sent. + """ + super().__init__(message, schedules=schedules) + + @classmethod + def run_filter(cls, schedules): + """ + Execute a filter with the signature specified. + + Arguments: + schedules (QuerySet): Queryset of schedules to be sent. + """ + data = super().run_pipeline(schedules=schedules) + return data.get("schedules") From e196ae767b9e4879d01abb0483583781163b9dd4 Mon Sep 17 00:00:00 2001 From: Bryann Valderrama Date: Wed, 4 Dec 2024 16:35:25 -0500 Subject: [PATCH 03/25] feat: add pipeline for new filter --- nau_openedx_extensions/filters/pipeline.py | 34 ++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/nau_openedx_extensions/filters/pipeline.py b/nau_openedx_extensions/filters/pipeline.py index 99dfd60..1d3ecfd 100644 --- a/nau_openedx_extensions/filters/pipeline.py +++ b/nau_openedx_extensions/filters/pipeline.py @@ -77,3 +77,37 @@ def _is_user_email_allowed(user, domains_allowed): if user_domain == domain or fnmatch(user_domain, f"*.{domain}"): return True return False + + +class FilterUsersWithAllowedNewsletter(PipelineStep): + """ + Filter users with allowed newsletter. + + Example usage: + + Add the following configurations to your configuration file: + + OPEN_EDX_FILTERS_CONFIG = { + "org.openedx.learning.schedule.nudge.email.started.v1": { + "fail_silently": False, + "pipeline": [ + "nau_openedx_extensions.filters.pipeline.FilterUsersWithAllowedNewsletter", + ], + }, + } + """ + + def run_filter(self, schedules) -> dict: # pylint: disable=arguments-differ + """ + Execute filter that filters users with allowed newsletter. + + Arguments: + schedules (QuerySet): Queryset of schedules to be sent. + + Returns: + dict: Dictionary with the filtered schedules. + """ + schedules = schedules.filter(enrollment__user__nauuserextendedmodel__allow_newsletter=True) + return { + "schedules": schedules, + } From d91a2ff6d2a605e819e7345ac3cc1b657ab0d34a Mon Sep 17 00:00:00 2001 From: Bryann Valderrama Date: Thu, 5 Dec 2024 11:30:07 -0500 Subject: [PATCH 04/25] refactor: update filter definition --- nau_openedx_extensions/filters/definition.py | 24 +++++++------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/nau_openedx_extensions/filters/definition.py b/nau_openedx_extensions/filters/definition.py index 38dcef6..6cff178 100644 --- a/nau_openedx_extensions/filters/definition.py +++ b/nau_openedx_extensions/filters/definition.py @@ -3,31 +3,23 @@ from openedx_filters.exceptions import OpenEdxFilterException from openedx_filters.tooling import OpenEdxPublicFilter +from django.db.models.query import QuerySet -class ScheduleNudgeEmailStarted(OpenEdxPublicFilter): + +class ScheduleQuerysetRequested(OpenEdxPublicFilter): """ - Custom class used to create schedule email filters and its custom methods. + Custom class used to create schedule queryset filters filters and its custom methods. """ - filter_type = "org.openedx.learning.schedule.nudge.email.started.v1" + filter_type = "org.openedx.learning.schedule.queryset.requested.v1" - class InvalidSchedule(OpenEdxFilterException): + class PreventScheduleQuerysetRequest(OpenEdxFilterException): """ - Custom class used to stop the submission view render process. + Custom class used to stop the schedule queryset request process. """ - def __init__(self, message: str, schedules): - """ - Override init that defines specific arguments used in the submission view render process. - - Arguments: - message (str): error message for the exception. - schedules (QuerySet): schedules to be sent. - """ - super().__init__(message, schedules=schedules) - @classmethod - def run_filter(cls, schedules): + def run_filter(cls, schedules: QuerySet) -> QuerySet: """ Execute a filter with the signature specified. From cabfa5627be48b60085b7bdac7d8ef8b21c65fc8 Mon Sep 17 00:00:00 2001 From: Bryann Valderrama Date: Thu, 5 Dec 2024 12:51:32 -0500 Subject: [PATCH 05/25] feat: add init method in filter exception class --- nau_openedx_extensions/filters/definition.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/nau_openedx_extensions/filters/definition.py b/nau_openedx_extensions/filters/definition.py index 6cff178..232d254 100644 --- a/nau_openedx_extensions/filters/definition.py +++ b/nau_openedx_extensions/filters/definition.py @@ -6,7 +6,7 @@ from django.db.models.query import QuerySet -class ScheduleQuerysetRequested(OpenEdxPublicFilter): +class ScheduleQuerySetRequested(OpenEdxPublicFilter): """ Custom class used to create schedule queryset filters filters and its custom methods. """ @@ -18,6 +18,16 @@ class PreventScheduleQuerysetRequest(OpenEdxFilterException): Custom class used to stop the schedule queryset request process. """ + def __init__(self, message: str, schedules: QuerySet): + """ + Override init that defines specific arguments used in the schedule queryset request process. + + Arguments: + message (str): error message for the exception. + schedules (QuerySet): Queryset of schedules to be sent + """ + super().__init__(message, schedules=schedules) + @classmethod def run_filter(cls, schedules: QuerySet) -> QuerySet: """ From 7c89909827791cf4bf3577824a371ef409853c81 Mon Sep 17 00:00:00 2001 From: Bryann Valderrama Date: Thu, 5 Dec 2024 12:52:06 -0500 Subject: [PATCH 06/25] feat: update pipeline for raise exception --- nau_openedx_extensions/filters/pipeline.py | 27 +++++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/nau_openedx_extensions/filters/pipeline.py b/nau_openedx_extensions/filters/pipeline.py index 1d3ecfd..a60b54c 100644 --- a/nau_openedx_extensions/filters/pipeline.py +++ b/nau_openedx_extensions/filters/pipeline.py @@ -5,6 +5,7 @@ from fnmatch import fnmatch from django.conf import settings +from django.db.models.query import QuerySet from django.utils.translation import gettext as _ from openedx_filters import PipelineStep from openedx_filters.learning.filters import CourseEnrollmentStarted @@ -12,6 +13,7 @@ from nau_openedx_extensions.edxapp_wrapper import site_configuration_helpers as configuration_helpers from nau_openedx_extensions.edxapp_wrapper.course_module import get_other_course_settings from nau_openedx_extensions.edxapp_wrapper.student import get_student_course_enrollment_allowed +from nau_openedx_extensions.filters.definition import ScheduleQuerySetRequested class FilterEnrollmentByDomain(PipelineStep): # pylint: disable=too-few-public-methods @@ -87,27 +89,40 @@ class FilterUsersWithAllowedNewsletter(PipelineStep): Add the following configurations to your configuration file: + ``` OPEN_EDX_FILTERS_CONFIG = { - "org.openedx.learning.schedule.nudge.email.started.v1": { + "org.openedx.learning.schedule.queryset.requested.v1": { "fail_silently": False, "pipeline": [ "nau_openedx_extensions.filters.pipeline.FilterUsersWithAllowedNewsletter", ], }, } + ``` """ - def run_filter(self, schedules) -> dict: # pylint: disable=arguments-differ + def run_filter(self, schedules: QuerySet) -> dict: """ Execute filter that filters users with allowed newsletter. Arguments: schedules (QuerySet): Queryset of schedules to be sent. + Raises: + PreventScheduleQuerysetRequest: If the filter can't be applied. + Returns: dict: Dictionary with the filtered schedules. """ - schedules = schedules.filter(enrollment__user__nauuserextendedmodel__allow_newsletter=True) - return { - "schedules": schedules, - } + try: + filtered_schedules = schedules.filter( + enrollment__user__nauuserextendedmodel__allow_newsletter=True, + ) + return { + "schedules": filtered_schedules, + } + except AttributeError: + raise ScheduleQuerySetRequested.PreventScheduleQuerysetRequest( + "The filter can't be applied because the user model " + "doesn't have the attribute 'nauuserextendedmodel'." + ) From 7a3ff6448ac186b09231b09b80ea059171de9d3c Mon Sep 17 00:00:00 2001 From: Bryann Valderrama Date: Thu, 5 Dec 2024 16:13:12 -0500 Subject: [PATCH 07/25] chore: add allow_newsletter field as a visible field in account settings --- nau_openedx_extensions/settings/common.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nau_openedx_extensions/settings/common.py b/nau_openedx_extensions/settings/common.py index 36e4995..02c7890 100644 --- a/nau_openedx_extensions/settings/common.py +++ b/nau_openedx_extensions/settings/common.py @@ -77,7 +77,7 @@ def plugin_settings(settings): settings.NAU_COURSE_MESSAGE_BATCH_SIZE = 50 settings.NAU_COURSE_MESSAGE_RECIPIENT_FIELDS = ["profile__name", "email"] settings.NAU_CC_ALLOWED_SLUG = "cccmd:" - settings.NAU_ACCOUNTS_CC_VISIBLE_FIELDS = ["employment_situation", "nif"] + settings.NAU_ACCOUNTS_CC_VISIBLE_FIELDS = ["employment_situation", "nif", "allow_newsletter"] settings.SCORMXBLOCK_ASYNC_THRESHOLD = 500 settings.NAU_SITE_CONFIGURATION_HELPERS_MODULE = ( "nau_openedx_extensions.edxapp_wrapper.backends.site_configuration_helpers_l_v1" From d48cb3bee16ea3be8bcc37548a5691f7b0f9b1c3 Mon Sep 17 00:00:00 2001 From: Bryann Valderrama Date: Thu, 5 Dec 2024 17:12:35 -0500 Subject: [PATCH 08/25] chore: allow show boolean fields in account fields --- .../custom_registration_form/context_extender.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nau_openedx_extensions/custom_registration_form/context_extender.py b/nau_openedx_extensions/custom_registration_form/context_extender.py index 5b61005..6b9fdbf 100644 --- a/nau_openedx_extensions/custom_registration_form/context_extender.py +++ b/nau_openedx_extensions/custom_registration_form/context_extender.py @@ -27,7 +27,7 @@ def get_fields(custom_model_instance): for field in custom_fields: if field.name not in allowed_fields: continue - if isinstance(field, (models.CharField, models.TextField)): + if isinstance(field, (models.CharField, models.TextField, models.BooleanField)): yield field From cc358fb68c895bf3d7f1b3c7306db1919d37f199 Mon Sep 17 00:00:00 2001 From: Bryann Valderrama Date: Fri, 6 Dec 2024 18:23:57 -0500 Subject: [PATCH 09/25] refactor: use FieldError instead AttributeError --- nau_openedx_extensions/filters/pipeline.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/nau_openedx_extensions/filters/pipeline.py b/nau_openedx_extensions/filters/pipeline.py index a60b54c..d4b584e 100644 --- a/nau_openedx_extensions/filters/pipeline.py +++ b/nau_openedx_extensions/filters/pipeline.py @@ -5,6 +5,7 @@ from fnmatch import fnmatch from django.conf import settings +from django.core.exceptions import FieldError from django.db.models.query import QuerySet from django.utils.translation import gettext as _ from openedx_filters import PipelineStep @@ -121,8 +122,9 @@ def run_filter(self, schedules: QuerySet) -> dict: return { "schedules": filtered_schedules, } - except AttributeError: + except FieldError: raise ScheduleQuerySetRequested.PreventScheduleQuerysetRequest( "The filter can't be applied because the user model " - "doesn't have the attribute 'nauuserextendedmodel'." + "doesn't have the attribute 'nauuserextendedmodel'.", + schedules, ) From 17627439e3d28e254da8231cd8715b97022698ac Mon Sep 17 00:00:00 2001 From: Bryann Valderrama Date: Mon, 9 Dec 2024 12:04:47 -0500 Subject: [PATCH 10/25] chore: update filter definition --- nau_openedx_extensions/filters/definition.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/nau_openedx_extensions/filters/definition.py b/nau_openedx_extensions/filters/definition.py index 232d254..96ed8bf 100644 --- a/nau_openedx_extensions/filters/definition.py +++ b/nau_openedx_extensions/filters/definition.py @@ -13,7 +13,7 @@ class ScheduleQuerySetRequested(OpenEdxPublicFilter): filter_type = "org.openedx.learning.schedule.queryset.requested.v1" - class PreventScheduleQuerysetRequest(OpenEdxFilterException): + class PreventScheduleQuerySetRequest(OpenEdxFilterException): """ Custom class used to stop the schedule queryset request process. """ @@ -35,6 +35,9 @@ def run_filter(cls, schedules: QuerySet) -> QuerySet: Arguments: schedules (QuerySet): Queryset of schedules to be sent. + + Returns: + QuerySet: Schedules to be sent. """ data = super().run_pipeline(schedules=schedules) return data.get("schedules") From 8a4d8bcb309066d8bff80a95a5a0577798e49d8f Mon Sep 17 00:00:00 2001 From: Bryann Valderrama Date: Mon, 9 Dec 2024 12:55:55 -0500 Subject: [PATCH 11/25] chore: use latest versions of openedx-filters and openedx-events --- requirements/base.in | 4 ++-- requirements/base.txt | 2 +- requirements/constraints.txt | 2 +- requirements/test.txt | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/requirements/base.in b/requirements/base.in index b1fbc13..ff9fd73 100644 --- a/requirements/base.in +++ b/requirements/base.in @@ -4,5 +4,5 @@ edx-opaque-keys[django] six future; python_version < "3.0" web-fragments -openedx-filters==1.8.1 -openedx-events==9.10.0 +openedx-filters==1.11.0 +openedx-events==9.15.0 diff --git a/requirements/base.txt b/requirements/base.txt index 0ffde05..c3e2122 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -10,7 +10,7 @@ celery==5.4.0 # via -c requirements/constraints.txt, -r requirements django==2.2.25 # via -c requirements/constraints.txt, edx-opaque-keys, openedx-filters edx-opaque-keys[django]==2.2.0 # via -c requirements/constraints.txt, -r requirements/base.in kombu==5.3.4 # via celery -openedx-filters==1.8.1 # via -c requirements/constraints.txt, -r requirements/base.in +openedx-filters==1.11.0 # via -c requirements/constraints.txt, -r requirements/base.in openedx-events==9.15.0 pbr==5.10.0 # via stevedore pymongo==4.2.0 # via edx-opaque-keys diff --git a/requirements/constraints.txt b/requirements/constraints.txt index f646a7b..5d63172 100644 --- a/requirements/constraints.txt +++ b/requirements/constraints.txt @@ -2,7 +2,7 @@ celery<5.0 Django==2.2.25 edx-opaque-keys[django]==2.2.0 -openedx-filters==1.8.1 +openedx-filters==1.11.0 openedx-events==9.15.0 pip-tools<5.4 click==7.1.2 diff --git a/requirements/test.txt b/requirements/test.txt index 7b4e875..2cf5868 100644 --- a/requirements/test.txt +++ b/requirements/test.txt @@ -22,7 +22,7 @@ kombu==5.3.4 # via -r requirements/base.txt, celery lazy-object-proxy==1.7.1 # via astroid markupsafe==2.1.1 # via jinja2 mccabe==0.7.0 # via pylint -openedx-filters==1.8.1 # via -c requirements/constraints.txt, -r requirements/base.txt +openedx-filters==1.11.0 # via -c requirements/constraints.txt, -r requirements/base.txt openedx-events==9.15.0 packaging==21.3 # via pytest pbr==5.10.0 # via -r requirements/base.txt, stevedore From 1aef6f03422dd634ee2c5b6a4d30f26766248236 Mon Sep 17 00:00:00 2001 From: Bryann Valderrama Date: Mon, 9 Dec 2024 13:14:24 -0500 Subject: [PATCH 12/25] fix: solve pylint errors --- nau_openedx_extensions/filters/definition.py | 3 +-- nau_openedx_extensions/filters/pipeline.py | 8 ++++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/nau_openedx_extensions/filters/definition.py b/nau_openedx_extensions/filters/definition.py index 96ed8bf..cb850f8 100644 --- a/nau_openedx_extensions/filters/definition.py +++ b/nau_openedx_extensions/filters/definition.py @@ -1,10 +1,9 @@ """Filters definition module.""" +from django.db.models.query import QuerySet from openedx_filters.exceptions import OpenEdxFilterException from openedx_filters.tooling import OpenEdxPublicFilter -from django.db.models.query import QuerySet - class ScheduleQuerySetRequested(OpenEdxPublicFilter): """ diff --git a/nau_openedx_extensions/filters/pipeline.py b/nau_openedx_extensions/filters/pipeline.py index d4b584e..850c455 100644 --- a/nau_openedx_extensions/filters/pipeline.py +++ b/nau_openedx_extensions/filters/pipeline.py @@ -102,7 +102,7 @@ class FilterUsersWithAllowedNewsletter(PipelineStep): ``` """ - def run_filter(self, schedules: QuerySet) -> dict: + def run_filter(self, schedules: QuerySet) -> dict: # pylint: disable=arguments-differ """ Execute filter that filters users with allowed newsletter. @@ -122,9 +122,9 @@ def run_filter(self, schedules: QuerySet) -> dict: return { "schedules": filtered_schedules, } - except FieldError: - raise ScheduleQuerySetRequested.PreventScheduleQuerysetRequest( + except FieldError as exc: + raise ScheduleQuerySetRequested.PreventScheduleQuerySetRequest( "The filter can't be applied because the user model " "doesn't have the attribute 'nauuserextendedmodel'.", schedules, - ) + ) from exc From 02e352dbcce8263129caa8a3d88ed2681f26b3c1 Mon Sep 17 00:00:00 2001 From: Bryann Valderrama Date: Mon, 9 Dec 2024 17:23:27 -0500 Subject: [PATCH 13/25] chore: remove changes of allow_newsletter field --- .../custom_registration_form/context_extender.py | 2 +- nau_openedx_extensions/settings/common.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/nau_openedx_extensions/custom_registration_form/context_extender.py b/nau_openedx_extensions/custom_registration_form/context_extender.py index 6b9fdbf..5b61005 100644 --- a/nau_openedx_extensions/custom_registration_form/context_extender.py +++ b/nau_openedx_extensions/custom_registration_form/context_extender.py @@ -27,7 +27,7 @@ def get_fields(custom_model_instance): for field in custom_fields: if field.name not in allowed_fields: continue - if isinstance(field, (models.CharField, models.TextField, models.BooleanField)): + if isinstance(field, (models.CharField, models.TextField)): yield field diff --git a/nau_openedx_extensions/settings/common.py b/nau_openedx_extensions/settings/common.py index 02c7890..36e4995 100644 --- a/nau_openedx_extensions/settings/common.py +++ b/nau_openedx_extensions/settings/common.py @@ -77,7 +77,7 @@ def plugin_settings(settings): settings.NAU_COURSE_MESSAGE_BATCH_SIZE = 50 settings.NAU_COURSE_MESSAGE_RECIPIENT_FIELDS = ["profile__name", "email"] settings.NAU_CC_ALLOWED_SLUG = "cccmd:" - settings.NAU_ACCOUNTS_CC_VISIBLE_FIELDS = ["employment_situation", "nif", "allow_newsletter"] + settings.NAU_ACCOUNTS_CC_VISIBLE_FIELDS = ["employment_situation", "nif"] settings.SCORMXBLOCK_ASYNC_THRESHOLD = 500 settings.NAU_SITE_CONFIGURATION_HELPERS_MODULE = ( "nau_openedx_extensions.edxapp_wrapper.backends.site_configuration_helpers_l_v1" From a9b038605ddccfd2d6e8cd7f65686b6c8841f081 Mon Sep 17 00:00:00 2001 From: Bryann Valderrama Date: Thu, 12 Dec 2024 07:31:12 -0500 Subject: [PATCH 14/25] chore: remove filter definition --- nau_openedx_extensions/filters/definition.py | 42 -------------------- nau_openedx_extensions/filters/pipeline.py | 3 +- 2 files changed, 1 insertion(+), 44 deletions(-) delete mode 100644 nau_openedx_extensions/filters/definition.py diff --git a/nau_openedx_extensions/filters/definition.py b/nau_openedx_extensions/filters/definition.py deleted file mode 100644 index cb850f8..0000000 --- a/nau_openedx_extensions/filters/definition.py +++ /dev/null @@ -1,42 +0,0 @@ -"""Filters definition module.""" - -from django.db.models.query import QuerySet -from openedx_filters.exceptions import OpenEdxFilterException -from openedx_filters.tooling import OpenEdxPublicFilter - - -class ScheduleQuerySetRequested(OpenEdxPublicFilter): - """ - Custom class used to create schedule queryset filters filters and its custom methods. - """ - - filter_type = "org.openedx.learning.schedule.queryset.requested.v1" - - class PreventScheduleQuerySetRequest(OpenEdxFilterException): - """ - Custom class used to stop the schedule queryset request process. - """ - - def __init__(self, message: str, schedules: QuerySet): - """ - Override init that defines specific arguments used in the schedule queryset request process. - - Arguments: - message (str): error message for the exception. - schedules (QuerySet): Queryset of schedules to be sent - """ - super().__init__(message, schedules=schedules) - - @classmethod - def run_filter(cls, schedules: QuerySet) -> QuerySet: - """ - Execute a filter with the signature specified. - - Arguments: - schedules (QuerySet): Queryset of schedules to be sent. - - Returns: - QuerySet: Schedules to be sent. - """ - data = super().run_pipeline(schedules=schedules) - return data.get("schedules") diff --git a/nau_openedx_extensions/filters/pipeline.py b/nau_openedx_extensions/filters/pipeline.py index 850c455..6b695bc 100644 --- a/nau_openedx_extensions/filters/pipeline.py +++ b/nau_openedx_extensions/filters/pipeline.py @@ -9,12 +9,11 @@ from django.db.models.query import QuerySet from django.utils.translation import gettext as _ from openedx_filters import PipelineStep -from openedx_filters.learning.filters import CourseEnrollmentStarted +from openedx_filters.learning.filters import CourseEnrollmentStarted, ScheduleQuerySetRequested from nau_openedx_extensions.edxapp_wrapper import site_configuration_helpers as configuration_helpers from nau_openedx_extensions.edxapp_wrapper.course_module import get_other_course_settings from nau_openedx_extensions.edxapp_wrapper.student import get_student_course_enrollment_allowed -from nau_openedx_extensions.filters.definition import ScheduleQuerySetRequested class FilterEnrollmentByDomain(PipelineStep): # pylint: disable=too-few-public-methods From e8b293442782d6a37b2c2c9e810d12d69ab65e42 Mon Sep 17 00:00:00 2001 From: Bryann Valderrama Date: Thu, 12 Dec 2024 09:35:51 -0500 Subject: [PATCH 15/25] chore: remove try-except when running the filter --- nau_openedx_extensions/filters/pipeline.py | 25 ++++++---------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/nau_openedx_extensions/filters/pipeline.py b/nau_openedx_extensions/filters/pipeline.py index 6b695bc..a06f1f9 100644 --- a/nau_openedx_extensions/filters/pipeline.py +++ b/nau_openedx_extensions/filters/pipeline.py @@ -5,11 +5,10 @@ from fnmatch import fnmatch from django.conf import settings -from django.core.exceptions import FieldError from django.db.models.query import QuerySet from django.utils.translation import gettext as _ from openedx_filters import PipelineStep -from openedx_filters.learning.filters import CourseEnrollmentStarted, ScheduleQuerySetRequested +from openedx_filters.learning.filters import CourseEnrollmentStarted from nau_openedx_extensions.edxapp_wrapper import site_configuration_helpers as configuration_helpers from nau_openedx_extensions.edxapp_wrapper.course_module import get_other_course_settings @@ -83,7 +82,10 @@ def _is_user_email_allowed(user, domains_allowed): class FilterUsersWithAllowedNewsletter(PipelineStep): """ - Filter users with allowed newsletter. + Filter the Schedules QuerySet to only keep those whose associated user has + the `allow_newsletter` field set to `True`. If the user does not have the + `allow_newsletter` field set to `True`, or if the field does not exist, the + Schedule will be filtered out. Example usage: @@ -108,22 +110,7 @@ def run_filter(self, schedules: QuerySet) -> dict: # pylint: disable=arguments- Arguments: schedules (QuerySet): Queryset of schedules to be sent. - Raises: - PreventScheduleQuerysetRequest: If the filter can't be applied. - Returns: dict: Dictionary with the filtered schedules. """ - try: - filtered_schedules = schedules.filter( - enrollment__user__nauuserextendedmodel__allow_newsletter=True, - ) - return { - "schedules": filtered_schedules, - } - except FieldError as exc: - raise ScheduleQuerySetRequested.PreventScheduleQuerySetRequest( - "The filter can't be applied because the user model " - "doesn't have the attribute 'nauuserextendedmodel'.", - schedules, - ) from exc + return {"schedules": schedules.filter(enrollment__user__nauuserextendedmodel__allow_newsletter=True)} From d10bb12d95c48fc1a8ffeb46f760fdc7a1e840ee Mon Sep 17 00:00:00 2001 From: Bryann Valderrama Date: Thu, 12 Dec 2024 09:39:28 -0500 Subject: [PATCH 16/25] chore: upgrade openedx-filters to v1.12.0 --- requirements/base.in | 2 +- requirements/base.txt | 2 +- requirements/constraints.txt | 2 +- requirements/test.txt | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/requirements/base.in b/requirements/base.in index ff9fd73..96505e1 100644 --- a/requirements/base.in +++ b/requirements/base.in @@ -4,5 +4,5 @@ edx-opaque-keys[django] six future; python_version < "3.0" web-fragments -openedx-filters==1.11.0 +openedx-filters==1.12.0 openedx-events==9.15.0 diff --git a/requirements/base.txt b/requirements/base.txt index c3e2122..67e7649 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -10,7 +10,7 @@ celery==5.4.0 # via -c requirements/constraints.txt, -r requirements django==2.2.25 # via -c requirements/constraints.txt, edx-opaque-keys, openedx-filters edx-opaque-keys[django]==2.2.0 # via -c requirements/constraints.txt, -r requirements/base.in kombu==5.3.4 # via celery -openedx-filters==1.11.0 # via -c requirements/constraints.txt, -r requirements/base.in +openedx-filters==1.12.0 # via -c requirements/constraints.txt, -r requirements/base.in openedx-events==9.15.0 pbr==5.10.0 # via stevedore pymongo==4.2.0 # via edx-opaque-keys diff --git a/requirements/constraints.txt b/requirements/constraints.txt index 5d63172..22c2b03 100644 --- a/requirements/constraints.txt +++ b/requirements/constraints.txt @@ -2,7 +2,7 @@ celery<5.0 Django==2.2.25 edx-opaque-keys[django]==2.2.0 -openedx-filters==1.11.0 +openedx-filters==1.12.0 openedx-events==9.15.0 pip-tools<5.4 click==7.1.2 diff --git a/requirements/test.txt b/requirements/test.txt index 2cf5868..a7de424 100644 --- a/requirements/test.txt +++ b/requirements/test.txt @@ -22,7 +22,7 @@ kombu==5.3.4 # via -r requirements/base.txt, celery lazy-object-proxy==1.7.1 # via astroid markupsafe==2.1.1 # via jinja2 mccabe==0.7.0 # via pylint -openedx-filters==1.11.0 # via -c requirements/constraints.txt, -r requirements/base.txt +openedx-filters==1.12.0 # via -c requirements/constraints.txt, -r requirements/base.txt openedx-events==9.15.0 packaging==21.3 # via pytest pbr==5.10.0 # via -r requirements/base.txt, stevedore From ec6cff90bf37c121069eff0bccecb264da81fc05 Mon Sep 17 00:00:00 2001 From: Bryann Valderrama Date: Thu, 12 Dec 2024 12:59:16 -0500 Subject: [PATCH 17/25] chore: update translations --- .../locale/en/LC_MESSAGES/django.mo | Bin 784 -> 784 bytes .../locale/en/LC_MESSAGES/django.po | 8 ++++---- .../locale/pt_PT/LC_MESSAGES/django.mo | Bin 2456 -> 2456 bytes .../locale/pt_PT/LC_MESSAGES/django.po | 8 ++++---- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/nau_openedx_extensions/locale/en/LC_MESSAGES/django.mo b/nau_openedx_extensions/locale/en/LC_MESSAGES/django.mo index 46d442a7c17dbdcc98303f4a4266c635027d8f33..ca6659eddb9ef6314de0b244c432ce2ed93b82b2 100644 GIT binary patch delta 24 fcmbQhHi2!zdtM`5Ln8%4BP&x2T?5mNe?*u7S=|Qu delta 24 fcmbQhHi2!zdtL)w10w}PV=GfLZ3DxNe?*u7S%n7h diff --git a/nau_openedx_extensions/locale/en/LC_MESSAGES/django.po b/nau_openedx_extensions/locale/en/LC_MESSAGES/django.po index 007c63a..186bc96 100644 --- a/nau_openedx_extensions/locale/en/LC_MESSAGES/django.po +++ b/nau_openedx_extensions/locale/en/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: equipa@nau.edu.pt\n" -"POT-Creation-Date: 2024-10-02 13:56+0100\n" +"POT-Creation-Date: 2024-12-12 12:58-0500\n" "PO-Revision-Date: 2021-02-15 15:56+0000\n" "Last-Translator: FULL NAME \n" "Language: en\n" @@ -108,18 +108,18 @@ msgstr "" "href='https://www.nau.edu.pt/legal/consentimento-para-o-envio-de-" "newsletters/'>consent to the sending of newsletters" -#: nau_openedx_extensions/filters/pipeline.py:50 +#: nau_openedx_extensions/filters/pipeline.py:51 msgid "" "You need to activate your account before you can enroll in the course. " "Check your {email} inbox for an account activation link from " "{platform_name}." msgstr "" -#: nau_openedx_extensions/filters/pipeline.py:62 +#: nau_openedx_extensions/filters/pipeline.py:63 msgid "If you think this is an error, contact the course support." msgstr "" -#: nau_openedx_extensions/filters/pipeline.py:63 +#: nau_openedx_extensions/filters/pipeline.py:64 #, python-format msgid "" "You can't enroll on this course because your email domain is not allowed." diff --git a/nau_openedx_extensions/locale/pt_PT/LC_MESSAGES/django.mo b/nau_openedx_extensions/locale/pt_PT/LC_MESSAGES/django.mo index b2f3646d20ef8678444b41a15eb6c6fe73a45735..97e5ba802856ac9be3436b667fac7ae2e689f2ee 100644 GIT binary patch delta 26 hcmbOsJVSUx2Me!}uAz~Fp^=rTg|30==BX^qtN>tT266xZ delta 26 hcmbOsJVSUx2Me!(u7Qz)p|O>znYMx9=BX^qtN>sG250~P diff --git a/nau_openedx_extensions/locale/pt_PT/LC_MESSAGES/django.po b/nau_openedx_extensions/locale/pt_PT/LC_MESSAGES/django.po index 415ac13..8eab565 100644 --- a/nau_openedx_extensions/locale/pt_PT/LC_MESSAGES/django.po +++ b/nau_openedx_extensions/locale/pt_PT/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: equipa@nau.edu.pt\n" -"POT-Creation-Date: 2024-10-02 13:56+0100\n" +"POT-Creation-Date: 2024-12-12 12:58-0500\n" "PO-Revision-Date: 2021-02-15 15:56+0000\n" "Last-Translator: Ivo Branco \n" "Language: pt_PT\n" @@ -110,7 +110,7 @@ msgstr "" "href='https://www.nau.edu.pt/legal/consentimento-para-o-envio-de-" "newsletters/'>consentimento para o envio de newsletters" -#: nau_openedx_extensions/filters/pipeline.py:50 +#: nau_openedx_extensions/filters/pipeline.py:51 msgid "" "You need to activate your account before you can enroll in the course. " "Check your {email} inbox for an account activation link from " @@ -120,11 +120,11 @@ msgstr "" "Verifique no seu e-mail {email} o link de ativação da conta " "{platform_name}." -#: nau_openedx_extensions/filters/pipeline.py:62 +#: nau_openedx_extensions/filters/pipeline.py:63 msgid "If you think this is an error, contact the course support." msgstr "Se achar que se trata de um erro, contacte o suporte." -#: nau_openedx_extensions/filters/pipeline.py:63 +#: nau_openedx_extensions/filters/pipeline.py:64 #, python-format msgid "" "You can't enroll on this course because your email domain is not allowed." From 673057c865d203ce5d0e1a8d9574857fa7abda5a Mon Sep 17 00:00:00 2001 From: Bryann Valderrama Date: Fri, 13 Dec 2024 14:47:33 -0500 Subject: [PATCH 18/25] test: add FilterUserWithAllowedNewsletter unit tests --- nau_openedx_extensions/tests/test_pipeline.py | 34 ++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/nau_openedx_extensions/tests/test_pipeline.py b/nau_openedx_extensions/tests/test_pipeline.py index 43b4689..1d12137 100644 --- a/nau_openedx_extensions/tests/test_pipeline.py +++ b/nau_openedx_extensions/tests/test_pipeline.py @@ -4,12 +4,13 @@ from unittest.mock import MagicMock, Mock, patch +from django.db.models import QuerySet from django.test import TestCase from django.test.utils import override_settings from opaque_keys.edx.keys import CourseKey from openedx_filters.learning.filters import CourseEnrollmentStarted -from nau_openedx_extensions.filters.pipeline import FilterEnrollmentByDomain +from nau_openedx_extensions.filters.pipeline import FilterEnrollmentByDomain, FilterUsersWithAllowedNewsletter class FilterEnrollmentByDomainTest(TestCase): @@ -246,3 +247,34 @@ def test_inactive_user_with_email_not_in_allowed_domains(self): "You need to activate your account before you can enroll in the course. " "Check your example@example.com inbox for an account activation link from NAU." )) + + +class TestFilterUsersWithAllowedNewsletter(TestCase): + """Test the FilterUsersWithAllowedNewsletter class that filters users who have allowed newsletters.""" + + def test_run_filter_with_allowed_newsletter_users(self): + """ + Test that the filter returns only schedules for users who have allowed newsletters. + """ + mock_schedules = Mock(spec=QuerySet) + mock_schedules.filter.return_value = mock_schedules + + result = FilterUsersWithAllowedNewsletter.run_filter(self, mock_schedules) + + mock_schedules.filter.assert_called_once_with(enrollment__user__nauuserextendedmodel__allow_newsletter=True) + self.assertIsInstance(result, dict) + self.assertIn("schedules", result) + self.assertEqual(result["schedules"], mock_schedules) + + def test_run_filter_with_empty_queryset(self): + """ + Test that the filter works correctly with an empty queryset. + """ + mock_schedules = Mock(spec=QuerySet) + mock_schedules.filter.return_value = mock_schedules + + result = FilterUsersWithAllowedNewsletter.run_filter(self, mock_schedules) + + mock_schedules.filter.assert_called_once_with(enrollment__user__nauuserextendedmodel__allow_newsletter=True) + self.assertIsInstance(result, dict) + self.assertIn("schedules", result) From 814a9b575c4067d3a643897c80bc4deacf0b3077 Mon Sep 17 00:00:00 2001 From: Bryann Valderrama Date: Mon, 16 Dec 2024 13:50:46 -0500 Subject: [PATCH 19/25] test: add unit test for new filter --- nau_openedx_extensions/tests/test_pipeline.py | 42 ++++++++++--------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/nau_openedx_extensions/tests/test_pipeline.py b/nau_openedx_extensions/tests/test_pipeline.py index 1d12137..cb47ecc 100644 --- a/nau_openedx_extensions/tests/test_pipeline.py +++ b/nau_openedx_extensions/tests/test_pipeline.py @@ -4,9 +4,9 @@ from unittest.mock import MagicMock, Mock, patch -from django.db.models import QuerySet from django.test import TestCase from django.test.utils import override_settings +from django_mock_queries.query import MockModel, MockSet from opaque_keys.edx.keys import CourseKey from openedx_filters.learning.filters import CourseEnrollmentStarted @@ -250,31 +250,35 @@ def test_inactive_user_with_email_not_in_allowed_domains(self): class TestFilterUsersWithAllowedNewsletter(TestCase): - """Test the FilterUsersWithAllowedNewsletter class that filters users who have allowed newsletters.""" + """ + Test the FilterUsersWithAllowedNewsletter class that filters users who have allowed newsletters. + """ - def test_run_filter_with_allowed_newsletter_users(self): + def test_run_filter(self): """ Test that the filter returns only schedules for users who have allowed newsletters. - """ - mock_schedules = Mock(spec=QuerySet) - mock_schedules.filter.return_value = mock_schedules - - result = FilterUsersWithAllowedNewsletter.run_filter(self, mock_schedules) - mock_schedules.filter.assert_called_once_with(enrollment__user__nauuserextendedmodel__allow_newsletter=True) - self.assertIsInstance(result, dict) - self.assertIn("schedules", result) - self.assertEqual(result["schedules"], mock_schedules) - - def test_run_filter_with_empty_queryset(self): - """ - Test that the filter works correctly with an empty queryset. + Expected result: + - The filter returns a dictionary with the key schedules and a queryset of schedules. + - The schedules queryset has only one schedule that has a user with allow_newsletter=True. + - The other schedules that have a user with allow_newsletter=False or without allow_newsletter + are not in the queryset. """ - mock_schedules = Mock(spec=QuerySet) - mock_schedules.filter.return_value = mock_schedules + mock_schedules = MockSet( + MockModel( + mock_name="allow_newsletter_true", + enrollment=MockModel(user=MockModel(nauuserextendedmodel=MockModel(allow_newsletter=True))), + ), + MockModel( + mock_name="allow_newsletter_false", + enrollment=MockModel(user=MockModel(nauuserextendedmodel=MockModel(allow_newsletter=False))), + ), + MockModel(mock_name="without_allow_newsletter", enrollment=MockModel(user=MockModel())), + ) result = FilterUsersWithAllowedNewsletter.run_filter(self, mock_schedules) - mock_schedules.filter.assert_called_once_with(enrollment__user__nauuserextendedmodel__allow_newsletter=True) self.assertIsInstance(result, dict) self.assertIn("schedules", result) + self.assertEqual(len(result["schedules"]), 1) + self.assertEqual(result["schedules"][0].mock_name, "allow_newsletter_true") From 73bcb940179ec9eeb19e8aee64dc2453adb5b664 Mon Sep 17 00:00:00 2001 From: Bryann Valderrama Date: Mon, 16 Dec 2024 14:07:24 -0500 Subject: [PATCH 20/25] chore: add django_mock_queries in test requirements --- requirements/test.in | 1 + requirements/test.txt | 2 ++ 2 files changed, 3 insertions(+) diff --git a/requirements/test.in b/requirements/test.in index d774883..ecb481a 100644 --- a/requirements/test.in +++ b/requirements/test.in @@ -8,3 +8,4 @@ pycodestyle pylint pytest coverage +django_mock_queries diff --git a/requirements/test.txt b/requirements/test.txt index a7de424..b24fb05 100644 --- a/requirements/test.txt +++ b/requirements/test.txt @@ -50,3 +50,5 @@ typing-extensions==4.3.0 # via astroid, pylint vine==5.1.0 # via -r requirements/base.txt, amqp, celery web-fragments==2.0.0 # via -r requirements/base.txt wrapt==1.14.1 # via astroid +django_mock_queries==2.3.0 # via -r requirements/test.in +model-bakery==1.5.0 # via django_mock_queries From 78144fb0fc1c5b9dfa44730ce53a4db371139963 Mon Sep 17 00:00:00 2001 From: Bryann Valderrama Date: Tue, 17 Dec 2024 08:19:05 -0500 Subject: [PATCH 21/25] docs: update pipeline docstring --- nau_openedx_extensions/filters/pipeline.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/nau_openedx_extensions/filters/pipeline.py b/nau_openedx_extensions/filters/pipeline.py index a06f1f9..36cf371 100644 --- a/nau_openedx_extensions/filters/pipeline.py +++ b/nau_openedx_extensions/filters/pipeline.py @@ -87,6 +87,10 @@ class FilterUsersWithAllowedNewsletter(PipelineStep): `allow_newsletter` field set to `True`, or if the field does not exist, the Schedule will be filtered out. + The Schedules QuerySet is used to send recurring nudges emails to users. + This filter allows excluding users who have opted out of receiving these + emails. + Example usage: Add the following configurations to your configuration file: From 78b4bb0f4cca728f5a0dac0c6ee24f80e514887c Mon Sep 17 00:00:00 2001 From: Bryann Valderrama Date: Wed, 11 Dec 2024 13:52:49 -0500 Subject: [PATCH 22/25] feat: add boolean field in the extended profile fields --- .../context_extender.py | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/nau_openedx_extensions/custom_registration_form/context_extender.py b/nau_openedx_extensions/custom_registration_form/context_extender.py index 5b61005..0014f6d 100644 --- a/nau_openedx_extensions/custom_registration_form/context_extender.py +++ b/nau_openedx_extensions/custom_registration_form/context_extender.py @@ -44,14 +44,21 @@ def update_account_view(context, user, **kwargs): custom_model_instance = NauUserExtendedModel() finally: for field in get_fields(custom_model_instance): - extended_profile_fields.append( - { - "field_name": _(field.name), # pylint: disable=translation-of-non-string - "field_label": _(field.verbose_name), # pylint: disable=translation-of-non-string - "field_type": "TextField" if not field.choices else "ListField", - "field_options": [] if not field.choices else field.choices, - } - ) + extended_profile_field = { + "field_name": _(field.name), # pylint: disable=translation-of-non-string + "field_label": _(field.verbose_name), # pylint: disable=translation-of-non-string + } + if isinstance(field, models.BooleanField): + extended_profile_field["field_type"] = "CheckboxField" + extended_profile_field["field_options"] = [] + elif field.choices: + extended_profile_field["field_type"] = "ListField" + extended_profile_field["field_options"] = field.choices + else: + extended_profile_field["field_type"] = "TextField" + extended_profile_field["field_options"] = [] + + extended_profile_fields.append(extended_profile_field) context["extended_profile_fields"].extend(extended_profile_fields) From 11b21ee579daf7a556cddd6a1b7f6d4472a8b4b4 Mon Sep 17 00:00:00 2001 From: Bryann Valderrama Date: Thu, 12 Dec 2024 11:36:07 -0500 Subject: [PATCH 23/25] feat: add allow_newsletter field into account settings --- .../custom_registration_form/context_extender.py | 2 +- nau_openedx_extensions/settings/common.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/nau_openedx_extensions/custom_registration_form/context_extender.py b/nau_openedx_extensions/custom_registration_form/context_extender.py index 0014f6d..dc831ce 100644 --- a/nau_openedx_extensions/custom_registration_form/context_extender.py +++ b/nau_openedx_extensions/custom_registration_form/context_extender.py @@ -27,7 +27,7 @@ def get_fields(custom_model_instance): for field in custom_fields: if field.name not in allowed_fields: continue - if isinstance(field, (models.CharField, models.TextField)): + if isinstance(field, (models.CharField, models.TextField, models.BooleanField)): yield field diff --git a/nau_openedx_extensions/settings/common.py b/nau_openedx_extensions/settings/common.py index 36e4995..02c7890 100644 --- a/nau_openedx_extensions/settings/common.py +++ b/nau_openedx_extensions/settings/common.py @@ -77,7 +77,7 @@ def plugin_settings(settings): settings.NAU_COURSE_MESSAGE_BATCH_SIZE = 50 settings.NAU_COURSE_MESSAGE_RECIPIENT_FIELDS = ["profile__name", "email"] settings.NAU_CC_ALLOWED_SLUG = "cccmd:" - settings.NAU_ACCOUNTS_CC_VISIBLE_FIELDS = ["employment_situation", "nif"] + settings.NAU_ACCOUNTS_CC_VISIBLE_FIELDS = ["employment_situation", "nif", "allow_newsletter"] settings.SCORMXBLOCK_ASYNC_THRESHOLD = 500 settings.NAU_SITE_CONFIGURATION_HELPERS_MODULE = ( "nau_openedx_extensions.edxapp_wrapper.backends.site_configuration_helpers_l_v1" From 569cd4b01747e481e018d864b184400d7e2780dc Mon Sep 17 00:00:00 2001 From: Bryann Valderrama Date: Thu, 12 Dec 2024 14:58:32 -0500 Subject: [PATCH 24/25] chore: fix pylint errors --- .../custom_registration_form/context_extender.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nau_openedx_extensions/custom_registration_form/context_extender.py b/nau_openedx_extensions/custom_registration_form/context_extender.py index dc831ce..149faa0 100644 --- a/nau_openedx_extensions/custom_registration_form/context_extender.py +++ b/nau_openedx_extensions/custom_registration_form/context_extender.py @@ -45,8 +45,8 @@ def update_account_view(context, user, **kwargs): finally: for field in get_fields(custom_model_instance): extended_profile_field = { - "field_name": _(field.name), # pylint: disable=translation-of-non-string - "field_label": _(field.verbose_name), # pylint: disable=translation-of-non-string + "field_name": _(field.name), # pylint: disable=translation-of-non-string + "field_label": _(field.verbose_name), # pylint: disable=translation-of-non-string } if isinstance(field, models.BooleanField): extended_profile_field["field_type"] = "CheckboxField" From c279fd70299c6f0744a51a4be8a4e8f9f4e2afb0 Mon Sep 17 00:00:00 2001 From: Ivo Branco Date: Fri, 3 Jan 2025 12:34:23 +0000 Subject: [PATCH 25/25] fix: correct expiration date calculation for ID verification --- nau_openedx_extensions/verify_student/id_verification.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nau_openedx_extensions/verify_student/id_verification.py b/nau_openedx_extensions/verify_student/id_verification.py index 20ea909..d51ff4c 100644 --- a/nau_openedx_extensions/verify_student/id_verification.py +++ b/nau_openedx_extensions/verify_student/id_verification.py @@ -40,7 +40,7 @@ def verification_active_predicate(verification): if verification_active: log.info("User %d already has an ID verification", user_id) else: - expiration_date = now + timedelta(days=36500) # 100 years + expiration_date = now + timedelta(days=365 * 100 + 100/4) # 365 days * 100 years + leap year days log.info("Create user ID Verification for %d", user_id) create_user_id_verification( user_id,