def get_commands(excluded_form_ids): @memoized def module_uses_case(): return module.all_forms_require_a_case() @memoized def domain_uses_usercase(): return is_usercase_in_use(self.app.domain) for form in module.get_suite_forms(): if form.unique_id in excluded_form_ids: continue command = Command(id=id_strings.form_command(form, module)) if form.requires_case(): form_datums = self.entries_helper.get_datums_meta_for_form_generic( form, module) var_name = next(meta.datum.id for meta in reversed(form_datums) if meta.action and meta.requires_selection) case = CaseIDXPath(session_var(var_name)).case() else: case = None if getattr(form, 'form_filter', None): fixture_xpath = (session_var( id_strings.fixture_session_var(module)) if module.fixture_select.active else None) interpolated_xpath = interpolate_xpath(form.form_filter, case, fixture_xpath, module=module, form=form) if xpath_references_case(interpolated_xpath) and \ (not module_uses_case() or module.put_in_root and not module.root_requires_same_case()): raise CaseXPathValidationError(module=module, form=form) if xpath_references_user_case( interpolated_xpath) and not domain_uses_usercase(): raise UserCaseXPathValidationError(module=module, form=form) command.relevant = interpolated_xpath if getattr(module, 'has_schedule', False) and module.all_forms_require_a_case(): # If there is a schedule and another filter condition, disregard it... # Other forms of filtering are disabled in the UI schedule_filter_condition = MenuContributor._schedule_filter_conditions( form, module, case) if schedule_filter_condition is not None: command.relevant = schedule_filter_condition yield command
def get_commands(excluded_form_ids): @memoized def module_uses_case(): return module.all_forms_require_a_case() @memoized def domain_uses_usercase(): return is_usercase_in_use(self.app.domain) for form in module.get_suite_forms(): if form.unique_id in excluded_form_ids: continue command = Command(id=id_strings.form_command(form, module)) if form.requires_case(): form_datums = self.entries_helper.get_datums_meta_for_form_generic(form, module) var_name = next( meta.datum.id for meta in reversed(form_datums) if meta.action and meta.requires_selection ) case = CaseIDXPath(session_var(var_name)).case() else: case = None if getattr(form, 'form_filter', None): fixture_xpath = ( session_var(id_strings.fixture_session_var(module)) if module.fixture_select.active else None ) interpolated_xpath = interpolate_xpath(form.form_filter, case, fixture_xpath, module=module, form=form) if xpath_references_case(interpolated_xpath) and \ (not module_uses_case() or module.put_in_root and not module.root_requires_same_case()): raise CaseXPathValidationError(module=module, form=form) if xpath_references_user_case(interpolated_xpath) and not domain_uses_usercase(): raise UserCaseXPathValidationError(module=module, form=form) command.relevant = interpolated_xpath if getattr(module, 'has_schedule', False) and module.all_forms_require_a_case(): # If there is a schedule and another filter condition, disregard it... # Other forms of filtering are disabled in the UI schedule_filter_condition = MenuContributor._schedule_filter_conditions(form, module, case) if schedule_filter_condition is not None: command.relevant = schedule_filter_condition yield command if hasattr(module, 'case_list') and module.case_list.show: yield Command(id=id_strings.case_list_command(module))
def check_actions(self): errors = [] from corehq.apps.app_manager.models import AdvancedOpenCaseAction, LoadUpdateAction case_tags = list(self.form.actions.get_case_tags()) for action in self.form.actions.get_subcase_actions(): for case_index in action.case_indices: if case_index.tag not in case_tags: errors.append({'type': 'missing parent tag', 'case_tag': case_index.tag}) if case_index.relationship == 'question' and not case_index.relationship_question: errors.append({'type': 'missing relationship question', 'case_tag': case_index.tag}) if isinstance(action, AdvancedOpenCaseAction): if not action.name_path: errors.append({'type': 'case_name required', 'case_tag': action.case_tag}) for case_index in action.case_indices: meta = self.form.actions.actions_meta_by_tag.get(case_index.tag) if meta and meta['type'] == 'open' and meta['action'].repeat_context: if ( not action.repeat_context or not action.repeat_context.startswith(meta['action'].repeat_context) ): errors.append({'type': 'subcase repeat context', 'case_tag': action.case_tag, 'parent_tag': case_index.tag}) errors.extend(self.check_case_properties( subcase_names=action.get_property_names(), case_tag=action.case_tag )) for action in self.form.actions.get_all_actions(): if not action.case_type and (not isinstance(action, LoadUpdateAction) or not action.auto_select): errors.append({'type': "no case type in action", 'case_tag': action.case_tag}) if isinstance(action, LoadUpdateAction) and action.auto_select: mode = action.auto_select.mode if not action.auto_select.value_key: key_names = { AUTO_SELECT_CASE: _('Case property'), AUTO_SELECT_FIXTURE: _('Lookup Table field'), AUTO_SELECT_USER: _('custom user property'), AUTO_SELECT_RAW: _('custom XPath expression'), } if mode in key_names: errors.append({'type': 'auto select key', 'key_name': key_names[mode]}) if not action.auto_select.value_source: source_names = { AUTO_SELECT_CASE: _('Case tag'), AUTO_SELECT_FIXTURE: _('Lookup Table tag'), } if mode in source_names: errors.append({'type': 'auto select source', 'source_name': source_names[mode]}) elif mode == AUTO_SELECT_CASE: case_tag = action.auto_select.value_source if not self.form.actions.get_action_from_tag(case_tag): errors.append({'type': 'auto select case ref', 'case_tag': action.case_tag}) errors.extend(self.check_case_properties( all_names=action.get_property_names(), case_tag=action.case_tag )) if self.form.form_filter: # Replace any dots with #case, which doesn't make for valid xpath # but will trigger any appropriate validation errors interpolated_form_filter = interpolate_xpath(self.form.form_filter, case_xpath="#case", module=self.form.get_module(), form=self.form) form_filter_references_case = ( xpath_references_case(interpolated_form_filter) or xpath_references_user_case(interpolated_form_filter) ) if form_filter_references_case: if not any(action for action in self.form.actions.load_update_cases if not action.auto_select): errors.append({'type': "filtering without case"}) def generate_paths(): for action in self.form.actions.get_all_actions(): for path in action.get_paths(): yield path if self.form.schedule: if self.form.schedule.transition_condition.type == 'if': yield self.form.schedule.transition_condition.question if self.form.schedule.termination_condition.type == 'if': yield self.form.schedule.termination_condition.question errors.extend(self.check_paths(generate_paths())) return errors
def check_actions(self): errors = [] from corehq.apps.app_manager.models import AdvancedOpenCaseAction, LoadUpdateAction for action in self.form.actions.get_subcase_actions(): case_tags = self.form.actions.get_case_tags() for case_index in action.case_indices: if case_index.tag not in case_tags: errors.append({'type': 'missing parent tag', 'case_tag': case_index.tag}) if case_index.relationship == 'question' and not case_index.relationship_question: errors.append({'type': 'missing relationship question', 'case_tag': case_index.tag}) if isinstance(action, AdvancedOpenCaseAction): if not action.name_path: errors.append({'type': 'case_name required', 'case_tag': action.case_tag}) for case_index in action.case_indices: meta = self.form.actions.actions_meta_by_tag.get(case_index.tag) if meta and meta['type'] == 'open' and meta['action'].repeat_context: if ( not action.repeat_context or not action.repeat_context.startswith(meta['action'].repeat_context) ): errors.append({'type': 'subcase repeat context', 'case_tag': action.case_tag, 'parent_tag': case_index.tag}) errors.extend(self.check_case_properties( subcase_names=action.get_property_names(), case_tag=action.case_tag )) for action in self.form.actions.get_all_actions(): if not action.case_type and (not isinstance(action, LoadUpdateAction) or not action.auto_select): errors.append({'type': "no case type in action", 'case_tag': action.case_tag}) if isinstance(action, LoadUpdateAction) and action.auto_select: mode = action.auto_select.mode if not action.auto_select.value_key: key_names = { AUTO_SELECT_CASE: _('Case property'), AUTO_SELECT_FIXTURE: _('Lookup Table field'), AUTO_SELECT_USER: _('custom user property'), AUTO_SELECT_RAW: _('custom XPath expression'), } if mode in key_names: errors.append({'type': 'auto select key', 'key_name': key_names[mode]}) if not action.auto_select.value_source: source_names = { AUTO_SELECT_CASE: _('Case tag'), AUTO_SELECT_FIXTURE: _('Lookup Table tag'), } if mode in source_names: errors.append({'type': 'auto select source', 'source_name': source_names[mode]}) elif mode == AUTO_SELECT_CASE: case_tag = action.auto_select.value_source if not self.form.actions.get_action_from_tag(case_tag): errors.append({'type': 'auto select case ref', 'case_tag': action.case_tag}) errors.extend(self.check_case_properties( all_names=action.get_property_names(), case_tag=action.case_tag )) if self.form.form_filter: # Replace any dots with #case, which doesn't make for valid xpath # but will trigger any appropriate validation errors interpolated_form_filter = interpolate_xpath(self.form.form_filter, case_xpath="#case", module=self.form.get_module(), form=self.form) form_filter_references_case = ( xpath_references_case(interpolated_form_filter) or xpath_references_user_case(interpolated_form_filter) ) if form_filter_references_case: if not any(action for action in self.form.actions.load_update_cases if not action.auto_select): errors.append({'type': "filtering without case"}) def generate_paths(): for action in self.form.actions.get_all_actions(): for path in action.get_paths(): yield path if self.form.schedule: if self.form.schedule.transition_condition.type == 'if': yield self.form.schedule.transition_condition.question if self.form.schedule.termination_condition.type == 'if': yield self.form.schedule.termination_condition.question errors.extend(self.check_paths(generate_paths())) return errors