def setUp(self): self.app = Application.new_app(DOMAIN, "Untitled Application") self.module = self.app.add_module( Module.new_module("Untitled Module", None)) self.app.new_form(0, "Untitled Form", None) self.module.case_type = 'case' self.module.search_config = CaseSearch( command_label={'en': 'Search Patients Nationally'}, properties=[ CaseSearchProperty(name='name', label={'en': 'Name'}), CaseSearchProperty(name='dob', label={'en': 'Date of birth'}) ], relevant="{} and {}".format("instance('groups')/groups/group", CLAIM_DEFAULT_RELEVANT_CONDITION), default_properties=[ DefaultCaseSearchProperty( property=u'ɨŧsȺŧɍȺᵽ', defaultValue= (u"instance('casedb')/case" u"[@case_id='instance('commcaresession')/session/data/case_id']" u"/ɨŧsȺŧɍȺᵽ")), DefaultCaseSearchProperty( property='name', defaultValue= "instance('locations')/locations/location[@id=123]/@type", ), ], )
def setUp(self): self.app = Application.new_app(DOMAIN, "Untitled Application") self.app.build_spec = BuildSpec(version='tests', build_number=1) self.module = self.app.add_module( Module.new_module("Untitled Module", None)) self.app.new_form(0, "Untitled Form", None) self.module.case_type = 'case' # chosen xpath just used to reference more instances - not considered valid to use in apps self.module.case_details.short.columns.append( DetailColumn.wrap( dict( header={"en": "report_name"}, model="case", format="calculate", field="whatever", calc_xpath="instance('reports')/report[1]/name", ))) self.module.case_details.long.columns.append( DetailColumn.wrap( dict( header={"en": "ledger_name"}, model="case", format="calculate", field="whatever", calc_xpath="instance('ledgerdb')/ledgers/name/name", ))) self.module.search_config = CaseSearch( command_label={'en': 'Search Patients Nationally'}, properties=[ CaseSearchProperty(name='name', label={'en': 'Name'}), CaseSearchProperty(name='dob', label={'en': 'Date of birth'}) ], relevant="{} and {}".format("instance('groups')/groups/group", CLAIM_DEFAULT_RELEVANT_CONDITION), default_properties=[ DefaultCaseSearchProperty( property=u'ɨŧsȺŧɍȺᵽ', defaultValue= (u"instance('casedb')/case" u"[@case_id='instance('commcaresession')/session/data/case_id']" u"/ɨŧsȺŧɍȺᵽ")), DefaultCaseSearchProperty( property='name', defaultValue= "instance('locations')/locations/location[@id=123]/@type", ), ], )
def test_overwrite_options(self): self.dest_module.search_config = CaseSearch( properties=[CaseSearchProperty(name='age', label={'en': 'Age'})], default_properties=[ DefaultCaseSearchProperty( property='location', defaultValue= "instance('locations')/locations/location[@id=123]/location_id" ) ]) original_json = self.dest_module.search_config.to_json() self.dest_module.search_config.overwrite_attrs( self.src_module.search_config, ["search_claim_options"]) final_json = self.dest_module.search_config.to_json() # properties and default properties should be unchanged self.assertEqual(original_json["properties"], final_json["properties"]) self.assertEqual(original_json["default_properties"], final_json["default_properties"]) # everything else should match the source config src_json = self.src_module.search_config.to_json() for config_dict in (final_json, src_json): config_dict.pop("properties", []) config_dict.pop("default_properties", []) self.assertEqual(final_json, src_json)
def test_only_default_properties(self, *args): self.module.search_config = CaseSearch(default_properties=[ DefaultCaseSearchProperty( property='ɨŧsȺŧɍȺᵽ', defaultValue= ("instance('casedb')/case" "[@case_id='instance('commcaresession')/session/data/case_id']" "/ɨŧsȺŧɍȺᵽ")), DefaultCaseSearchProperty( property='name', defaultValue= "instance('locations')/locations/location[@id=123]/@type", ), ], ) with patch( 'corehq.util.view_utils.get_url_base') as get_url_base_patch: get_url_base_patch.return_value = 'https://www.example.com' suite = self.app.create_suite() self.assertXmlPartialEqual(self.get_xml('search_config_default_only'), suite, "./remote-request[1]")
def test_only_default_properties(self, *args): self.module.search_config = CaseSearch( default_properties=[ DefaultCaseSearchProperty( property='ɨŧsȺŧɍȺᵽ', defaultValue=( "instance('casedb')/case" "[@case_id='instance('commcaresession')/session/data/case_id']" "/ɨŧsȺŧɍȺᵽ") ), DefaultCaseSearchProperty( property='name', defaultValue="instance('locations')/locations/location[@id=123]/@type", ), ], ) # wrap to have assign_references called self.app = Application.wrap(self.app.to_json()) suite = self.app.create_suite() self.assertXmlPartialEqual(self.get_xml('search_config_default_only'), suite, "./remote-request[1]")
def setUp(self): self.all_attrs = [ 'search_properties', 'search_default_properties', 'search_claim_options' ] self.app = Application.new_app('domain', "Untitled Application") self.src_module = self.app.add_module( Module.new_module('Src Module', lang='en')) self.case_search_config = CaseSearch( search_label=CaseSearchLabel( label={'en': 'Search Patients Nationally'}), properties=[ CaseSearchProperty(name='name', label={'en': 'Name'}), CaseSearchProperty(name='dob', label={'en': 'Date of birth'}) ], auto_launch=True, default_search=True, additional_relevant="instance('groups')/groups/group", search_filter= "name = instance('item-list:trees')/trees_list/trees[favorite='yes']/name", search_button_display_condition="false()", blacklisted_owner_ids_expression= "instance('commcaresession')/session/context/userid", default_properties=[ DefaultCaseSearchProperty( property='ɨŧsȺŧɍȺᵽ', defaultValue= ("instance('casedb')/case" "[@case_id='instance('commcaresession')/session/data/case_id']/ɨŧsȺŧɍȺᵽ" )), DefaultCaseSearchProperty( property='name', defaultValue= "instance('locations')/locations/location[@id=123]/@type"), ], ) self.src_module.search_config = self.case_search_config self.dest_module = self.app.add_module( Module.new_module('Dest Module', lang='en'))
def edit_module_detail_screens(request, domain, app_id, module_id): """ Overwrite module case details. Only overwrites components that have been provided in the request. Components are short, long, filter, parent_select, fixture_select and sort_elements. """ params = json_request(request.POST) detail_type = params.get('type') short = params.get('short', None) long = params.get('long', None) tabs = params.get('tabs', None) filter = params.get('filter', ()) custom_xml = params.get('custom_xml', None) parent_select = params.get('parent_select', None) fixture_select = params.get('fixture_select', None) sort_elements = params.get('sort_elements', None) persist_case_context = params.get('persistCaseContext', None) persistent_case_context_xml = params.get('persistentCaseContextXML', None) use_case_tiles = params.get('useCaseTiles', None) persist_tile_on_forms = params.get("persistTileOnForms", None) pull_down_tile = params.get("enableTilePullDown", None) case_list_lookup = params.get("case_list_lookup", None) search_properties = params.get("search_properties") custom_variables = { 'short': params.get("short_custom_variables", None), 'long': params.get("long_custom_variables", None) } app = get_app(domain, app_id) module = app.get_module(module_id) if detail_type == 'case': detail = module.case_details elif detail_type == CAREPLAN_GOAL: detail = module.goal_details elif detail_type == CAREPLAN_TASK: detail = module.task_details else: try: detail = getattr(module, '{0}_details'.format(detail_type)) except AttributeError: return HttpResponseBadRequest("Unknown detail type '%s'" % detail_type) lang = request.COOKIES.get('lang', app.langs[0]) if short is not None: detail.short.columns = map(DetailColumn.from_json, short) if persist_case_context is not None: detail.short.persist_case_context = persist_case_context detail.short.persistent_case_context_xml = persistent_case_context_xml if use_case_tiles is not None: detail.short.use_case_tiles = use_case_tiles if persist_tile_on_forms is not None: detail.short.persist_tile_on_forms = persist_tile_on_forms if pull_down_tile is not None: detail.short.pull_down_tile = pull_down_tile if case_list_lookup is not None: _save_case_list_lookup_params(detail.short, case_list_lookup, lang) if long is not None: detail.long.columns = map(DetailColumn.from_json, long) if tabs is not None: detail.long.tabs = map(DetailTab.wrap, tabs) if filter != (): # Note that we use the empty tuple as the sentinel because a filter # value of None represents clearing the filter. detail.short.filter = filter if custom_xml is not None: detail.short.custom_xml = custom_xml if custom_variables['short'] is not None: try: etree.fromstring("<variables>{}</variables>".format( custom_variables['short'])) except etree.XMLSyntaxError as error: return HttpResponseBadRequest( "There was an issue with your custom variables: {}".format( error.message)) detail.short.custom_variables = custom_variables['short'] if custom_variables['long'] is not None: try: etree.fromstring("<variables>{}</variables>".format( custom_variables['long'])) except etree.XMLSyntaxError as error: return HttpResponseBadRequest( "There was an issue with your custom variables: {}".format( error.message)) detail.long.custom_variables = custom_variables['long'] if sort_elements is not None: detail.short.sort_elements = [] for sort_element in sort_elements: item = SortElement() item.field = sort_element['field'] item.type = sort_element['type'] item.direction = sort_element['direction'] item.display[lang] = sort_element['display'] if toggles.SORT_CALCULATION_IN_CASE_LIST.enabled(domain): item.sort_calculation = sort_element['sort_calculation'] else: item.sort_calculation = "" detail.short.sort_elements.append(item) if parent_select is not None: module.parent_select = ParentSelect.wrap(parent_select) if module_case_hierarchy_has_circular_reference(module): return HttpResponseBadRequest( _("The case hierarchy contains a circular reference.")) if fixture_select is not None: module.fixture_select = FixtureSelect.wrap(fixture_select) if search_properties is not None: if search_properties.get('properties') is not None: module.search_config = CaseSearch( properties=[ CaseSearchProperty.wrap(p) for p in _update_search_properties( module, search_properties.get('properties'), lang) ], relevant=(search_properties.get('relevant') if search_properties.get('relevant') is not None else CLAIM_DEFAULT_RELEVANT_CONDITION), include_closed=bool(search_properties.get('include_closed')), default_properties=[ DefaultCaseSearchProperty.wrap(p) for p in search_properties.get('default_properties') ]) resp = {} app.save(resp) return json_response(resp)
def setUp(self): self.app = Application.new_app(DOMAIN, "Untitled Application") self.app.build_spec = BuildSpec(version='2.35.0', build_number=1) self.module = self.app.add_module( Module.new_module("Untitled Module", None)) self.app.new_form(0, "Untitled Form", None) self.module.case_type = 'case' # chosen xpath just used to reference more instances - not considered valid to use in apps self.module.case_details.short.columns.append( DetailColumn.wrap( dict( header={"en": "report_name"}, model="case", format="calculate", field="whatever", calc_xpath="instance('reports')/report[1]/name", ))) self.module.case_details.short.columns.append( DetailColumn.wrap( dict( header={"en": "moon"}, model="case", format="calculate", field="whatever", calc_xpath= "instance('item-list:moons')/moons_list/moons[favorite='yes']/name", ))) self.module.case_details.long.columns.append( DetailColumn.wrap( dict( header={"en": "ledger_name"}, model="case", format="calculate", field="whatever", calc_xpath="instance('ledgerdb')/ledgers/name/name", ))) self.module.search_config = CaseSearch( command_label={'en': 'Search Patients Nationally'}, properties=[ CaseSearchProperty(name='name', label={'en': 'Name'}), CaseSearchProperty(name='dob', label={'en': 'Date of birth'}) ], default_relevant=True, additional_relevant="instance('groups')/groups/group", search_filter= "name = instance('item-list:trees')/trees_list/trees[favorite='yes']/name", default_properties=[ DefaultCaseSearchProperty( property='ɨŧsȺŧɍȺᵽ', defaultValue= ("instance('casedb')/case" "[@case_id='instance('commcaresession')/session/data/case_id']" "/ɨŧsȺŧɍȺᵽ")), DefaultCaseSearchProperty( property='name', defaultValue= "instance('locations')/locations/location[@id=123]/@type", ), ], )
def edit_module_detail_screens(request, domain, app_id, module_unique_id): """ Overwrite module case details. Only overwrites components that have been provided in the request. Components are short, long, filter, parent_select, fixture_select and sort_elements. """ params = json_request(request.POST) detail_type = params.get('type') short = params.get('short', None) long_ = params.get('long', None) tabs = params.get('tabs', None) filter = params.get('filter', ()) custom_xml = params.get('custom_xml', None) parent_select = params.get('parent_select', None) fixture_select = params.get('fixture_select', None) sort_elements = params.get('sort_elements', None) persist_case_context = params.get('persistCaseContext', None) persistent_case_context_xml = params.get('persistentCaseContextXML', None) use_case_tiles = params.get('useCaseTiles', None) persist_tile_on_forms = params.get("persistTileOnForms", None) persistent_case_tile_from_module = params.get("persistentCaseTileFromModule", None) pull_down_tile = params.get("enableTilePullDown", None) sort_nodeset_columns = params.get("sortNodesetColumns", None) print_template = params.get('printTemplate', None) case_list_lookup = params.get("case_list_lookup", None) search_properties = params.get("search_properties") custom_variables = { 'short': params.get("short_custom_variables", None), 'long': params.get("long_custom_variables", None) } app = get_app(domain, app_id) try: module = app.get_module_by_unique_id(module_unique_id) except ModuleNotFoundException: # temporary fallback module = app.get_module(module_unique_id) if detail_type == 'case': detail = module.case_details else: try: detail = getattr(module, '{0}_details'.format(detail_type)) except AttributeError: return HttpResponseBadRequest("Unknown detail type '%s'" % detail_type) lang = request.COOKIES.get('lang', app.langs[0]) if short is not None: detail.short.columns = list(map(DetailColumn.from_json, short)) if persist_case_context is not None: detail.short.persist_case_context = persist_case_context detail.short.persistent_case_context_xml = persistent_case_context_xml if use_case_tiles is not None: detail.short.use_case_tiles = use_case_tiles if persist_tile_on_forms is not None: detail.short.persist_tile_on_forms = persist_tile_on_forms if persistent_case_tile_from_module is not None: detail.short.persistent_case_tile_from_module = persistent_case_tile_from_module if pull_down_tile is not None: detail.short.pull_down_tile = pull_down_tile if case_list_lookup is not None: _save_case_list_lookup_params(detail.short, case_list_lookup, lang) if long_ is not None: detail.long.columns = list(map(DetailColumn.from_json, long_)) if tabs is not None: detail.long.tabs = list(map(DetailTab.wrap, tabs)) if print_template is not None: detail.long.print_template = print_template if filter != (): # Note that we use the empty tuple as the sentinel because a filter # value of None represents clearing the filter. detail.short.filter = filter if custom_xml is not None: detail.short.custom_xml = custom_xml if custom_variables['short'] is not None: try: etree.fromstring("<variables>{}</variables>".format(custom_variables['short'])) except etree.XMLSyntaxError as error: return HttpResponseBadRequest( "There was an issue with your custom variables: {}".format(error.message) ) detail.short.custom_variables = custom_variables['short'] if custom_variables['long'] is not None: try: etree.fromstring("<variables>{}</variables>".format(custom_variables['long'])) except etree.XMLSyntaxError as error: return HttpResponseBadRequest( "There was an issue with your custom variables: {}".format(error.message) ) detail.long.custom_variables = custom_variables['long'] if sort_nodeset_columns is not None: detail.long.sort_nodeset_columns = sort_nodeset_columns if sort_elements is not None: # Attempt to map new elements to old so we don't lose translations # Imperfect because the same field may be used multiple times, or user may change field old_elements_by_field = {e['field']: e for e in detail.short.sort_elements} detail.short.sort_elements = [] for sort_element in sort_elements: item = SortElement() item.field = sort_element['field'] item.type = sort_element['type'] item.direction = sort_element['direction'] item.blanks = sort_element['blanks'] if item.field in old_elements_by_field: item.display = old_elements_by_field[item.field].display item.display[lang] = sort_element['display'] if toggles.SORT_CALCULATION_IN_CASE_LIST.enabled(domain): item.sort_calculation = sort_element['sort_calculation'] else: item.sort_calculation = "" detail.short.sort_elements.append(item) if parent_select is not None: module.parent_select = ParentSelect.wrap(parent_select) if module_case_hierarchy_has_circular_reference(module): return HttpResponseBadRequest(_("The case hierarchy contains a circular reference.")) if fixture_select is not None: module.fixture_select = FixtureSelect.wrap(fixture_select) if search_properties is not None: if ( search_properties.get('properties') is not None or search_properties.get('default_properties') is not None ): module.search_config = CaseSearch( properties=[ CaseSearchProperty.wrap(p) for p in _update_search_properties( module, search_properties.get('properties'), lang ) ], relevant=( search_properties.get('relevant') if search_properties.get('relevant') is not None else CLAIM_DEFAULT_RELEVANT_CONDITION ), include_closed=bool(search_properties.get('include_closed')), search_button_display_condition=search_properties.get('search_button_display_condition', ""), blacklisted_owner_ids_expression=search_properties.get('blacklisted_owner_ids_expression', ""), default_properties=[ DefaultCaseSearchProperty.wrap(p) for p in search_properties.get('default_properties') ] ) resp = {} app.save(resp) return json_response(resp)
def edit_module_detail_screens(request, domain, app_id, module_id): """ Overwrite module case details. Only overwrites components that have been provided in the request. Components are short, long, filter, parent_select, fixture_select and sort_elements. """ params = json_request(request.POST) detail_type = params.get('type') short = params.get('short', None) long = params.get('long', None) tabs = params.get('tabs', None) filter = params.get('filter', ()) custom_xml = params.get('custom_xml', None) parent_select = params.get('parent_select', None) fixture_select = params.get('fixture_select', None) sort_elements = params.get('sort_elements', None) persist_case_context = params.get('persistCaseContext', None) persistent_case_context_xml = params.get('persistentCaseContextXML', None) use_case_tiles = params.get('useCaseTiles', None) persist_tile_on_forms = params.get("persistTileOnForms", None) pull_down_tile = params.get("enableTilePullDown", None) case_list_lookup = params.get("case_list_lookup", None) search_properties = params.get("search_properties") custom_variables = { 'short': params.get("short_custom_variables", None), 'long': params.get("long_custom_variables", None) } app = get_app(domain, app_id) module = app.get_module(module_id) if detail_type == 'case': detail = module.case_details elif detail_type == CAREPLAN_GOAL: detail = module.goal_details elif detail_type == CAREPLAN_TASK: detail = module.task_details else: try: detail = getattr(module, '{0}_details'.format(detail_type)) except AttributeError: return HttpResponseBadRequest("Unknown detail type '%s'" % detail_type) lang = request.COOKIES.get('lang', app.langs[0]) if short is not None: detail.short.columns = map(DetailColumn.from_json, short) if persist_case_context is not None: detail.short.persist_case_context = persist_case_context detail.short.persistent_case_context_xml = persistent_case_context_xml if use_case_tiles is not None: detail.short.use_case_tiles = use_case_tiles if persist_tile_on_forms is not None: detail.short.persist_tile_on_forms = persist_tile_on_forms if pull_down_tile is not None: detail.short.pull_down_tile = pull_down_tile if case_list_lookup is not None: _save_case_list_lookup_params(detail.short, case_list_lookup, lang) if long is not None: detail.long.columns = map(DetailColumn.from_json, long) if tabs is not None: detail.long.tabs = map(DetailTab.wrap, tabs) if filter != (): # Note that we use the empty tuple as the sentinel because a filter # value of None represents clearing the filter. detail.short.filter = filter if custom_xml is not None: detail.short.custom_xml = custom_xml if custom_variables['short'] is not None: try: etree.fromstring("<variables>{}</variables>".format(custom_variables['short'])) except etree.XMLSyntaxError as error: return HttpResponseBadRequest( "There was an issue with your custom variables: {}".format(error.message) ) detail.short.custom_variables = custom_variables['short'] if custom_variables['long'] is not None: try: etree.fromstring("<variables>{}</variables>".format(custom_variables['long'])) except etree.XMLSyntaxError as error: return HttpResponseBadRequest( "There was an issue with your custom variables: {}".format(error.message) ) detail.long.custom_variables = custom_variables['long'] if sort_elements is not None: detail.short.sort_elements = [] for sort_element in sort_elements: item = SortElement() item.field = sort_element['field'] item.type = sort_element['type'] item.direction = sort_element['direction'] item.display[lang] = sort_element['display'] detail.short.sort_elements.append(item) if parent_select is not None: module.parent_select = ParentSelect.wrap(parent_select) if module_case_hierarchy_has_circular_reference(module): return HttpResponseBadRequest(_("The case hierarchy contains a circular reference.")) if fixture_select is not None: module.fixture_select = FixtureSelect.wrap(fixture_select) if search_properties is not None: if search_properties.get('properties') is not None: module.search_config = CaseSearch( properties=[ CaseSearchProperty.wrap(p) for p in _update_search_properties( module, search_properties.get('properties'), lang ) ], relevant=( search_properties.get('relevant') if search_properties.get('relevant') is not None else CLAIM_DEFAULT_RELEVANT_CONDITION ), include_closed=bool(search_properties.get('include_closed')), default_properties=[ DefaultCaseSearchProperty.wrap(p) for p in search_properties.get('default_properties') ] ) resp = {} app.save(resp) return json_response(resp)