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.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'}) ])
def setUp(self): self.app = Application.new_app(DOMAIN, "Untitled Application") self.app._id = '123' self.app.build_spec = BuildSpec(version='2.53.0', build_number=1) self.module = self.app.add_module(Module.new_module("Followup", None)) self.form = self.app.new_form(0, "Untitled Form", None, attachment=get_simple_form("xmlns1.0")) self.form.requires = 'case' self.module.case_type = 'case' self.module.case_details.long.columns.append( DetailColumn.wrap(dict( header={"en": "name"}, model="case", format="plain", field="whatever", )) ) self.module.search_config = CaseSearch( properties=[ CaseSearchProperty(name='name', label={'en': 'Name'}), CaseSearchProperty(name='favorite_color', label={'en': 'Favorite Color'}, itemset=Itemset( instance_id='item-list:colors', instance_uri='jr://fixture/item-list:colors', nodeset="instance('item-list:colors')/colors_list/colors", label='name', sort='name', value='value'), ) ], data_registry="myregistry", data_registry_workflow=REGISTRY_WORKFLOW_LOAD_CASE, additional_registry_cases=["'another case ID'"], ) self.reg_module = self.app.add_module(Module.new_module("Registration", None)) self.reg_form = self.app.new_form(1, "Untitled Form", None, attachment=get_simple_form("xmlns1.0")) self.reg_module.case_type = 'case' self.reg_form.actions.open_case = OpenCaseAction( name_update=ConditionalCaseUpdate(question_path="/data/question1") ) self.reg_form.actions.open_case.condition.type = 'always' self.reg_form.post_form_workflow = WORKFLOW_FORM self.reg_form.form_links = [ FormLink(form_id=self.form.get_unique_id()) ] # wrap to have assign_references called self.app = Application.wrap(self.app.to_json()) # reset to newly wrapped module self.module = self.app.modules[0] self.form = self.module.forms[0]
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_case_search_action(self, *args): """ Case search action should be added to case list and a new search detail should be created """ # Regular and advanced modules should get the search detail search_config = CaseSearch( command_label={'en': 'Advanced Search'}, again_label={'en': 'Search One More Time'}, properties=[CaseSearchProperty(name='name', label={'en': 'Name'})]) advanced_module = self.app.add_module( AdvancedModule.new_module("advanced", None)) advanced_module.search_config = search_config # Modules with custom xml should not get the search detail module_custom = self.app.add_module( Module.new_module("custom_xml", None)) module_custom.search_config = search_config module_custom.case_details.short.custom_xml = "<detail id='m2_case_short'></detail>" advanced_module_custom = self.app.add_module( AdvancedModule.new_module("advanced with custom_xml", None)) advanced_module_custom.search_config = search_config advanced_module_custom.case_details.short.custom_xml = "<detail id='m3_case_short'></detail>" suite = self.app.create_suite() self.assertXmlPartialEqual(self.get_xml('search_command_detail'), suite, "./detail")
def setUpTestData(cls): cls.domain = "registry-fixture-test" cls.domain_obj = create_domain(cls.domain) cls.domain_obj.hr_name = "Registry Fixture Test" cls.domain_obj.save() cls.restore_user = create_restore_user(cls.domain, username=f'{cls.domain}-user') cls.restore_user_domain_1 = create_restore_user( "domain1", username='******') invitations = [Invitation("domain1"), Invitation("domain2")] grants = [ Grant("domain1", [cls.domain]), Grant("domain2", [cls.domain]) ] cls.registry = create_registry_for_test( cls.restore_user._couch_user.get_django_user(), cls.domain, invitations=invitations, grants=grants, name="Test Registry") factory = AppFactory(domain=cls.domain) module1, form1 = factory.new_basic_module("patient", "patient") module1.search_config.properties = [CaseSearchProperty()] module1.search_config.data_registry = cls.registry.slug factory.new_report_module("reports") cls.app = factory.app cls.app.save()
def setUp(self): factory = AppFactory(DOMAIN, "App with DR and child modules", build_version='2.53.0') m0, f0 = factory.new_basic_module("case list", "case") factory.form_requires_case(f0) m1, f1 = factory.new_basic_module("child case list", "case", parent_module=m0) m1.parent_select = ParentSelect(active=True, relationship="other", module_id=m0.get_or_create_unique_id()) f2 = factory.new_form(m1) factory.form_requires_case(f1) factory.form_requires_case(f2) m1.search_config = CaseSearch( properties=[CaseSearchProperty(name='name', label={'en': 'Name'})], data_registry="myregistry", data_registry_workflow=REGISTRY_WORKFLOW_LOAD_CASE, ) # link from f1 to f2 (both in the child module) f1.post_form_workflow = WORKFLOW_FORM f1.form_links = [FormLink(form_id=f2.get_unique_id())] factory.app._id = "123" # wrap to have assign_references called self.app = Application.wrap(factory.app.to_json())
def setUp(self): self.factory = AppFactory(domain=DOMAIN) self.app_id = uuid4().hex self.factory.app._id = self.app_id module, form = self.factory.new_basic_module('basic', 'tree') self.factory.form_requires_case(form, 'tree') child_module, child_form = self.factory.new_basic_module('child', 'leaf', parent_module=module) self.factory.form_requires_case(child_form, 'leaf') child_module.search_config = CaseSearch( search_label=CaseSearchLabel(label={'en': 'Search'}), properties=[CaseSearchProperty(name=field) for field in ['name', 'shape']], data_registry="a_registry", data_registry_workflow=REGISTRY_WORKFLOW_SMART_LINK, ) child_module.assign_references() child_module.session_endpoint_id = "child_endpoint" child_module.parent_select.active = True child_module.parent_select.module_id = module.unique_id generator = SuiteGenerator(self.factory.app) detail_section_elements = generator.add_section(DetailContributor) entries = EntriesContributor(generator.suite, self.factory.app, self.factory.app.modules) generator.suite.entries.extend(entries.get_module_contributions(child_module)) self.request_factory = RemoteRequestFactory(generator.suite, child_module, detail_section_elements)
def test_blacklisted_owner_ids(self, *args): self.module.search_config = CaseSearch( properties=[ CaseSearchProperty(name='name', label={'en': 'Name'}), ], blacklisted_owner_ids_expression="instance('commcaresession')/session/context/userid", ) 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_blacklisted_owners'), suite, "./remote-request[1]")
def test_workflow_registry_module_previous_screen_after_case_list_form(self): factory = AppFactory(DOMAIN, "App with DR", build_version='2.53.0') m0, f0 = factory.new_basic_module("new case", "case") factory.form_opens_case(f0, "case") m1, f1 = factory.new_basic_module("update case", "case") factory.form_requires_case(f1, "case") m1.case_details.long.columns.append( DetailColumn.wrap(dict( header={"en": "name"}, model="case", format="plain", field="whatever", )) ) m1.search_config = CaseSearch( properties=[ CaseSearchProperty(name='name', label={'en': 'Name'}), ], data_registry="myregistry", data_registry_workflow=REGISTRY_WORKFLOW_LOAD_CASE, ) m1.case_list_form.form_id = f0.get_unique_id() m1.case_list_form.label = {'en': 'New Case'} f1.post_form_workflow = WORKFLOW_PREVIOUS app = Application.wrap(factory.app.to_json()) app._id = "123" suite = app.create_suite() self.assertXmlPartialEqual( """ <partial> <create> <command value="'m1'"/> <query id="results" value="http://localhost:8000/a/test_domain/phone/registry_case/123/"> <data key="case_type" ref="'case'"/> <data key="x_commcare_data_registry" ref="'myregistry'"/> <data key="case_id" ref="instance('commcaresession')/session/data/case_id"/> </query> <datum id="case_id" value="instance('commcaresession')/session/data/case_id"/> <query id="registry" value="http://localhost:8000/a/test_domain/phone/registry_case/123/"> <data key="x_commcare_data_registry" ref="'myregistry'"/> <data key="case_type" ref="'case'"/> <data key="case_id" ref="instance('commcaresession')/session/data/case_id"/> </query> </create> </partial> """, suite, "./entry[2]/stack/create" )
def test_blacklisted_owner_ids(self, *args): self.module.search_config = CaseSearch( properties=[ CaseSearchProperty(name='name', label={'en': 'Name'}), ], blacklisted_owner_ids_expression="instance('commcaresession')/session/context/userid", ) # 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_blacklisted_owners'), suite, "./remote-request[1]")
def setUpClass(cls): super().setUpClass() cls.user = create_user("admin", "123") CaseSearchConfig.objects.create(domain=cls.domain, enabled=True) household_1 = str(uuid.uuid4()) case_blocks = [ CaseBlock( case_id=household_1, case_type='household', case_name="Villanueva", create=True, ) ] case_blocks.extend([ CaseBlock( case_id=str(uuid.uuid4()), case_type='person', case_name=name, create=True, update=properties, index={ 'parent': IndexAttrs('household', household_id, 'child') } if household_id else None, ) for name, properties, household_id in [ ("Jane", { "family": "Villanueva" }, household_1), ("Xiomara", { "family": "Villanueva" }, household_1), ("Alba", { "family": "Villanueva" }, household_1), ("Rogelio", { "family": "de la Vega" }, household_1), ("Jane", { "family": "Ramos" }, None), ] ]) case_search_es_setup(cls.domain, case_blocks) cls.factory = AppFactory(domain=cls.domain) module, form = cls.factory.new_basic_module('person', 'person') module.search_config = CaseSearch( properties=[CaseSearchProperty(name='name')]) module.case_details.short.columns = [ DetailColumn(format='plain', field=field, header={'en': field}, model='person') for field in ['name', 'parent/name'] ]
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 get_app_with_case_search(domain): factory = AppFactory(domain=domain) for case_type, fields in [ ('person', ['name']), ('creative_work', ['name', 'parent/name']), ]: module, _ = factory.new_basic_module(case_type, case_type) module.search_config = CaseSearch( properties=[CaseSearchProperty(name=field) for field in fields]) module.case_details.short.columns = [ DetailColumn(format='plain', field=field, header={'en': field}, model=case_type) for field in fields ] return factory.app
def setUp(self): self.factory = AppFactory(domain="multiple-referrals") self.app_id = uuid4().hex self.factory.app._id = self.app_id self.module, self.form = self.factory.new_basic_module( 'basic', 'person') self.factory.form_requires_case(self.form, 'person') self.form.xmlns = "some-xmlns" self.module.case_details.short.multi_select = True self.module.search_config = CaseSearch( search_label=CaseSearchLabel(label={'en': 'Search'}), properties=[ CaseSearchProperty(name=field) for field in ['name', 'greatest_fear'] ], ) self.module.assign_references()
def test_sort_cache_search(self): app = Application.wrap(self.get_json('suite-advanced')) app.modules[0].search_config = CaseSearch( properties=[CaseSearchProperty(name='name', label={'en': 'Name'})], ) detail = app.modules[0].case_details.short detail.sort_elements.append( SortElement( field=detail.columns[0].field, type='index', direction='descending', blanks='first', ) ) self.assertXmlPartialEqual( self.get_xml('sort-cache-search'), app.create_suite(), "./detail[@id='m0_search_short']" )
def test_case_search_action(self): app = Application.wrap(self.get_json('suite-advanced')) app.modules[0].search_config = CaseSearch( search_label=CaseSearchLabel( label={'en': 'Get them'}, media_image={'en': "jr://file/commcare/image/1.png"}, media_audio={'en': "jr://file/commcare/image/2.mp3"} ), search_again_label=CaseSearchAgainLabel( label={'en': 'Get them'}, media_audio={'en': "jr://file/commcare/image/2.mp3"} ), properties=[CaseSearchProperty(name='name', label={'en': 'Name'})], ) # wrap to have assign_references called app = Application.wrap(app.to_json()) # test for legacy action node for older versions self.assertXmlPartialEqual( self.get_xml('case-search-with-action'), app.create_suite(), "./detail[@id='m0_case_short']/action" ) self.assertXmlPartialEqual( self.get_xml('case-search-again-with-action'), app.create_suite(), "./detail[@id='m0_search_short']/action" ) # test for localized action node for apps with CC version > 2.21 app.build_spec.version = '2.21.0' self.assertXmlPartialEqual( self.get_xml('case-search-with-localized-action'), app.create_suite(), "./detail[@id='m0_case_short']/action" ) self.assertXmlPartialEqual( self.get_xml('case-search-again-with-localized-action'), app.create_suite(), "./detail[@id='m0_search_short']/action" )
def case_claim_app_factory(cls): factory = cls(build_version='2.51.0') case_module, update_case_form = factory.new_basic_module('case_module', 'suite_test') register_module, register_form = factory.new_basic_module('register_case', 'suite_test') case_module.case_list_form.form_id = register_form.get_unique_id() case_module.case_list_form.label = { 'en': 'New Case', } case_module.search_config.command_label = { 'en': 'Find a Mother', } case_module.search_config.again_label = { 'en': 'Find Another Mother', } case_module.search_config.properties = [CaseSearchProperty( name='name', label={'en': 'Name of Mother'} )] return factory
def test_additional_types__shadow_module(self, *args): shadow_module = self.app.add_module(ShadowModule.new_module("shadow", "en")) shadow_module.source_module_id = self.module.get_or_create_unique_id() shadow_module.search_config = CaseSearch( search_label=CaseSearchLabel( label={ 'en': 'Search from Shadow Module' } ), properties=[ CaseSearchProperty(name='name', label={'en': 'Name'}), ], ) another_case_type = "another_case_type" self.module.search_config.additional_case_types = [another_case_type] app = Application.wrap(self.app.to_json()) suite_xml = app.create_suite() suite = parse_normalize(suite_xml, to_string=False) ref_path = './remote-request[2]/session/datum/@nodeset' self.assertEqual( "instance('{}')/{}/case[@case_type='{}' or @case_type='{}']{}".format( RESULTS_INSTANCE, RESULTS_INSTANCE, self.module.case_type, another_case_type, EXCLUDE_RELATED_CASES_FILTER ), suite.xpath(ref_path)[0] ) self.assertXmlPartialEqual( """ <partial> <data key="case_type" ref="'case'"/> <data key="case_type" ref="'another_case_type'"/> </partial> """, suite_xml, "./remote-request[2]/session/query/data[@key='case_type']" )
def test_get_related_case_relationships(self): app = Application.new_app(self.domain, "Case Search App") module = app.add_module(Module.new_module("Search Module", "en")) module.case_type = self.case_type detail = module.case_details.short detail.columns.extend([ DetailColumn(header={"en": "x"}, model="case", field="x", format="plain"), DetailColumn(header={"en": "y"}, model="case", field="parent/parent/y", format="plain"), DetailColumn(header={"en": "z"}, model="case", field="host/z", format="plain"), ]) module.search_config.properties = [ CaseSearchProperty( name="texture", label={"en": "Texture"}, ) ] module = app.add_module(Module.new_module("Non-Search Module", "en")) module.case_type = self.case_type detail = module.case_details.short detail.columns.append( DetailColumn(header={"en": "zz"}, model="case", field="parent/zz", format="plain"), ) self.assertEqual(get_related_case_relationships(app, self.case_type), {"parent/parent", "host"}) self.assertEqual(get_related_case_relationships(app, "monster"), set())
def test_multi_select_module_errors(self, *args): factory = AppFactory() module, form = factory.new_basic_module('basic', 'person') factory.form_requires_case(form, 'person') module.case_details.short.multi_select = True module.search_config = CaseSearch( search_label=CaseSearchLabel(label={'en': 'Search'}), properties=[CaseSearchProperty(name=field) for field in ['name', 'greatest_fear']], data_registry="so_many_cases", data_registry_workflow=REGISTRY_WORKFLOW_LOAD_CASE, ) self.assertIn({ 'type': 'data registry multi select', 'module': {'id': 0, 'unique_id': 'basic_module', 'name': {'en': 'basic module'}} }, factory.app.validate_app()) module.search_config.data_registry_workflow = REGISTRY_WORKFLOW_SMART_LINK self.assertIn({ 'type': 'smart links multi select', 'module': {'id': 0, 'unique_id': 'basic_module', 'name': {'en': 'basic module'}} }, factory.app.validate_app())
def test_modules_case_search_app_strings(self): factory = AppFactory(build_version='2.40.0') factory.app.langs = ['en', 'es'] factory.app.build_profiles = OrderedDict({ 'en': BuildProfile(langs=['en'], name='en-profile'), 'es': BuildProfile(langs=['es'], name='es-profile'), }) module, form = factory.new_basic_module('my_module', 'cases') module.search_config = CaseSearch( search_label=CaseSearchLabel( label={ 'en': 'Get them', 'es': 'Conseguirlos' }, media_image={ 'en': "jr://file/commcare/image/1.png", 'es': "jr://file/commcare/image/1_es.png" }, media_audio={'en': "jr://file/commcare/image/2.mp3"}), search_again_label=CaseSearchAgainLabel( label={'en': 'Get them all'}), properties=[CaseSearchProperty(name="name", label={'en': 'Name'})]) # wrap to have assign_references called app = Application.wrap(factory.app.to_json()) with flag_disabled('USH_CASE_CLAIM_UPDATES'): # default language self.assertEqual(app.default_language, 'en') en_app_strings = self._generate_app_strings(app, 'default', build_profile_id='en') self.assertEqual(en_app_strings['case_search.m0'], 'Search All Cases') self.assertEqual(en_app_strings['case_search.m0.again'], 'Search Again') self.assertFalse('case_search.m0.icon' in en_app_strings) self.assertFalse('case_search.m0.audio' in en_app_strings) # non-default language es_app_strings = self._generate_app_strings(app, 'es', build_profile_id='es') self.assertEqual(es_app_strings['case_search.m0'], 'Search All Cases') self.assertEqual(es_app_strings['case_search.m0.again'], 'Search Again') with flag_enabled('USH_CASE_CLAIM_UPDATES'): # default language en_app_strings = self._generate_app_strings(app, 'default', build_profile_id='en') self.assertEqual(en_app_strings['case_search.m0'], 'Get them') self.assertEqual(en_app_strings['case_search.m0.icon'], 'jr://file/commcare/image/1.png') self.assertEqual(en_app_strings['case_search.m0.audio'], 'jr://file/commcare/image/2.mp3') self.assertEqual(en_app_strings['case_search.m0.again'], 'Get them all') # non-default language es_app_strings = self._generate_app_strings(app, 'es', build_profile_id='es') self.assertEqual(es_app_strings['case_search.m0'], 'Conseguirlos') self.assertEqual(es_app_strings['case_search.m0.icon'], 'jr://file/commcare/image/1_es.png') self.assertEqual(es_app_strings['case_search.m0.again'], 'Get them all')
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_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)
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) 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") 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.wrap, short) if persist_case_context is not None: detail.short.persist_case_context = persist_case_context 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.wrap, 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 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'] detail.short.sort_elements.append(item) if parent_select is not None: module.parent_select = ParentSelect.wrap(parent_select) if fixture_select is not None: module.fixture_select = FixtureSelect.wrap(fixture_select) if search_properties is not None: module.search_config = CaseSearch(properties=[ CaseSearchProperty.wrap(p) for p in _update_search_properties(module, search_properties, lang) ]) # TODO: Add UI and controller support for CaseSearch.command_label resp = {} app.save(resp) return json_response(resp)
def setUp(self): super().setUp() self.app = Application.new_app(DOMAIN, "Application with Shadow") self.app._id = '456' self.app.build_spec = BuildSpec(version='2.53.0', build_number=1) self.module = self.app.add_module(Module.new_module("Followup", None)) self.form = self.app.new_form(0, "Untitled Form", None, attachment=get_simple_form("xmlns1.0")) self.form.requires = 'case' self.module.case_type = 'case' self.module.case_details.long.columns.append( DetailColumn.wrap(dict( header={"en": "name"}, model="case", format="plain", field="whatever", )) ) self.module.search_config = CaseSearch( properties=[ CaseSearchProperty(name='name', label={'en': 'Name'}), CaseSearchProperty(name='favorite_color', label={'en': 'Favorite Color'}, itemset=Itemset( instance_id='item-list:colors', instance_uri='jr://fixture/item-list:colors', nodeset="instance('item-list:colors')/colors_list/colors", label='name', sort='name', value='value'), ) ], data_registry="myregistry", data_registry_workflow=REGISTRY_WORKFLOW_LOAD_CASE, additional_registry_cases=["'another case ID'"], ) self.shadow_module = self.app.add_module(ShadowModule.new_module("Shadow", "en")) self.shadow_module.source_module_id = self.module.unique_id self.shadow_module.case_details.long.columns.append( DetailColumn.wrap(dict( header={"en": "name"}, model="case", format="plain", field="whatever", )) ) self.shadow_module.search_config = CaseSearch( properties=[ CaseSearchProperty(name='name', label={'en': 'Name'}), CaseSearchProperty(name='favorite_color', label={'en': 'Texture'}, itemset=Itemset( instance_id='item-list:textures', instance_uri='jr://fixture/item-list:textures', nodeset="instance('item-list:textures')/textures_list/textures", label='name', sort='name', value='value'), ) ], data_registry="myregistry", data_registry_workflow=REGISTRY_WORKFLOW_LOAD_CASE, ) # wrap to have assign_references called self.app = Application.wrap(self.app.to_json()) # reset to newly wrapped module self.module = self.app.modules[0] self.shadow_module = self.app.modules[1]
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 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") 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 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 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)) resp = {} app.save(resp) return json_response(resp)