def get_session_schema(form): """Get form session schema definition """ from corehq.apps.app_manager.suite_xml.sections.entries import EntriesHelper structure = {} datums = EntriesHelper( form.get_app()).get_datums_meta_for_form_generic(form) datums = [ d for d in datums if not d.is_new_case_id and d.case_type and d.requires_selection ] if len(datums): session_var = datums[-1].datum.id structure[session_var] = { "reference": { "source": "casedb", "subset": "case", "key": "@case_id", }, } return { "id": "commcaresession", "uri": "jr://instance/session", "name": "Session", "path": "/session/data", "structure": structure, }
def __init__(self, suite, app, modules, build_profile_id=None): from corehq.apps.app_manager.suite_xml.sections.entries import EntriesHelper self.suite = suite self.app = app self.modules = modules self.build_profile_id = build_profile_id self.entries_helper = EntriesHelper(app, modules, build_profile_id=self.build_profile_id)
def case_session_variable_name(self): session_var = 'case_id' datums = EntriesHelper(self.app).get_datums_meta_for_form_generic(self.form) datums = [datum for datum in datums if datum.case_type == self.case_type] if len(datums) == 1: session_var = datums[0].datum.id return session_var
def get_cloudcare_session_data(domain_name, form, couch_user): from corehq.apps.app_manager.suite_xml.sections.entries import EntriesHelper datums = EntriesHelper.get_new_case_id_datums_meta(form) session_data = {datum.datum.id: uuid.uuid4().hex for datum in datums} if couch_user.doc_type == 'CommCareUser': # smsforms.app.start_session could pass a CommCareCase try: extra_datums = EntriesHelper.get_extra_case_id_datums(form) except SuiteError as err: _assert = soft_assert(['nhooper_at_dimagi_dot_com'.replace('_at_', '@').replace('_dot_', '.')]) _assert(False, 'Domain "%s": %s' % (domain_name, err)) else: if EntriesHelper.any_usercase_datums(extra_datums): usercase_id = couch_user.get_usercase_id() if usercase_id: session_data[USERCASE_ID] = usercase_id return session_data
def get_form_datums(request, domain, app_id): from corehq.apps.app_manager.suite_xml.sections.entries import EntriesHelper form_id = request.GET.get('form_id') app = get_app(domain, app_id) form = app.get_form(form_id) def make_datum(datum): return {'name': datum.datum.id, 'case_type': datum.case_type} helper = EntriesHelper(app) datums = [] root_module = form.get_module().root_module if root_module: datums.extend([ make_datum(datum) for datum in helper.get_datums_meta_for_form_generic(root_module.get_form(0)) if datum.requires_selection ]) datums.extend([ make_datum(datum) for datum in helper.get_datums_meta_for_form_generic(form) if datum.requires_selection ]) return json_response(datums)
def get_session_schema(form): """Get form session schema definition """ from corehq.apps.app_manager.suite_xml.sections.entries import EntriesHelper app = form.get_app() structure = {} datums = EntriesHelper(app).get_datums_meta_for_form_generic(form) datums = [ d for d in datums if not d.is_new_case_id and d.case_type and d.requires_selection ] if len(datums): session_var = datums[-1].datum.id structure["data"] = { "merge": True, "structure": { session_var: { "reference": { "hashtag": "#case", "source": "casedb", "subset": "case", "key": "@case_id", }, }, }, } if is_usercase_in_use( app.domain) and toggles.USER_PROPERTY_EASY_REFS.enabled( app.domain): structure["context"] = { "merge": True, "structure": { "userid": { "reference": { "hashtag": "#user", "source": "casedb", "subset": USERCASE_TYPE, "subset_key": "@case_type", "subset_filter": True, "key": "hq_user_id", }, }, }, } return { "id": "commcaresession", "uri": "jr://instance/session", "name": "Session", "path": "/session", "structure": structure, }
def get_session_schema(form): """Get form session schema definition """ from corehq.apps.app_manager.suite_xml.sections.entries import EntriesHelper structure = {} datums = EntriesHelper( form.get_app()).get_datums_meta_for_form_generic(form) for datum in datums: if not datum.is_new_case_id and datum.case_type and datum.datum.id == 'case_id': structure['case_id'] = { "reference": { "source": "casedb", "subset": "case", "key": "@case_id", }, } return { "id": "commcaresession", "uri": "jr://instance/session", "name": "Session", "path": "/session/data", "structure": structure, }
def filter_cases(request, domain, app_id, module_id, parent_id=None): app = Application.get(app_id) module = app.get_module(module_id) auth_cookie = request.COOKIES.get('sessionid') requires_parent_cases = string_to_boolean( request.GET.get('requires_parent_cases', 'false')) xpath = EntriesHelper.get_filter_xpath(module) instances = get_instances_for_module(app, module, additional_xpaths=[xpath]) extra_instances = [{'id': inst.id, 'src': inst.src} for inst in instances] use_formplayer = toggles.USE_FORMPLAYER.enabled(domain) accessor = CaseAccessors(domain) # touchforms doesn't like this to be escaped xpath = HTMLParser.HTMLParser().unescape(xpath) case_type = module.case_type if xpath or should_use_sql_backend(domain): # if we need to do a custom filter, send it to touchforms for processing additional_filters = { "properties/case_type": case_type, "footprint": True } helper = BaseSessionDataHelper(domain, request.couch_user) result = helper.filter_cases(xpath, additional_filters, DjangoAuth(auth_cookie), extra_instances=extra_instances, use_formplayer=use_formplayer) if result.get('status', None) == 'error': code = result.get('code', 500) message = result.get( 'message', _("Something went wrong filtering your cases.")) if code == 500: notify_exception(None, message=message) return json_response(message, status_code=code) case_ids = result.get("cases", []) else: # otherwise just use our built in api with the defaults case_ids = [ res.id for res in get_filtered_cases( domain, status=CASE_STATUS_OPEN, case_type=case_type, user_id=request.couch_user._id, footprint=True, ids_only=True, ) ] cases = accessor.get_cases(case_ids) if parent_id: cases = filter(lambda c: c.parent and c.parent.case_id == parent_id, cases) # refilter these because we might have accidentally included footprint cases # in the results from touchforms. this is a little hacky but the easiest # (quick) workaround. should be revisted when we optimize the case list. cases = filter(lambda c: c.type == case_type, cases) cases = [c.to_api_json(lite=True) for c in cases if c] response = {'cases': cases} if requires_parent_cases: # Subtract already fetched cases from parent list parent_ids = set(map(lambda c: c['indices']['parent']['case_id'], cases)) - \ set(map(lambda c: c['case_id'], cases)) parents = accessor.get_cases(list(parent_ids)) parents = [c.to_api_json(lite=True) for c in parents] response.update({'parents': parents}) return json_response(response)
def filter_cases(request, domain, app_id, module_id, parent_id=None): app = Application.get(app_id) module = app.get_module(module_id) auth_cookie = request.COOKIES.get('sessionid') requires_parent_cases = string_to_boolean(request.GET.get('requires_parent_cases', 'false')) xpath = EntriesHelper.get_filter_xpath(module) instances = get_instances_for_module(app, module, additional_xpaths=[xpath]) extra_instances = [{'id': inst.id, 'src': inst.src} for inst in instances] accessor = CaseAccessors(domain) # touchforms doesn't like this to be escaped xpath = HTMLParser.HTMLParser().unescape(xpath) case_type = module.case_type if xpath or should_use_sql_backend(domain): # if we need to do a custom filter, send it to touchforms for processing additional_filters = { "properties/case_type": case_type, "footprint": True } helper = BaseSessionDataHelper(domain, request.couch_user) result = helper.filter_cases(xpath, additional_filters, DjangoAuth(auth_cookie), extra_instances=extra_instances) if result.get('status', None) == 'error': code = result.get('code', 500) message = result.get('message', _("Something went wrong filtering your cases.")) if code == 500: notify_exception(None, message=message) return json_response(message, status_code=code) case_ids = result.get("cases", []) else: # otherwise just use our built in api with the defaults case_ids = [res.id for res in get_filtered_cases( domain, status=CASE_STATUS_OPEN, case_type=case_type, user_id=request.couch_user._id, footprint=True, ids_only=True, )] cases = accessor.get_cases(case_ids) if parent_id: cases = filter(lambda c: c.parent and c.parent.case_id == parent_id, cases) # refilter these because we might have accidentally included footprint cases # in the results from touchforms. this is a little hacky but the easiest # (quick) workaround. should be revisted when we optimize the case list. cases = filter(lambda c: c.type == case_type, cases) cases = [c.to_api_json(lite=True) for c in cases if c] response = {'cases': cases} if requires_parent_cases: # Subtract already fetched cases from parent list parent_ids = set(map(lambda c: c['indices']['parent']['case_id'], cases)) - \ set(map(lambda c: c['case_id'], cases)) parents = accessor.get_cases(list(parent_ids)) parents = [c.to_api_json(lite=True) for c in parents] response.update({'parents': parents}) return json_response(response)
def build_detail(self, module, detail_type, detail, detail_column_infos, tabs=None, id=None, title=None, nodeset=None, print_template=None, start=0, end=None, relevant=None): """ Recursively builds the Detail object. (Details can contain other details for each of their tabs) """ from corehq.apps.app_manager.detail_screen import get_column_generator d = Detail(id=id, title=title, nodeset=nodeset, print_template=print_template, relevant=relevant) self._add_custom_variables(detail, d) if tabs: tab_spans = detail.get_tab_spans() for tab in tabs: # relevant should be set to None even in case its '' tab_relevant = None if tab.relevant and toggles.DISPLAY_CONDITION_ON_TABS.enabled(module.get_app().domain): tab_relevant = tab.relevant sub_detail = self.build_detail( module, detail_type, detail, detail_column_infos, title=Text(locale_id=id_strings.detail_tab_title_locale( module, detail_type, tab )), nodeset=tab.nodeset if tab.has_nodeset else None, start=tab_spans[tab.id][0], end=tab_spans[tab.id][1], relevant=tab_relevant, ) if sub_detail: d.details.append(sub_detail) if len(d.details): helper = EntriesHelper(self.app) datums = helper.get_datum_meta_module(module) d.variables.extend([DetailVariable(name=datum.datum.id, function=datum.datum.value) for datum in datums]) return d else: return None # Base case (has no tabs) else: # Add lookup if detail.lookup_enabled and detail.lookup_action: d.lookup = self._get_lookup_element(detail, module) # Add variables variables = list( schedule_detail_variables(module, detail, detail_column_infos) ) if variables: d.variables.extend(variables) # Add fields if end is None: end = len(detail_column_infos) for column_info in detail_column_infos[start:end]: # column_info is an instance of DetailColumnInfo named tuple. It has the following properties: # column_info.column: an instance of app_manager.models.DetailColumn # column_info.sort_element: an instance of app_manager.models.SortElement # column_info.order: an integer fields = get_column_generator( self.app, module, detail, parent_tab_nodeset=nodeset, detail_type=detail_type, *column_info ).fields for field in fields: d.fields.append(field) # Add actions if detail_type.endswith('short') and not module.put_in_root: if module.case_list_form.form_id: target_form = self.app.get_form(module.case_list_form.form_id) if target_form.is_registration_form(module.case_type): d.actions.append(self._get_reg_form_action(module)) if module_offers_search(module) and "search" not in id: # Add the search action only if this isn't a search detail d.actions.append(self._get_case_search_action(module)) try: if not self.app.enable_multi_sort: d.fields[0].sort = 'default' except IndexError: pass else: # only yield the Detail if it has Fields return d
def build_detail(self, module, detail_type, detail, detail_column_infos, tabs=None, id=None, title=None, nodeset=None, start=0, end=None): """ Recursively builds the Detail object. (Details can contain other details for each of their tabs) """ from corehq.apps.app_manager.detail_screen import get_column_generator d = Detail(id=id, title=title, nodeset=nodeset) self._add_custom_variables(detail, d) if tabs: tab_spans = detail.get_tab_spans() for tab in tabs: sub_detail = self.build_detail( module, detail_type, detail, detail_column_infos, title=Text(locale_id=id_strings.detail_tab_title_locale( module, detail_type, tab )), nodeset=tab.nodeset if tab.has_nodeset else None, start=tab_spans[tab.id][0], end=tab_spans[tab.id][1] ) if sub_detail: d.details.append(sub_detail) if len(d.details): helper = EntriesHelper(self.app) datums = helper.get_datum_meta_module(module) d.variables.extend([DetailVariable(name=datum.datum.id, function=datum.datum.value) for datum in datums]) return d else: return None # Base case (has no tabs) else: # Add lookup if detail.lookup_enabled and detail.lookup_action: d.lookup = self._get_lookup_element(detail, module) # Add variables variables = list( schedule_detail_variables(module, detail, detail_column_infos) ) if variables: d.variables.extend(variables) # Add fields if end is None: end = len(detail_column_infos) for column_info in detail_column_infos[start:end]: fields = get_column_generator( self.app, module, detail, detail_type=detail_type, *column_info ).fields d.fields.extend(fields) # Add actions if module.case_list_form.form_id and detail_type.endswith('short')\ and not module.put_in_root: target_form = self.app.get_form(module.case_list_form.form_id) if target_form.is_registration_form(module.case_type): d.actions.append(self._get_reg_form_action(module)) if module_offers_search(module) and detail_type.endswith('short') and not module.put_in_root: d.actions.append(self._get_case_search_action(module)) try: if not self.app.enable_multi_sort: d.fields[0].sort = 'default' except IndexError: pass else: # only yield the Detail if it has Fields return d
def get_session_schema(form): """Get form session schema definition """ from corehq.apps.app_manager.suite_xml.sections.entries import EntriesHelper app = form.get_app() structure = {} datums = EntriesHelper(app).get_datums_meta_for_form_generic(form) datums = [ d for d in datums if d.requires_selection and d.case_type and not d.is_new_case_id ] def _get_structure(datum, data_registry, source=None): id_source = f":{slugify(source)}" if source else "" return { "reference": { "hashtag": f'#registry_case{id_source}' if data_registry else f"#case{id_source}", "source": "registry" if data_registry else "casedb", "subset": f"case{id_source}", "key": "@case_id", }, } unrelated_parents = set() for datum in datums: if not datum.module_id: continue module = app.get_module_by_unique_id(datum.module_id) parent_select_active = hasattr( module, 'parent_select') and module.parent_select.active if parent_select_active and module.parent_select.relationship is None: # for child modules that use parent select where the parent is not a 'related' case # See toggles.NON_PARENT_MENU_SELECTION unrelated_parents.add(module.parent_select.module_id) data_structure = {} for i, datum in enumerate(reversed(datums)): if isinstance(datum.datum, InstanceDatum): continue module_id = datum.module_id module = app.get_module_by_unique_id(module_id) if module_id else None data_registry = module.search_config.data_registry if module else None if i == 0: # always add the datum for this module data_structure[datum.datum.id] = _get_structure( datum, data_registry) else: if module and module_id in unrelated_parents: source = clean_trans( module.name, app.langs ) # ensure that this structure reference is unique data_structure[datum.datum.id] = _get_structure( datum, data_registry, source) if data_structure: structure["data"] = { "merge": True, "structure": data_structure, } if is_usercase_in_use(app.domain): structure["context"] = { "merge": True, "structure": { "userid": { "reference": { "hashtag": "#user", "source": "casedb", "subset": USERCASE_TYPE, "subset_key": "@case_type", "subset_filter": True, "key": "hq_user_id", }, }, }, } return { "id": "commcaresession", "uri": "jr://instance/session", "name": "Session", "path": "/session", "structure": structure, }
def build_detail(self, module, detail_type, detail, detail_column_infos, tabs=None, id=None, title=None, nodeset=None, print_template=None, start=0, end=None, relevant=None): """ Recursively builds the Detail object. (Details can contain other details for each of their tabs) """ from corehq.apps.app_manager.detail_screen import get_column_generator d = Detail(id=id, title=title, nodeset=nodeset, print_template=print_template, relevant=relevant) self._add_custom_variables(detail, d) if tabs: tab_spans = detail.get_tab_spans() for tab in tabs: # relevant should be set to None even in case its '' tab_relevant = None if tab.relevant and toggles.DISPLAY_CONDITION_ON_TABS.enabled( module.get_app().domain): tab_relevant = tab.relevant sub_detail = self.build_detail( module, detail_type, detail, detail_column_infos, title=Text(locale_id=id_strings.detail_tab_title_locale( module, detail_type, tab)), nodeset=tab.nodeset if tab.has_nodeset else None, start=tab_spans[tab.id][0], end=tab_spans[tab.id][1], relevant=tab_relevant, ) if sub_detail: d.details.append(sub_detail) if len(d.details): helper = EntriesHelper(self.app) datums = helper.get_datum_meta_module(module) d.variables.extend([ DetailVariable(name=datum.datum.id, function=datum.datum.value) for datum in datums ]) return d else: return None # Base case (has no tabs) else: # Add lookup if detail.lookup_enabled and detail.lookup_action: d.lookup = self._get_lookup_element(detail, module) # Add variables variables = list( schedule_detail_variables(module, detail, detail_column_infos)) if variables: d.variables.extend(variables) # Add fields if end is None: end = len(detail_column_infos) for column_info in detail_column_infos[start:end]: # column_info is an instance of DetailColumnInfo named tuple. It has the following properties: # column_info.column: an instance of app_manager.models.DetailColumn # column_info.sort_element: an instance of app_manager.models.SortElement # column_info.order: an integer fields = get_column_generator(self.app, module, detail, parent_tab_nodeset=nodeset, detail_type=detail_type, *column_info).fields for field in fields: d.fields.append(field) # Add actions if detail_type.endswith('short') and not module.put_in_root: if module.case_list_form.form_id: target_form = self.app.get_form( module.case_list_form.form_id) if target_form.is_registration_form(module.case_type): d.actions.append(self._get_reg_form_action(module)) if module_offers_search(module): d.actions.append( self._get_case_search_action(module, in_search="search" in id)) try: if not self.app.enable_multi_sort: d.fields[0].sort = 'default' except IndexError: pass else: # only yield the Detail if it has Fields return d
def build_detail(self, module, detail_type, detail, detail_column_infos, tabs=None, id=None, title=None, nodeset=None, start=0, end=None): """ Recursively builds the Detail object. (Details can contain other details for each of their tabs) """ from corehq.apps.app_manager.detail_screen import get_column_generator d = Detail(id=id, title=title, nodeset=nodeset) if tabs: tab_spans = detail.get_tab_spans() for tab in tabs: sub_detail = self.build_detail( module, detail_type, detail, detail_column_infos, title=Text(locale_id=id_strings.detail_tab_title_locale( module, detail_type, tab)), nodeset=tab.nodeset if tab.has_nodeset else None, start=tab_spans[tab.id][0], end=tab_spans[tab.id][1]) if sub_detail: d.details.append(sub_detail) if len(d.details): helper = EntriesHelper(self.app) datums = helper.get_datum_meta_module(module) d.variables.extend([ DetailVariable(name=datum.datum.id, function=datum.datum.value) for datum in datums ]) return d else: return None # Base case (has no tabs) else: # Add lookup if detail.lookup_enabled and detail.lookup_action: d.lookup = self._get_lookup_element(detail, module) # Add variables variables = list( schedule_detail_variables(module, detail, detail_column_infos)) if variables: d.variables.extend(variables) # Add fields if end is None: end = len(detail_column_infos) for column_info in detail_column_infos[start:end]: fields = get_column_generator(self.app, module, detail, detail_type=detail_type, *column_info).fields d.fields.extend(fields) # Add actions if module.case_list_form.form_id and detail_type.endswith('short')\ and not module.put_in_root: target_form = self.app.get_form(module.case_list_form.form_id) if target_form.is_registration_form(module.case_type): d.actions.append(self._get_reg_form_action(module)) if module_offers_search(module) and detail_type.endswith( 'short') and not module.put_in_root: d.actions.append(self._get_case_search_action(module)) try: if not self.app.enable_multi_sort: d.fields[0].sort = 'default' except IndexError: pass else: # only yield the Detail if it has Fields return d
def __init__(self, suite, app, modules): from corehq.apps.app_manager.suite_xml.sections.entries import EntriesHelper self.suite = suite self.app = app self.modules = modules self.entries_helper = EntriesHelper(app, modules)