Example #1
0
 def test_get_case_properties(self):
     self.assertItemsEqual(
         get_case_properties(self.domain), {
             prop
             for case in self.cases if case.domain == self.domain
             for action in case.actions
             for prop in (action.updated_known_properties.keys() +
                          action.updated_unknown_properties.keys())
         })
 def test_get_case_properties(self):
     self.assertItemsEqual(
         get_case_properties(self.domain),
         {prop
          for case in self.cases if case.domain == self.domain
          for action in case.actions
          for prop in (action.updated_known_properties.keys() +
                       action.updated_unknown_properties.keys())}
     )
Example #3
0
def get_case_properties_for_case_type(domain, case_type):
    if should_use_sql_backend(domain):
        from corehq.apps.export.models import CaseExportDataSchema
        from corehq.apps.export.const import MAIN_TABLE
        schema = CaseExportDataSchema.generate_schema_from_builds(
            domain,
            case_type,
        )
        group_schemas = [gs for gs in schema.group_schemas if gs.path == MAIN_TABLE]
        if group_schemas:
            return sorted(set([item.path[0] for item in group_schemas[0].items]))
    else:
        from corehq.apps.hqcase.dbaccessors import get_case_properties
        return get_case_properties(domain, case_type)
Example #4
0
def get_case_properties_for_case_type(domain, case_type):
    if should_use_sql_backend(domain):
        from corehq.apps.export.models import CaseExportDataSchema
        from corehq.apps.export.models.new import MAIN_TABLE
        schema = CaseExportDataSchema.generate_schema_from_builds(
            domain,
            None,
            case_type,
        )
        group_schemas = [gs for gs in schema.group_schemas if gs.path == MAIN_TABLE]
        if group_schemas:
            return sorted(set([item.path[0].name for item in group_schemas[0].items]))
    else:
        from corehq.apps.hqcase.dbaccessors import get_case_properties
        return get_case_properties(domain, case_type)
Example #5
0
def export_cases(domain,
                 cases,
                 workbook,
                 filter_group=None,
                 users=None,
                 all_groups=None,
                 process=None):
    by_user_id = dict([(user.user_id, user)
                       for user in users]) if users else {}
    by_group_id = dict([(g.get_id, g)
                        for g in all_groups]) if all_groups else {}
    if filter_group:
        owner_ids = set(by_user_id.keys())
        owner_ids.add(filter_group.get_id)

    case_static_keys = (
        "case_id",
        "username",
        "user_id",
        "owner_id",
        "owner_name",
        "type",
        "name",
        "opened_on",
        "modified_on",
        "closed",
        "closed_on",
        "domain",
        "external_id",
    )
    referral_keys = (
        "case_id",
        'referral_id',
        "type",
        "opened_on",
        "modified_on",
        "followup_on",
        "closed",
    )
    case_dynamic_keys = get_case_properties(domain)
    case_rows = []

    def render_case_attr(case, key):
        attr = getattr(case, key)
        if isinstance(attr, dict):
            return attr.get('#text', '')
        else:
            return attr
Example #6
0
def get_case_properties_for_case_type(domain, case_type):
    # todo: seems like poor boundaries for this function care about the backend
    # todo: get_case_properties just always return the right answer,
    # todo: possibly by moving this there.
    if should_use_sql_backend(domain):
        from corehq.apps.export.models import CaseExportDataSchema
        from corehq.apps.export.models.new import MAIN_TABLE
        schema = CaseExportDataSchema.generate_schema_from_builds(
            domain,
            None,
            case_type,
        )
        group_schemas = [gs for gs in schema.group_schemas if gs.path == MAIN_TABLE]
        if group_schemas:
            return sorted(set([item.path[0].name for item in group_schemas[0].items]))
    else:
        from corehq.apps.hqcase.dbaccessors import get_case_properties
        return get_case_properties(domain, case_type)
Example #7
0
def get_case_properties_for_case_type(domain, case_type):
    # todo: seems like poor boundaries for this function care about the backend
    # todo: get_case_properties just always return the right answer,
    # todo: possibly by moving this there.
    if should_use_sql_backend(domain):
        from corehq.apps.export.models import CaseExportDataSchema
        from corehq.apps.export.models.new import MAIN_TABLE
        schema = CaseExportDataSchema.generate_schema_from_builds(
            domain,
            None,
            case_type,
        )
        group_schemas = [gs for gs in schema.group_schemas if gs.path == MAIN_TABLE]
        if group_schemas:
            return sorted(set([item.path[0].name for item in group_schemas[0].items]))
    else:
        from corehq.apps.hqcase.dbaccessors import get_case_properties
        return get_case_properties(domain, case_type)
Example #8
0
def excel_fields(request, domain):
    """
    Step two of three.

    Important values that are grabbed from the POST or defined by
    the user on this page:

    named_columns:
        Passed through from last step, see that for documentation

    case_type:
        The type of case we are matching to. When creating new cases,
        this is the type they will be created as. When updating
        existing cases, this is the type that we will search for.
        If the wrong case type is used when looking up existing cases,
        we will not update them.

    create_new_cases:
        A boolean that controls whether or not the user wanted
        to create new cases for any case that doesn't have a matching
        case id in the upload.

    search_column:
        Which column of the excel file we are using to specify either
        case ids or external ids. This is, strangely, required. If
        creating new cases only you would expect these to be blank with
        the create_new_cases flag set.

    search_field:
        Either case id or external id, determines which type of
        identification we are using to match to cases.

    key_column/value_column:
        These correspond to an advanced feature allowing a user
        to modify a single case with multiple rows.
    """
    named_columns = request.POST['named_columns']
    case_type = request.POST['case_type']
    try:
        search_column = request.POST['search_column']
    except MultiValueDictKeyError:
        # this is only true if your configuration is messed up in an irreparable way
        messages.error(request, _('It looks like you may have accessed this page from a stale page. '
                                  'Please start over.'))
        return _spreadsheet_expired(request, domain)

    search_field = request.POST['search_field']
    create_new_cases = request.POST.get('create_new_cases') == 'on'
    key_value_columns = request.POST.get('key_value_columns') == 'on'
    key_column = ''
    value_column = ''

    download_ref = DownloadBase.get(request.session.get(EXCEL_SESSION_ID))

    spreadsheet = importer_util.get_spreadsheet(download_ref, named_columns)
    if not spreadsheet:
        return _spreadsheet_expired(request, domain)

    columns = spreadsheet.get_header_columns()

    if key_value_columns:
        key_column = request.POST['key_column']
        value_column = request.POST['value_column']

        excel_fields = []
        key_column_index = columns.index(key_column)

        # if key/value columns were specified, get all the unique keys listed
        if key_column_index:
            excel_fields = spreadsheet.get_unique_column_values(key_column_index)

        # concatenate unique key fields with the rest of the columns
        excel_fields = columns + excel_fields
        # remove key/value column names from list
        excel_fields.remove(key_column)
        if value_column in excel_fields:
            excel_fields.remove(value_column)
    else:
        excel_fields = columns

    case_fields = get_case_properties(domain, case_type)

    # hide search column and matching case fields from the update list
    try:
        excel_fields.remove(search_column)
    except:
        pass

    try:
        case_fields.remove(search_field)
    except:
        pass

    # we can't actually update this so don't show it
    try:
        case_fields.remove('type')
    except:
        pass

    return render(
        request,
        "importer/excel_fields.html", {
            'named_columns': named_columns,
            'case_type': case_type,
            'search_column': search_column,
            'search_field': search_field,
            'create_new_cases': create_new_cases,
            'key_column': key_column,
            'value_column': value_column,
            'columns': columns,
            'excel_fields': excel_fields,
            'case_fields': case_fields,
            'domain': domain,
            'report': {
                'name': 'Import: Match columns to fields'
            },
            'slug': base.ImportCases.slug
        }
    )
Example #9
0
def export_cases(domain, cases, workbook, filter_group=None, users=None, all_groups=None, process=None):
    by_user_id = dict([(user.user_id, user) for user in users]) if users else {}
    by_group_id = dict([(g.get_id, g) for g in all_groups]) if all_groups else {}
    if filter_group:
        owner_ids = set(by_user_id.keys())
        owner_ids.add(filter_group.get_id)

    case_static_keys = (
        "case_id",
        "username",
        "user_id",
        "owner_id",
        "owner_name",
        "type",
        "name",
        "opened_on",
        "modified_on",
        "closed",
        "closed_on",
        "domain",
        "external_id",
    )
    referral_keys = (
        "case_id",
        'referral_id',
        "type",
        "opened_on",
        "modified_on",
        "followup_on",
        "closed",
    )
    case_dynamic_keys = get_case_properties(domain)
    case_rows = []

    def render_case_attr(case, key):
        attr = getattr(case, key)
        if isinstance (attr, dict):
            return attr.get('#text', '')
        else:
            return attr

    num_cases = len(cases)

    def get_matching_owner(case):
        if by_user_id:
            if case.user_id in by_user_id:
                return case.user_id
            elif get_owner_id(case) in by_user_id:
                return get_owner_id(case)
        else:
            return get_owner_id(case)

    def might_be_relevant(case):
        return not filter_group or get_owner_id(case) in owner_ids

    for i, case in enumerate(cases):
        if process:
            DownloadBase.set_progress(process, i, num_cases)
        if might_be_relevant(case):
            matching_owner = get_matching_owner(case)
            case_row = {'dynamic_properties': {}}
            for key in case_static_keys:
                if key == 'username':
                    try:
                        case_row[key] = by_user_id[matching_owner].raw_username
                    except (TypeError, KeyError):
                        case_row[key] = ''
                elif key == 'owner_name':
                    if users and case.owner_id in by_user_id:
                        case_row[key] = by_user_id[case.owner_id].full_name
                    elif case.owner_id in by_group_id:
                        case_row[key] = by_group_id[case.owner_id].name
                    else:
                        case_row[key] = ''
                else:
                    case_row[key] = getattr(case, key)
            for key in case.dynamic_properties():
                case_row['dynamic_properties'][key] = render_case_attr(case, key)
            case_rows.append(case_row)

    def format_dynamic_key(key):
        return "d.{key}".format(key=key)

    def tidy_up_case_row(case_row):
        row = dict([(key, case_row[key]) for key in case_static_keys])
        for key in case_dynamic_keys:
            row[format_dynamic_key(key)] = case_row['dynamic_properties'].get(key, workbook.undefined)
        return row

    case_headers = list(case_static_keys)
    case_headers.extend([format_dynamic_key(key) for key in case_dynamic_keys])
    workbook.open("Cases", case_headers)
    for case_row in case_rows:
        workbook.write_row("Cases", tidy_up_case_row(case_row))

    return workbook
Example #10
0
def excel_fields(request, domain):
    """
    Step two of three.

    Important values that are grabbed from the POST or defined by
    the user on this page:

    named_columns:
        Passed through from last step, see that for documentation

    case_type:
        The type of case we are matching to. When creating new cases,
        this is the type they will be created as. When updating
        existing cases, this is the type that we will search for.
        If the wrong case type is used when looking up existing cases,
        we will not update them.

    create_new_cases:
        A boolean that controls whether or not the user wanted
        to create new cases for any case that doesn't have a matching
        case id in the upload.

    search_column:
        Which column of the excel file we are using to specify either
        case ids or external ids. This is, strangely, required. If
        creating new cases only you would expect these to be blank with
        the create_new_cases flag set.

    search_field:
        Either case id or external id, determines which type of
        identification we are using to match to cases.

    key_column/value_column:
        These correspond to an advanced feature allowing a user
        to modify a single case with multiple rows.
    """
    named_columns = request.POST['named_columns']
    case_type = request.POST['case_type']
    try:
        search_column = request.POST['search_column']
    except MultiValueDictKeyError:
        # this is only true if your configuration is messed up in an irreparable way
        messages.error(request, _('It looks like you may have accessed this page from a stale page. '
                                  'Please start over.'))
        return _spreadsheet_expired(request, domain)

    search_field = request.POST['search_field']
    create_new_cases = request.POST.get('create_new_cases') == 'on'
    key_value_columns = request.POST.get('key_value_columns') == 'on'
    key_column = ''
    value_column = ''

    download_ref = DownloadBase.get(request.session.get(EXCEL_SESSION_ID))

    spreadsheet = importer_util.get_spreadsheet(download_ref, named_columns)
    if not spreadsheet:
        return _spreadsheet_expired(request, domain)

    columns = spreadsheet.get_header_columns()

    if key_value_columns:
        key_column = request.POST['key_column']
        value_column = request.POST['value_column']

        excel_fields = []
        key_column_index = columns.index(key_column)

        # if key/value columns were specified, get all the unique keys listed
        if key_column_index:
            excel_fields = spreadsheet.get_unique_column_values(key_column_index)

        # concatenate unique key fields with the rest of the columns
        excel_fields = columns + excel_fields
        # remove key/value column names from list
        excel_fields.remove(key_column)
        if value_column in excel_fields:
            excel_fields.remove(value_column)
    else:
        excel_fields = columns

    case_fields = get_case_properties(domain, case_type)

    # hide search column and matching case fields from the update list
    try:
        excel_fields.remove(search_column)
    except:
        pass

    try:
        case_fields.remove(search_field)
    except:
        pass

    # we can't actually update this so don't show it
    try:
        case_fields.remove('type')
    except:
        pass

    return render(
        request,
        "importer/excel_fields.html", {
            'named_columns': named_columns,
            'case_type': case_type,
            'search_column': search_column,
            'search_field': search_field,
            'create_new_cases': create_new_cases,
            'key_column': key_column,
            'value_column': value_column,
            'columns': columns,
            'excel_fields': excel_fields,
            'case_fields': case_fields,
            'domain': domain,
            'report': {
                'name': 'Import: Match columns to fields'
            },
            'slug': base.ImportCases.slug
        }
    )