diff --git a/corehq/apps/data_analytics/migrations/0011_domainmetrics.py b/corehq/apps/data_analytics/migrations/0011_domainmetrics.py new file mode 100644 index 000000000000..186e4f4b93c1 --- /dev/null +++ b/corehq/apps/data_analytics/migrations/0011_domainmetrics.py @@ -0,0 +1,73 @@ +# Generated by Django 4.2.16 on 2024-12-06 01:12 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('data_analytics', '0010_maltrow_last_run_date'), + ] + + operations = [ + migrations.CreateModel( + name='DomainMetrics', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('domain', models.TextField(db_index=True, unique=True)), + ('date_created', models.DateTimeField(auto_now_add=True)), + ('last_modified', models.DateTimeField(auto_now=True)), + ('has_project_icon', models.BooleanField()), + ('has_security_settings', models.BooleanField()), + ('is_active', models.BooleanField()), + ('is_first_domain_for_creating_user', models.BooleanField()), + ('lookup_tables', models.IntegerField()), + ('repeaters', models.IntegerField()), + ('ucrs', models.IntegerField()), + ('apps', models.IntegerField()), + ('apps_with_icon', models.IntegerField()), + ('apps_with_multiple_languages', models.IntegerField()), + ('mobile_workers', models.IntegerField()), + ('web_users', models.IntegerField()), + ('active_mobile_workers', models.IntegerField()), + ('active_mobile_workers_in_last_365_days', models.IntegerField()), + ('case_sharing_groups', models.IntegerField()), + ('case_sharing_locations', models.IntegerField()), + ('has_custom_roles', models.BooleanField()), + ('has_locations', models.BooleanField()), + ('location_restricted_users', models.IntegerField()), + ('users_with_submission', models.IntegerField()), + ('cases', models.IntegerField()), + ('active_cases', models.IntegerField()), + ('cases_modified_in_last_30_days', models.IntegerField()), + ('cases_modified_in_last_60_days', models.IntegerField()), + ('cases_modified_in_last_90_days', models.IntegerField()), + ('inactive_cases', models.IntegerField()), + ('usercases_modified_in_last_30_days', models.IntegerField()), + ('forms', models.IntegerField()), + ('forms_submitted_in_last_30_days', models.IntegerField()), + ('forms_submitted_in_last_60_days', models.IntegerField()), + ('forms_submitted_in_last_90_days', models.IntegerField()), + ('first_form_submission', models.DateTimeField(null=True)), + ('most_recent_form_submission', models.DateTimeField(null=True)), + ('three_hundredth_form_submission', models.DateTimeField(null=True)), + ('total_sms', models.IntegerField()), + ('sms_in_last_30_days', models.IntegerField()), + ('sms_in_last_60_days', models.IntegerField()), + ('sms_in_last_90_days', models.IntegerField()), + ('incoming_sms', models.IntegerField()), + ('incoming_sms_in_last_30_days', models.IntegerField()), + ('incoming_sms_in_last_60_days', models.IntegerField()), + ('incoming_sms_in_last_90_days', models.IntegerField()), + ('outgoing_sms', models.IntegerField()), + ('outgoing_sms_in_last_30_days', models.IntegerField()), + ('outgoing_sms_in_last_60_days', models.IntegerField()), + ('outgoing_sms_in_last_90_days', models.IntegerField()), + ('telerivet_backends', models.IntegerField()), + ('case_exports', models.IntegerField()), + ('custom_exports', models.IntegerField()), + ('deid_exports', models.IntegerField()), + ('saved_exports', models.IntegerField()), + ], + ), + ] diff --git a/corehq/apps/data_analytics/models.py b/corehq/apps/data_analytics/models.py index 1d7d3398d0fc..3cb7a801c57b 100644 --- a/corehq/apps/data_analytics/models.py +++ b/corehq/apps/data_analytics/models.py @@ -157,3 +157,94 @@ def export_row(self, past_months): experienced_threshold=self.experienced_threshold or DEFAULT_EXPERIENCED_THRESHOLD, performance_threshold=self.performance_threshold or DEFAULT_PERFORMANCE_THRESHOLD, ) + + +class DomainMetrics(models.Model): + + domain = models.TextField(unique=True, db_index=True) + date_created = models.DateTimeField(auto_now_add=True) + last_modified = models.DateTimeField(auto_now=True) + + has_project_icon = models.BooleanField() + has_security_settings = models.BooleanField() + is_active = models.BooleanField() + is_first_domain_for_creating_user = models.BooleanField() + + lookup_tables = models.IntegerField() + repeaters = models.IntegerField() + ucrs = models.IntegerField() + + # App Metrics + apps = models.IntegerField() + apps_with_icon = models.IntegerField() + apps_with_multiple_languages = models.IntegerField() + + # User Metrics + mobile_workers = models.IntegerField() + web_users = models.IntegerField() + + active_mobile_workers = models.IntegerField() + active_mobile_workers_in_last_365_days = models.IntegerField() + case_sharing_groups = models.IntegerField() + case_sharing_locations = models.IntegerField() + has_custom_roles = models.BooleanField() + has_locations = models.BooleanField() + location_restricted_users = models.IntegerField() + users_with_submission = models.IntegerField() + + # Case Metrics + cases = models.IntegerField() + + active_cases = models.IntegerField() + cases_modified_in_last_30_days = models.IntegerField() + cases_modified_in_last_60_days = models.IntegerField() + cases_modified_in_last_90_days = models.IntegerField() + inactive_cases = models.IntegerField() + usercases_modified_in_last_30_days = models.IntegerField() + + # Form Metrics + forms = models.IntegerField() + forms_submitted_in_last_30_days = models.IntegerField() + forms_submitted_in_last_60_days = models.IntegerField() + forms_submitted_in_last_90_days = models.IntegerField() + + first_form_submission = models.DateTimeField(null=True) + most_recent_form_submission = models.DateTimeField(null=True) + three_hundredth_form_submission = models.DateTimeField(null=True) + + # SMS Metrics + total_sms = models.IntegerField() + sms_in_last_30_days = models.IntegerField() + sms_in_last_60_days = models.IntegerField() + sms_in_last_90_days = models.IntegerField() + + incoming_sms = models.IntegerField() + incoming_sms_in_last_30_days = models.IntegerField() + incoming_sms_in_last_60_days = models.IntegerField() + incoming_sms_in_last_90_days = models.IntegerField() + + outgoing_sms = models.IntegerField() + outgoing_sms_in_last_30_days = models.IntegerField() + outgoing_sms_in_last_60_days = models.IntegerField() + outgoing_sms_in_last_90_days = models.IntegerField() + + telerivet_backends = models.IntegerField() + + # Export Metrics + case_exports = models.IntegerField() + custom_exports = models.IntegerField() + deid_exports = models.IntegerField() + saved_exports = models.IntegerField() + + # Calculated properties + @property + def has_app(self): + return bool(self.apps) + + @property + def has_used_sms(self): + return bool(self.total_sms) + + @property + def has_used_sms_in_last_30_days(self): + return bool(self.sms_in_last_30_days) diff --git a/corehq/apps/domain/deletion.py b/corehq/apps/domain/deletion.py index d5ee8891faac..2714f2124206 100644 --- a/corehq/apps/domain/deletion.py +++ b/corehq/apps/domain/deletion.py @@ -366,6 +366,7 @@ def _delete_demo_user_restores(domain_name): ModelDeletion('custom_data_fields', 'CustomDataFieldsDefinition', 'domain', [ 'CustomDataFieldsProfile', 'Field', ]), + ModelDeletion('data_analytics', 'DomainMetrics', 'domain'), ModelDeletion('data_analytics', 'GIRRow', 'domain_name'), ModelDeletion('data_analytics', 'MALTRow', 'domain_name'), ModelDeletion('data_dictionary', 'CaseType', 'domain', [ diff --git a/corehq/apps/dump_reload/tests/test_dump_models.py b/corehq/apps/dump_reload/tests/test_dump_models.py index 0bf30270d94b..e38263e411fb 100644 --- a/corehq/apps/dump_reload/tests/test_dump_models.py +++ b/corehq/apps/dump_reload/tests/test_dump_models.py @@ -52,6 +52,7 @@ "cleanup.DeletedCouchDoc", "cleanup.DeletedSQLDoc", "contenttypes.ContentType", + "data_analytics.DomainMetrics", "data_analytics.GIRRow", "data_analytics.MALTRow", "django_celery_results.ChordCounter", diff --git a/migrations.lock b/migrations.lock index 515762313673..041b620a6b13 100644 --- a/migrations.lock +++ b/migrations.lock @@ -307,6 +307,7 @@ data_analytics 0008_auto_20161114_1903 0009_remove_girrow_wam 0010_maltrow_last_run_date + 0011_domainmetrics data_dictionary 0001_squashed_0002_auto_20161116_2209 0002_auto_20161118_1537