diff --git a/api/institutions/serializers.py b/api/institutions/serializers.py index 29c7c8b380a..e3679b2a9c5 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 c13cb1f8d74..f5602bafcb2 100644 --- a/api/institutions/views.py +++ b/api/institutions/views.py @@ -561,6 +561,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..1e85b31a95f 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_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(), @@ -140,3 +141,20 @@ def _storage_byte_count(self): purged__isnull=True, basefilenode__in=self._public_osfstorage_file_queryset(), ).aggregate(storage_bytes=Sum('size', default=0))['storage_bytes'] + + def _get_last_active(self): + end_date = self.yearmonth.next_month() + + node_logs = self.user.logs.filter(created__lt=end_date).order_by('-created') + preprint_logs = self.user.preprint_logs.filter(created__lt=end_date).order_by('-created') + + latest_node_log_date = node_logs.first().created if node_logs.exists() else None + latest_preprint_log_date = preprint_logs.first().created if preprint_logs.exists() else None + dates = [date for date in [latest_node_log_date, latest_preprint_log_date] if date is not None] + + latest_activity_date = max(dates, default=None) + + if latest_activity_date: + return YearMonth.from_date(latest_activity_date) + else: + return None diff --git a/osf/metrics/reports.py b/osf/metrics/reports.py index 08d14867ae0..76fa7e65b51 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..e807a93f50a 100644 --- a/osf_tests/metrics/reporters/test_institutional_users_reporter.py +++ b/osf_tests/metrics/reporters/test_institutional_users_reporter.py @@ -52,6 +52,11 @@ def _assert_report_matches_setup(self, report: InstitutionalUserReport, setup: _ self.assertEqual(report.user_name, setup.user.fullname) self.assertEqual(report.department_name, setup.department_name) self.assertEqual(report.month_last_login, YearMonth.from_date(setup.user.date_last_login)) + if setup.user.month_last_active: + self.assertEqual(report.month_last_active, YearMonth.from_date(setup.user.month_last_active)) + else: + self.assertEqual(report.month_last_active, setup.user.month_last_active) + self.assertEqual(report.account_creation_date, YearMonth.from_date(setup.user.created)) self.assertEqual(report.orcid_id, setup.orcid_id) # counts (NOTE: report.public_file_count and report.storage_byte_count tested separately) @@ -159,6 +164,8 @@ def __post_init__(self): ), ) self._add_affiliations(self._generate_counted_objects()) + recent_log = self.user.logs.order_by('-created').first() + self.user.month_last_active = getattr(recent_log, 'created', None) def affiliate_user(self): self.user.add_or_update_affiliated_institution(