def get_case_hierarchy(case, type_info):
    def get_children(case, referenced_type=None, seen=None):
        seen = seen or set()

        ignore_types = type_info.get(case.type, {}).get("ignore_relationship_types", [])
        if referenced_type and referenced_type in ignore_types:
            return None

        seen.add(case.case_id)
        children = [
            get_children(i.referenced_case, i.referenced_type, seen) for i in case.reverse_indices
            if i.referenced_id not in seen
        ]

        children = [c for c in children if c is not None]

        # non-first-level descendants
        descendant_types = []
        for c in children:
            descendant_types.extend(c['descendant_types'])
        descendant_types = list(set(descendant_types))

        children = sorted(children, key=partial(sortkey, type_info=type_info))
       
        # set parent_case_id used by flat display
        for c in children:
            if not hasattr(c['case'], 'treetable_parent_node_id'):
                c['case'].treetable_parent_node_id = case.case_id
      
        child_cases = []
        for c in children:
            child_cases.extend(c['case_list'])

        return {
            'case': case,
            'child_cases': children,
            'descendant_types': list(set(descendant_types + [c['case'].type for c in children])),
            'case_list': [case] + child_cases
        }

    return get_children(case)
dataset/ETHPy150Open dimagi/commcare-hq/corehq/ex-submodules/casexml/apps/case/templatetags/case_tags.py/get_case_hierarchy/original