diff --git a/lms/djangoapps/certificates/models.py b/lms/djangoapps/certificates/models.py index 983446275a6..ceb9b5804f1 100644 --- a/lms/djangoapps/certificates/models.py +++ b/lms/djangoapps/certificates/models.py @@ -465,8 +465,12 @@ def save(self, *args, **kwargs): # pylint: disable=signature-differs Credentials IDA. """ super().save(*args, **kwargs) + if self._meta.proxy: + sending_class = self._meta.proxy_for_model + else: + sending_class = self.__class__ COURSE_CERT_CHANGED.send_robust( - sender=self.__class__, + sender=sending_class, user=self.user, course_key=self.course_id, mode=self.mode, @@ -498,7 +502,7 @@ def save(self, *args, **kwargs): # pylint: disable=signature-differs if CertificateStatuses.is_passing_status(self.status): COURSE_CERT_AWARDED.send_robust( - sender=self.__class__, + sender=sending_class, user=self.user, course_key=self.course_id, mode=self.mode, diff --git a/lms/djangoapps/grades/signals/handlers.py b/lms/djangoapps/grades/signals/handlers.py index 14089d74ea5..a3f605bbd16 100644 --- a/lms/djangoapps/grades/signals/handlers.py +++ b/lms/djangoapps/grades/signals/handlers.py @@ -152,7 +152,7 @@ def score_published_handler(sender, block, user, raw_earned, raw_possible, only_ if previous_score is not None: prev_raw_earned, prev_raw_possible = (previous_score.grade, previous_score.max_grade) - if not is_score_higher_or_equal(prev_raw_earned, prev_raw_possible, raw_earned, raw_possible): + if not is_score_higher_or_equal(prev_raw_earned, prev_raw_possible, raw_earned, raw_possible, True): update_score = False log.warning( "Grades: Rescore is not higher than previous: " diff --git a/lms/envs/common.py b/lms/envs/common.py index 958d06ccbfd..cacb6031af9 100644 --- a/lms/envs/common.py +++ b/lms/envs/common.py @@ -1430,6 +1430,7 @@ def _make_mako_template_dirs(settings): GOOGLE_SITE_VERIFICATION_ID = '' GOOGLE_ANALYTICS_LINKEDIN = 'GOOGLE_ANALYTICS_LINKEDIN_DUMMY' GOOGLE_ANALYTICS_TRACKING_ID = None +GOOGLE_ANALYTICS_4_ID = None ######################## BRANCH.IO ########################### BRANCH_IO_KEY = '' diff --git a/lms/envs/production.py b/lms/envs/production.py index 75a225ca30c..dd683595107 100644 --- a/lms/envs/production.py +++ b/lms/envs/production.py @@ -686,6 +686,7 @@ def get_env_setting(setting): GOOGLE_ANALYTICS_TRACKING_ID = AUTH_TOKENS.get('GOOGLE_ANALYTICS_TRACKING_ID') GOOGLE_ANALYTICS_LINKEDIN = AUTH_TOKENS.get('GOOGLE_ANALYTICS_LINKEDIN') GOOGLE_SITE_VERIFICATION_ID = ENV_TOKENS.get('GOOGLE_SITE_VERIFICATION_ID') +GOOGLE_ANALYTICS_4_ID = AUTH_TOKENS.get('GOOGLE_ANALYTICS_4_ID') ##### BRANCH.IO KEY ##### BRANCH_IO_KEY = AUTH_TOKENS.get('BRANCH_IO_KEY') diff --git a/lms/templates/certificates/accomplishment-base.html b/lms/templates/certificates/accomplishment-base.html index 1fe0456469c..554bb607ccb 100644 --- a/lms/templates/certificates/accomplishment-base.html +++ b/lms/templates/certificates/accomplishment-base.html @@ -19,6 +19,19 @@ ${document_title} <%static:css group='style-certificates'/> + + + <% ga_4_id = static.get_value("GOOGLE_ANALYTICS_4_ID", settings.GOOGLE_ANALYTICS_4_ID) %> + % if ga_4_id: + + + % endif diff --git a/lms/templates/main.html b/lms/templates/main.html index 83416317ba8..a6bac477514 100644 --- a/lms/templates/main.html +++ b/lms/templates/main.html @@ -163,6 +163,18 @@ % endif +<% ga_4_id = static.get_value("GOOGLE_ANALYTICS_4_ID", settings.GOOGLE_ANALYTICS_4_ID) %> +% if ga_4_id: + + +% endif + <% branch_key = static.get_value("BRANCH_IO_KEY", settings.BRANCH_IO_KEY) %> % if branch_key and not is_from_mobile_app: + + {% endif %} + diff --git a/openedx/core/djangoapps/site_configuration/templatetags/configuration.py b/openedx/core/djangoapps/site_configuration/templatetags/configuration.py index b5242a53b5b..9de10d3bb07 100644 --- a/openedx/core/djangoapps/site_configuration/templatetags/configuration.py +++ b/openedx/core/djangoapps/site_configuration/templatetags/configuration.py @@ -65,3 +65,12 @@ def microsite_template_path(template_name): """ template_name = theming_helpers.get_template_path(template_name) return template_name[1:] if template_name[0] == '/' else template_name + + +@register.simple_tag +def google_analytics_4_id(): + """ + Django template tag that outputs the GOOGLE_ANALYTICS_4_ID: + {% google_analytics_4_id %} + """ + return configuration_helpers.get_value("GOOGLE_ANALYTICS_4_ID", settings.GOOGLE_ANALYTICS_4_ID) diff --git a/openedx/core/lib/grade_utils.py b/openedx/core/lib/grade_utils.py index 2e7073e962d..48c262e85a5 100644 --- a/openedx/core/lib/grade_utils.py +++ b/openedx/core/lib/grade_utils.py @@ -17,14 +17,14 @@ def compare_scores(earned1, possible1, earned2, possible2, treat_undefined_as_ze """ try: percentage1 = float(earned1) / float(possible1) - except ZeroDivisionError: + except (ZeroDivisionError, TypeError): if not treat_undefined_as_zero: raise percentage1 = 0.0 try: percentage2 = float(earned2) / float(possible2) - except ZeroDivisionError: + except (ZeroDivisionError, TypeError): if not treat_undefined_as_zero: raise percentage2 = 0.0