def test_get_case_types(self):
        self._send_case_to_es(case_type='t1')
        self._send_case_to_es(case_type='t2')
        self._send_case_to_es(case_type='t3', closed_on=datetime.utcnow())
        self._send_case_to_es(domain='other', case_type='t4')

        case_types = get_case_types_for_domain_es(self.domain)
        self.assertEqual(case_types, {'t1', 't2', 't3'})
        self.assertEqual({'t4'}, get_case_types_for_domain_es('other'))
        self.assertEqual(set(), get_case_types_for_domain_es('none'))
    def test_get_case_types(self):
        self._send_case_to_es(case_type='t1')
        self._send_case_to_es(case_type='t2')
        self._send_case_to_es(case_type='t3', closed_on=datetime.utcnow())
        self._send_case_to_es(domain='other', case_type='t4')

        case_types = get_case_types_for_domain_es(self.domain)
        self.assertEqual(case_types, {'t1', 't2', 't3'})
        self.assertEqual({'t4'}, get_case_types_for_domain_es('other'))
        self.assertEqual(set(), get_case_types_for_domain_es('none'))
    def test_get_case_types_caching(self):
        self._send_case_to_es(case_type='t1')

        self.assertEqual({'t1'}, get_case_types_for_domain_es(self.domain))

        self._send_case_to_es(case_type='t2')
        # cached response
        self.assertEqual({'t1'}, get_case_types_for_domain_es(self.domain))

        # simulate a save
        from casexml.apps.case.signals import case_post_save
        case_post_save.send(self, case=CommCareCase(domain=self.domain, type='t2'))

        self.assertEqual({'t1', 't2'}, get_case_types_for_domain_es(self.domain))
Exemple #4
0
    def test_get_case_types_caching(self):
        self._send_case_to_es(case_type='t1')

        self.assertEqual({'t1'}, get_case_types_for_domain_es(self.domain))

        self._send_case_to_es(case_type='t2')
        # cached response
        self.assertEqual({'t1'}, get_case_types_for_domain_es(self.domain))

        # simulate a save
        from casexml.apps.case.signals import case_post_save
        case_post_save.send(self, case=CommCareCase(domain=self.domain, type='t2'))

        self.assertEqual({'t1', 't2'}, get_case_types_for_domain_es(self.domain))
Exemple #5
0
 def case_types(self):
     """
     :return: Set of all case types for the domain excluding the CallCenter case type.
     """
     case_types = get_case_types_for_domain_es(self.domain)
     case_types = case_types - {self.cc_case_type}
     return case_types
Exemple #6
0
 def case_types(self):
     """
     :return: Set of all case types for the domain excluding the CallCenter case type.
     """
     case_types = get_case_types_for_domain_es(self.domain)
     case_types = case_types - {self.cc_case_type}
     return case_types
Exemple #7
0
 def set_case_type_choices(self, initial):
     case_types = [''] + list(get_case_types_for_domain_es(self.domain))
     if initial and initial not in case_types:
         # Include the deleted case type in the list of choices so that
         # we always allow proper display and edit of rules
         case_types.append(initial)
     case_types.sort()
     self.fields['case_type'].choices = ((case_type, case_type)
                                         for case_type in case_types)
Exemple #8
0
 def set_case_type_choices(self, initial):
     case_types = [''] + list(get_case_types_for_domain_es(self.domain))
     if initial and initial not in case_types:
         # Include the deleted case type in the list of choices so that
         # we always allow proper display and edit of rules
         case_types.append(initial)
     case_types.sort()
     self.fields['case_type'].choices = (
         (case_type, case_type) for case_type in case_types
     )
Exemple #9
0
def get_case_type_to_properties(domain):
    case_type_to_properties = {}
    case_types = get_case_types_for_domain_es(domain)
    for case_type in case_types:
        case_type_to_properties[case_type] = []
        case_export_schema = CaseExportDataSchema.generate_schema_from_builds(domain, None, case_type)
        for export_group_schema in case_export_schema.group_schemas[0].items:
            cleaned_case_property = export_group_schema.label.replace('_', '')
            case_type_to_properties[case_type].append(cleaned_case_property)
    return case_type_to_properties
Exemple #10
0
    def obj_get_list(self, bundle, **kwargs):
        domain = kwargs['domain']
        couch_user = CouchUser.from_django_user(bundle.request.user)
        if not domain_has_privilege(domain, privileges.ZAPIER_INTEGRATION) or not couch_user.is_member_of(domain):
            raise ImmediateHttpResponse(
                HttpForbidden('You are not allowed to get list of case types for this domain')
            )

        case_types = get_case_types_for_domain_es(domain)
        results = [CaseType(case_type=case_type) for case_type in case_types]
        return results
Exemple #11
0
    def obj_get_list(self, bundle, **kwargs):
        domain = kwargs['domain']
        couch_user = CouchUser.from_django_user(bundle.request.user)
        if not domain_has_privilege(domain, privileges.ZAPIER_INTEGRATION) or not couch_user.is_member_of(domain):
            raise ImmediateHttpResponse(
                HttpForbidden('You are not allowed to get list of case types for this domain')
            )

        case_types = get_case_types_for_domain_es(domain)
        results = [CaseType(case_type=case_type) for case_type in case_types]
        return results
Exemple #12
0
 def get(self, request, domain):
     data = {
         '@odata.context':
         absolute_reverse('odata_meta', args=[domain]),
         'value': [{
             'name': case_type,
             'kind': 'EntitySet',
             'url': case_type,
         } for case_type in get_case_types_for_domain_es(domain)]
     }
     return add_odata_headers(JsonResponse(data))
Exemple #13
0
def _get_case_size_stats(domain, sample_size, use_case_search):
    total_bytes = 0
    total_cases = 0
    index_class = CaseSearchES if use_case_search else CaseES
    for case_type in get_case_types_for_domain_es(domain, use_case_search):
        query = (index_class().domain(domain).case_type(case_type).size(
            sample_size))
        num_cases, avg_size = _get_totals_for_query(query)
        total_bytes += num_cases * avg_size
        total_cases += num_cases
    return total_cases, total_bytes
Exemple #14
0
 def get(self, request, domain):
     data = {
         '@odata.context': absolute_reverse('odata_meta', args=[domain]),
         'value': [
             {
                 'name': case_type,
                 'kind': 'EntitySet',
                 'url': case_type,
             }
             for case_type in get_case_types_for_domain_es(domain)
         ]
     }
     return add_odata_headers(JsonResponse(data))
Exemple #15
0
def get_case_type_to_properties(domain):
    case_type_to_properties = defaultdict(list)
    case_types = get_case_types_for_domain_es(domain)
    for case_type in case_types:
        if not case_type:
            # TODO - understand why a case can have a blank case type and handle appropriately
            continue
        case_export_schema = (
            get_latest_case_export_schema(domain, case_type)
            or CaseExportDataSchema.generate_schema_from_builds(domain, None, case_type)
        )
        for export_group_schema in case_export_schema.group_schemas[0].items:
            cleaned_case_property = export_group_schema.label.replace('_', '')
            case_type_to_properties[case_type].append(cleaned_case_property)
    return dict(case_type_to_properties)
Exemple #16
0
def get_case_type_to_properties(domain):
    case_type_to_properties = defaultdict(list)
    case_types = get_case_types_for_domain_es(domain)
    for case_type in case_types:
        if not case_type:
            # TODO - understand why a case can have a blank case type and handle appropriately
            continue
        case_export_schema = (get_latest_case_export_schema(domain, case_type)
                              or
                              CaseExportDataSchema.generate_schema_from_builds(
                                  domain, None, case_type))
        for export_group_schema in case_export_schema.group_schemas[0].items:
            cleaned_case_property = export_group_schema.label.replace('_', '')
            case_type_to_properties[case_type].append(cleaned_case_property)
    return dict(case_type_to_properties)
Exemple #17
0
    def _get_cases_for_apps(self, apps_by_type, as_dict=True):
        used_case_types = set()
        case_types_by_app = collections.defaultdict(list)
        for app_type, apps in apps_by_type.items():
            for app_choice in apps:
                if not app_choice.id == self.UNKNOWN_SOURCE:
                    app = get_app(self.domain, app_choice.id)
                    case_types = []
                    if hasattr(app, 'modules'):
                        # Add regular case types
                        case_types = set([
                            module.case_type
                            for module in app.modules if module.case_type
                        ])

                        # Add user case if any module uses it
                        if any([module.uses_usercase() for module in app.modules]):
                            case_types.add(USERCASE_TYPE)

                        used_case_types = used_case_types.union(case_types)
                        case_types = [RMIDataChoice(
                            id=c,
                            text=c,
                            data=app_choice.data
                        ) for c in case_types]
                        if as_dict:
                            case_types = [c._asdict() for c in case_types]
                    case_types_by_app[app_choice.id] = case_types

        all_case_types = get_case_types_for_domain_es(self.domain)
        unknown_case_types = all_case_types.difference(used_case_types)
        unknown_case_types = [RMIDataChoice(
            id=c,
            text=c,
            data={
                'unknown': True,
            }
        ) for c in unknown_case_types]
        if as_dict:
            unknown_case_types = [c._asdict() for c in unknown_case_types]
        case_types_by_app[self.UNKNOWN_SOURCE] = unknown_case_types

        return case_types_by_app
Exemple #18
0
    def _get_cases_for_apps(self, apps_by_type, as_dict=True):
        used_case_types = set()
        case_types_by_app = collections.defaultdict(list)
        for app_type, apps in apps_by_type.items():
            for app_choice in apps:
                if not app_choice.id == self.UNKNOWN_SOURCE:
                    app = get_app(self.domain, app_choice.id)
                    case_types = []
                    if hasattr(app, 'modules'):
                        # Add regular case types
                        case_types = set([
                            module.case_type
                            for module in app.modules if module.case_type
                        ])

                        # Add user case if any module uses it
                        if any([module.uses_usercase() for module in app.modules]):
                            case_types.add(USERCASE_TYPE)

                        used_case_types = used_case_types.union(case_types)
                        case_types = [RMIDataChoice(
                            id=c,
                            text=c,
                            data=app_choice.data
                        ) for c in case_types]
                        if as_dict:
                            case_types = [c._asdict() for c in case_types]
                    case_types_by_app[app_choice.id] = case_types

        all_case_types = get_case_types_for_domain_es(self.domain)
        unknown_case_types = all_case_types.difference(used_case_types)
        unknown_case_types = [RMIDataChoice(
            id=c,
            text=c,
            data={
                'unknown': True,
            }
        ) for c in unknown_case_types]
        if as_dict:
            unknown_case_types = [c._asdict() for c in unknown_case_types]
        case_types_by_app[self.UNKNOWN_SOURCE] = unknown_case_types

        return case_types_by_app
Exemple #19
0
 def options(self):
     case_types = sorted(get_case_types_for_domain_es(self.domain))
     return [(case, "%s" % case) for case in case_types
             if case != USER_LOCATION_OWNER_MAP_TYPE]
Exemple #20
0
 def case_type_choices(self):
     return [(t, t) for t in get_case_types_for_domain_es(self.domain)]
Exemple #21
0
 def get(self, request, domain):
     return JsonResponse({
         'existing_case_types':
         list(get_case_types_for_domain_es(domain))
     })
Exemple #22
0
def _process_file_and_get_upload(uploaded_file_handle,
                                 request,
                                 domain,
                                 max_columns=None):
    extension = os.path.splitext(
        uploaded_file_handle.name)[1][1:].strip().lower()

    # NOTE: We may not always be able to reference files from subsequent
    # views if your worker changes, so we have to store it elsewhere
    # using the soil framework.

    if extension not in valid_extensions:
        raise SpreadsheetFileExtError(
            'The file you chose could not be processed. '
            'Please check that it is saved as a Microsoft '
            'Excel file.')

    # stash content in the default storage for subsequent views
    case_upload = CaseUpload.create(uploaded_file_handle,
                                    filename=uploaded_file_handle.name,
                                    domain=domain)

    request.session[EXCEL_SESSION_ID] = case_upload.upload_id

    case_upload.check_file()
    invalid_column_names = set()
    with case_upload.get_spreadsheet() as spreadsheet:
        columns = spreadsheet.get_header_columns()
        validate_column_names(columns, invalid_column_names)
        row_count = spreadsheet.max_row

    if invalid_column_names:
        error_message = format_html(
            _("Column names must be <a target='_blank' href='https://www.w3schools.com/xml/xml_elements.asp'>"
              "valid XML elements</a> and cannot start with a number or contain spaces or most special characters."
              " Please update the following: {}.").format(
                  ', '.join(invalid_column_names)))
        raise ImporterRawError(error_message)

    if row_count == 0:
        raise ImporterError(
            'Your spreadsheet is empty. Please try again with a different spreadsheet.'
        )

    if max_columns is not None and len(columns) > max_columns:
        raise ImporterError('Your spreadsheet has too many columns. '
                            'A maximum of %(max_columns)s is supported.' %
                            {'max_columns': MAX_CASE_IMPORTER_COLUMNS})

    case_types_from_apps = sorted(get_case_types_from_apps(domain))
    unrecognized_case_types = sorted([
        t for t in get_case_types_for_domain_es(domain)
        if t not in case_types_from_apps
    ])

    if len(case_types_from_apps) == 0 and len(unrecognized_case_types) == 0:
        raise ImporterError(
            'No cases have been submitted to this domain and there are no '
            'applications yet. You cannot import case details from an Excel '
            'file until you have existing cases or applications.')

    context = {
        'columns': columns,
        'unrecognized_case_types': unrecognized_case_types,
        'case_types_from_apps': case_types_from_apps,
        'domain': domain,
        'slug': base.ImportCases.slug,
    }
    return case_upload, context
Exemple #23
0
 def options(self):
     case_types = get_case_types_for_domain_es(self.domain)
     return [(case, "%s" % case) for case in case_types
             if case != USER_LOCATION_OWNER_MAP_TYPE]
Exemple #24
0
 def case_type_choices(self):
     return [(t, t) for t in get_case_types_for_domain_es(self.domain)]
 def available_case_types(self):
     return sorted(get_case_types_for_domain_es(self.domain))
 def test_get_case_types_case_sensitive(self):
     self._send_case_to_es(case_type='child')
     self._send_case_to_es(case_type='Child')
     case_types = get_case_types_for_domain_es(self.domain)
     self.assertEqual(case_types, {'child', 'Child'})
 def test_get_case_types_case_sensitive(self):
     self._send_case_to_es(case_type='child')
     self._send_case_to_es(case_type='Child')
     case_types = get_case_types_for_domain_es(self.domain)
     self.assertEqual(case_types, {'child', 'Child'})
Exemple #28
0
def excel_config(request, domain):
    """
    Step one of three.

    This is the initial post when the user uploads the Excel file

    """
    if request.method != 'POST':
        return HttpResponseRedirect(base.ImportCases.get_url(domain=domain))

    if not request.FILES:
        return render_error(request, domain, 'Please choose an Excel file to import.')

    uploaded_file_handle = request.FILES['file']

    extension = os.path.splitext(uploaded_file_handle.name)[1][1:].strip().lower()

    # NOTE: We may not always be able to reference files from subsequent
    # views if your worker changes, so we have to store it elsewhere
    # using the soil framework.

    if extension not in importer_util.ALLOWED_EXTENSIONS:
        return render_error(request, domain, _(
            'The file you chose could not be processed. '
            'Please check that it is saved as a Microsoft '
            'Excel file.'
        ))

    # stash content in the default storage for subsequent views
    case_upload = CaseUpload.create(uploaded_file_handle,
                                    filename=uploaded_file_handle.name,
                                    domain=domain)

    request.session[EXCEL_SESSION_ID] = case_upload.upload_id
    try:
        case_upload.check_file()
    except ImporterError as e:
        return render_error(request, domain, get_importer_error_message(e))
    except SpreadsheetFileExtError:
        return render_error(request, domain, _("Please upload file with extension .xls or .xlsx"))
    invalid_column_names = set()
    with case_upload.get_spreadsheet() as spreadsheet:
        columns = spreadsheet.get_header_columns()
        validate_column_names(columns, invalid_column_names)
        row_count = spreadsheet.max_row

    if invalid_column_names:
        error_message = format_html(
            _("Column names must be <a target='_blank' href='https://www.w3schools.com/xml/xml_elements.asp'>"
              "valid XML elements</a> and cannot start with a number or contain spaces or most special characters."
              " Please update the following: {}.").format(
                ', '.join(invalid_column_names)))
        return render_error(request, domain, error_message)

    if row_count == 0:
        return render_error(request, domain, _(
            'Your spreadsheet is empty. Please try again with a different spreadsheet.'
        ))

    if len(columns) > MAX_CASE_IMPORTER_COLUMNS:
        return render_error(request, domain, _(
            'Your spreadsheet has too many columns. '
            'A maximum of %(max_columns)s is supported.'
        ) % {'max_columns': MAX_CASE_IMPORTER_COLUMNS})

    case_types_from_apps = sorted(get_case_types_from_apps(domain))
    unrecognized_case_types = sorted([t for t in get_case_types_for_domain_es(domain)
                                      if t not in case_types_from_apps])

    if len(case_types_from_apps) == 0 and len(unrecognized_case_types) == 0:
        return render_error(request, domain, _(
            'No cases have been submitted to this domain and there are no '
            'applications yet. You cannot import case details from an Excel '
            'file until you have existing cases or applications.'
        ))

    context = {
        'columns': columns,
        'unrecognized_case_types': unrecognized_case_types,
        'case_types_from_apps': case_types_from_apps,
        'domain': domain,
        'slug': base.ImportCases.slug,
    }
    context.update(_case_importer_breadcrumb_context(_('Case Options'), domain))
    return render(request, "case_importer/excel_config.html", context)
Exemple #29
0
 def get(self, request, domain):
     return JsonResponse({
         'existing_case_types': list(get_case_types_for_domain_es(domain))
     })
Exemple #30
0
def excel_config(request, domain):
    """
    Step one of three.

    This is the initial post when the user uploads the Excel file

    """
    if request.method != 'POST':
        return HttpResponseRedirect(base.ImportCases.get_url(domain=domain))

    if not request.FILES:
        return render_error(request, domain,
                            'Please choose an Excel file to import.')

    uploaded_file_handle = request.FILES['file']

    extension = os.path.splitext(
        uploaded_file_handle.name)[1][1:].strip().lower()

    # NOTE: We may not always be able to reference files from subsequent
    # views if your worker changes, so we have to store it elsewhere
    # using the soil framework.

    if extension not in importer_util.ALLOWED_EXTENSIONS:
        return render_error(
            request, domain,
            _('The file you chose could not be processed. '
              'Please check that it is saved as a Microsoft '
              'Excel file.'))

    # stash content in the default storage for subsequent views
    case_upload = CaseUpload.create(uploaded_file_handle,
                                    filename=uploaded_file_handle.name,
                                    domain=domain)

    request.session[EXCEL_SESSION_ID] = case_upload.upload_id
    try:
        case_upload.check_file()
    except ImporterError as e:
        return render_error(request, domain, get_importer_error_message(e))
    except SpreadsheetFileExtError:
        return render_error(
            request, domain,
            _("Please upload file with extension .xls or .xlsx"))
    invalid_column_names = set()
    with case_upload.get_spreadsheet() as spreadsheet:
        columns = spreadsheet.get_header_columns()
        validate_column_names(columns, invalid_column_names)
        row_count = spreadsheet.max_row

    if invalid_column_names:
        error_message = format_html(
            _("Column names must be <a target='_blank' href='https://www.w3schools.com/xml/xml_elements.asp'>"
              "valid XML elements</a> and cannot start with a number or contain spaces or most special characters."
              " Please update the following: {}.").format(
                  ', '.join(invalid_column_names)))
        return render_error(request, domain, error_message)

    if row_count == 0:
        return render_error(
            request, domain,
            _('Your spreadsheet is empty. Please try again with a different spreadsheet.'
              ))

    if len(columns) > MAX_CASE_IMPORTER_COLUMNS:
        return render_error(
            request, domain,
            _('Your spreadsheet has too many columns. '
              'A maximum of %(max_columns)s is supported.') %
            {'max_columns': MAX_CASE_IMPORTER_COLUMNS})

    case_types_from_apps = sorted(get_case_types_from_apps(domain))
    unrecognized_case_types = sorted([
        t for t in get_case_types_for_domain_es(domain)
        if t not in case_types_from_apps
    ])

    if len(case_types_from_apps) == 0 and len(unrecognized_case_types) == 0:
        return render_error(
            request, domain,
            _('No cases have been submitted to this domain and there are no '
              'applications yet. You cannot import case details from an Excel '
              'file until you have existing cases or applications.'))

    context = {
        'columns': columns,
        'unrecognized_case_types': unrecognized_case_types,
        'case_types_from_apps': case_types_from_apps,
        'domain': domain,
        'slug': base.ImportCases.slug,
    }
    context.update(_case_importer_breadcrumb_context(_('Case Options'),
                                                     domain))
    request.use_select2_v4 = True
    return render(request, "case_importer/excel_config.html", context)
Exemple #31
0
 def obj_get_list(self, bundle, **kwargs):
     domain = kwargs['domain']
     case_types = get_case_types_for_domain_es(domain)
     results = [CaseType(case_type=case_type) for case_type in case_types]
     return results
Exemple #32
0
def excel_config(request, domain):
    """
    Step one of three.

    This is the initial post when the user uploads the excel file

    """
    if request.method != 'POST':
        return HttpResponseRedirect(base.ImportCases.get_url(domain=domain))

    if not request.FILES:
        return render_error(request, domain,
                            'Please choose an Excel file to import.')

    uploaded_file_handle = request.FILES['file']

    extension = os.path.splitext(
        uploaded_file_handle.name)[1][1:].strip().lower()

    # NOTE: We may not always be able to reference files from subsequent
    # views if your worker changes, so we have to store it elsewhere
    # using the soil framework.

    if extension not in importer_util.ALLOWED_EXTENSIONS:
        return render_error(
            request, domain,
            _('The file you chose could not be processed. '
              'Please check that it is saved as a Microsoft '
              'Excel file.'))

    # stash content in the default storage for subsequent views
    case_upload = CaseUpload.create(uploaded_file_handle,
                                    filename=uploaded_file_handle.name)

    request.session[EXCEL_SESSION_ID] = case_upload.upload_id
    try:
        case_upload.check_file()
    except ImporterError as e:
        return render_error(request, domain, get_importer_error_message(e))
    except SpreadsheetFileExtError:
        return render_error(
            request, domain,
            _("Please upload file with extension .xls or .xlsx"))
    with case_upload.get_spreadsheet() as spreadsheet:
        columns = spreadsheet.get_header_columns()
        row_count = spreadsheet.max_row

    if row_count == 0:
        return render_error(
            request, domain,
            _('Your spreadsheet is empty. Please try again with a different spreadsheet.'
              ))

    if len(columns) > MAX_CASE_IMPORTER_COLUMNS:
        return render_error(
            request, domain,
            _('Your spreadsheet has too many columns. '
              'A maximum of %(max_columns)s is supported.') %
            {'max_columns': MAX_CASE_IMPORTER_COLUMNS})

    case_types_from_apps = get_case_types_from_apps(domain)
    unrecognized_case_types = [
        t for t in get_case_types_for_domain_es(domain)
        if t not in case_types_from_apps
    ]

    if len(case_types_from_apps) == 0 and len(unrecognized_case_types) == 0:
        return render_error(
            request, domain,
            _('No cases have been submitted to this domain and there are no '
              'applications yet. You cannot import case details from an Excel '
              'file until you have existing cases or applications.'))

    return render(
        request, "case_importer/excel_config.html", {
            'columns': columns,
            'unrecognized_case_types': unrecognized_case_types,
            'case_types_from_apps': case_types_from_apps,
            'domain': domain,
            'report': {
                'name': 'Import: Configuration'
            },
            'slug': base.ImportCases.slug
        })