From 2347759f09166f4df9790b74466c31c9c2477206 Mon Sep 17 00:00:00 2001 From: John Tordoff <> Date: Mon, 23 Sep 2024 10:12:37 -0400 Subject: [PATCH] add reporter stat for monthly_active_users --- api/institutions/serializers.py | 1 + api/institutions/views.py | 1 + osf/metrics/reporters/institutional_users.py | 18 ++++++++++++++++++ osf/metrics/reports.py | 1 + .../test_institutional_users_reporter.py | 2 ++ 5 files changed, 23 insertions(+) diff --git a/api/institutions/serializers.py b/api/institutions/serializers.py index 70afb93c157..aa0956d9cc8 100644 --- a/api/institutions/serializers.py +++ b/api/institutions/serializers.py @@ -334,6 +334,7 @@ class Meta: department = ser.CharField(read_only=True, source='department_name') orcid_id = ser.CharField(read_only=True) month_last_login = YearmonthField(read_only=True) + month_last_active = YearmonthField(read_only=True) account_creation_date = YearmonthField(read_only=True) public_projects = ser.IntegerField(read_only=True, source='public_project_count') diff --git a/api/institutions/views.py b/api/institutions/views.py index c21dd6bddb7..14fb80106b8 100644 --- a/api/institutions/views.py +++ b/api/institutions/views.py @@ -560,6 +560,7 @@ class _NewInstitutionUserMetricsList(InstitutionMixin, ElasticsearchListView): 'user_name', 'department', 'month_last_login', + 'month_last_active', 'account_creation_date', 'public_projects', 'private_projects', diff --git a/osf/metrics/reporters/institutional_users.py b/osf/metrics/reporters/institutional_users.py index 98e13003387..3bf8f7324e8 100644 --- a/osf/metrics/reporters/institutional_users.py +++ b/osf/metrics/reporters/institutional_users.py @@ -52,6 +52,7 @@ def __post_init__(self): if self.user.date_last_login is not None else None ), + month_last_active=self.get_month_last_active(), account_creation_date=YearMonth.from_date(self.user.created), orcid_id=self.user.get_verified_external_id('ORCID', verified_only=True), public_project_count=self._public_project_queryset().count(), @@ -80,6 +81,23 @@ def _public_project_queryset(self): root_id=F('pk'), # only root nodes ) + def get_month_last_active(self): + """ + Calculate the last month the user was active, based on their node and preprint logs, + get the most recent + """ + last_node_log_date = self.user.logs.filter( + created__lt=self.before_datetime + ).order_by('-created').values_list('created', flat=True).first() + + last_preprint_log_date = self.user.preprint_logs.filter( + created__lt=self.before_datetime + ).order_by('-created').values_list('created', flat=True).first() + + if last_node_log_date and last_preprint_log_date: + most_recent_log = max(last_node_log_date, last_preprint_log_date) + return YearMonth.from_date(most_recent_log) + def _private_project_queryset(self): return self._node_queryset().filter( type='osf.node', # `type` field from TypedModel diff --git a/osf/metrics/reports.py b/osf/metrics/reports.py index cee4efc7c02..996e3c3b4ae 100644 --- a/osf/metrics/reports.py +++ b/osf/metrics/reports.py @@ -260,6 +260,7 @@ class InstitutionalUserReport(MonthlyReport): user_name = metrics.Keyword() department_name = metrics.Keyword() month_last_login = YearmonthField() + month_last_active = YearmonthField() account_creation_date = YearmonthField() orcid_id = metrics.Keyword() # counts: diff --git a/osf_tests/metrics/reporters/test_institutional_users_reporter.py b/osf_tests/metrics/reporters/test_institutional_users_reporter.py index 8fbb873083f..dd453168774 100644 --- a/osf_tests/metrics/reporters/test_institutional_users_reporter.py +++ b/osf_tests/metrics/reporters/test_institutional_users_reporter.py @@ -70,12 +70,14 @@ def test_one_user_with_nothing(self): _reports = list(InstitutionalUsersReporter().report(self._yearmonth)) self.assertEqual(len(_reports), 1) self._assert_report_matches_setup(_reports[0], self._user_setup_with_nothing) + self.assertEqual(_reports[0].month_last_active, None) def test_one_user_with_ones(self): self._user_setup_with_ones.affiliate_user() _reports = list(InstitutionalUsersReporter().report(self._yearmonth)) self.assertEqual(len(_reports), 1) self._assert_report_matches_setup(_reports[0], self._user_setup_with_ones) + self.assertEqual(_reports[0].month_last_active, self._yearmonth) def test_one_user_with_stuff_and_no_files(self): self._user_setup_with_stuff.affiliate_user()