diff --git a/corehq/apps/enterprise/api/api.py b/corehq/apps/enterprise/api/api.py index 7fa2c1b3d124..a0c8508b5e54 100644 --- a/corehq/apps/enterprise/api/api.py +++ b/corehq/apps/enterprise/api/api.py @@ -1,6 +1,7 @@ from tastypie.api import Api from corehq.apps.enterprise.api.resources import ( + CaseManagementResource, CommCareVersionComplianceResource, DomainResource, FormSubmissionResource, @@ -19,6 +20,7 @@ v1_api.register(MobileUserResource()) v1_api.register(FormSubmissionResource()) v1_api.register(ODataFeedResource()) +v1_api.register(CaseManagementResource()) v1_api.register(DataExportReportResource()) v1_api.register(CommCareVersionComplianceResource()) v1_api.register(SMSResource()) diff --git a/corehq/apps/enterprise/api/resources.py b/corehq/apps/enterprise/api/resources.py index 8c5479294a28..29cb9a22c5b6 100644 --- a/corehq/apps/enterprise/api/resources.py +++ b/corehq/apps/enterprise/api/resources.py @@ -414,6 +414,28 @@ def get_primary_keys(self): return ('form_id', 'submitted',) +class CaseManagementResource(ODataEnterpriseReportResource): + domain = fields.CharField() + num_applications = fields.IntegerField() + num_surveys_only = fields.IntegerField() + num_cases_only = fields.IntegerField() + num_mixed = fields.IntegerField() + + REPORT_SLUG = EnterpriseReport.CASE_MANAGEMENT + + def dehydrate(self, bundle): + bundle.data['domain'] = bundle.obj[0] + bundle.data['num_applications'] = bundle.obj[1] + bundle.data['num_surveys_only'] = bundle.obj[2] + bundle.data['num_cases_only'] = bundle.obj[3] + bundle.data['num_mixed'] = bundle.obj[4] + + return bundle + + def get_primary_keys(self): + return ('domain',) + + class DataExportReportResource(ODataEnterpriseReportResource): domain = fields.CharField() name = fields.CharField() @@ -423,14 +445,6 @@ class DataExportReportResource(ODataEnterpriseReportResource): REPORT_SLUG = EnterpriseReport.DATA_EXPORTS - def get_report_task(self, request): - account = BillingAccount.get_account_by_domain(request.domain) - return generate_enterprise_report.s( - self.REPORT_SLUG, - account.id, - request.couch_user.username - ) - def dehydrate(self, bundle): bundle.data['domain'] = bundle.obj[0] bundle.data['name'] = bundle.obj[1] diff --git a/corehq/apps/enterprise/enterprise.py b/corehq/apps/enterprise/enterprise.py index 98e7a5ab78eb..1864d2238a83 100644 --- a/corehq/apps/enterprise/enterprise.py +++ b/corehq/apps/enterprise/enterprise.py @@ -32,6 +32,8 @@ ) from corehq.apps.enterprise.iterators import raise_after_max_elements from corehq.apps.es import forms as form_es +from corehq.apps.es import filters +from corehq.apps.es.apps import AppES from corehq.apps.es.users import UserES from corehq.apps.export.dbaccessors import ODataExportFetcher from corehq.apps.reports.util import ( @@ -52,6 +54,7 @@ class EnterpriseReport(ABC): MOBILE_USERS = 'mobile_users' FORM_SUBMISSIONS = 'form_submissions' ODATA_FEEDS = 'odata_feeds' + CASE_MANAGEMENT = 'case_management' DATA_EXPORTS = 'data_exports' COMMCARE_VERSION_COMPLIANCE = 'commcare_version_compliance' SMS = 'sms' @@ -100,6 +103,8 @@ def create(cls, slug, account_id, couch_user, **kwargs): report = EnterpriseFormReport(account, couch_user, **kwargs) elif slug == cls.ODATA_FEEDS: report = EnterpriseODataReport(account, couch_user, **kwargs) + elif slug == cls.CASE_MANAGEMENT: + report = EnterpriseCaseManagementReport(account, couch_user, **kwargs) elif slug == cls.DATA_EXPORTS: report = EnterpriseDataExportReport(account, couch_user, **kwargs) elif slug == cls.COMMCARE_VERSION_COMPLIANCE: @@ -410,6 +415,65 @@ def rows_for_domain(self, domain_obj): return rows +class EnterpriseCaseManagementReport(EnterpriseReport): + title = gettext_lazy('Case Management') + total_description = gettext_lazy('% of Domains using Case Management') + + @property + def headers(self): + return [_('Project Space'), _('# Applications'), _('# Surveys Only'), _('# Cases Only'), _('# Mixed')] + + def rows_for_domain(self, domain_obj): + app_query = self.app_query(domain_obj.name) + app_count = app_query.count() + + if app_count == 0: + survey_only_count = 0 + case_only_count = 0 + mixed_count = 0 + else: + has_surveys = filters.nested('modules', filters.empty('modules.case_type.exact')) + has_cases = filters.nested('modules', filters.non_null('modules.case_type.exact')) + + survey_only_count = app_query.filter(filters.AND(has_surveys, filters.NOT(has_cases))).count() + case_only_count = app_query.filter(filters.AND(has_cases, filters.NOT(has_surveys))).count() + mixed_count = app_query.filter(filters.AND(has_surveys, has_cases)).count() + + return [[domain_obj.name, app_count, survey_only_count, case_only_count, mixed_count],] + + @property + def total(self): + num_domains_with_apps = 0 + num_domains_using_case_management = 0 + + for domain_obj in self.domains(): + (app_count, uses_case_management) = self.total_for_domain(domain_obj) + if app_count > 0: + if uses_case_management: + num_domains_using_case_management += 1 + num_domains_with_apps += 1 + + return _format_percentage_for_enterprise_tile(num_domains_using_case_management, num_domains_with_apps) + + def total_for_domain(self, domain_obj): + app_query = self.app_query(domain_obj.name) + app_count = app_query.count() + if app_count > 0: + has_cases = filters.nested('modules', filters.non_null('modules.case_type.exact')) + uses_case_management = app_query.filter(has_cases).count() > 0 + else: + uses_case_management = False + + return [app_count, uses_case_management] + + def app_query(self, domain): + return ( + AppES().domain(domain) + .filter(filters.term('doc_type', 'Application')) + .is_build(False) + ) + + class EnterpriseDataExportReport(EnterpriseReport): title = gettext_lazy('Data Exports') total_description = gettext_lazy('# of Exports') diff --git a/corehq/apps/enterprise/views.py b/corehq/apps/enterprise/views.py index 937a5307644c..89eb0e88dff7 100644 --- a/corehq/apps/enterprise/views.py +++ b/corehq/apps/enterprise/views.py @@ -97,7 +97,9 @@ def platform_overview(request, domain): EnterpriseReport.COMMCARE_VERSION_COMPLIANCE,)]}, {'name': _('Data Management & Export'), 'reports': [EnterpriseReport.create(slug, request.account.id, request.couch_user) - for slug in (EnterpriseReport.ODATA_FEEDS, EnterpriseReport.DATA_EXPORTS)]}, + for slug in (EnterpriseReport.ODATA_FEEDS, + EnterpriseReport.DATA_EXPORTS, + EnterpriseReport.CASE_MANAGEMENT,)]}, ], 'uses_date_range': [EnterpriseReport.FORM_SUBMISSIONS, EnterpriseReport.SMS], 'metric_type': 'Platform Overview',