def test_relationship_invalid(self): with self.assertRaises(TypeError): as_value_source({ 'supercase_value_source': { 'case_property': 'foo' }, 'relationship': 'invalid', })
def test_subcase_value_source(self): value_source = as_value_source({ 'subcase_value_source': { 'case_property': 'foo' }, }) self.assertIsInstance(value_source, SubcaseValueSource)
def test_set_external_data(self): value_source_configs = [{ 'case_property': 'value', 'jsonpath': '$.valueQuantity.value', 'external_data_type': COMMCARE_DATA_TYPE_DECIMAL, }, { 'value': 'degrees Celsius', 'jsonpath': '$.valueQuantity.unit', }, { 'supercase_value_source': { 'case_property': 'case_id', 'jsonpath': '$.subject.reference', }, 'identifier': 'parent', 'referenced_type': 'person', }, { 'supercase_value_source': { 'case_property': 'name', 'jsonpath': '$.subject.display', }, 'identifier': 'parent', 'referenced_type': 'person', }] resources = [] for case in (self.child_case_1, self.child_case_2): external_data = {} info = get_case_trigger_info_for_case(case, value_source_configs) for value_source_config in value_source_configs: value_source = as_value_source(value_source_config) value_source.set_external_value(external_data, info) resources.append(external_data) self.assertEqual( resources, [ { 'subject': { 'reference': self.parent_case_id, 'display': 'Joe', }, 'valueQuantity': { 'value': 36.2, # case 1 'unit': 'degrees Celsius', }, }, { 'subject': { 'reference': self.parent_case_id, 'display': 'Joe', }, 'valueQuantity': { 'value': 36.6, # case 2 'unit': 'degrees Celsius', }, } ])
def test_with_location_field_doc_type(self): json_object = as_value_source({ "doc_type": "CaseOwnerAncestorLocationField", "location_field": "dhis_id", }) self.assertIsInstance(json_object, CaseOwnerAncestorLocationField) self.assertEqual(json_object.case_owner_ancestor_location_field, "dhis_id")
def test_blank_path(self): json_doc = {"foo": {"bar": "baz"}} value_source = as_value_source({ "case_property": "bar", "jsonpath": "", }) with self.assertRaises(JsonpathError): value_source.get_import_value(json_doc)
def test_case_types(self): value_source = as_value_source({ 'subcase_value_source': { 'case_property': 'foo' }, 'case_types': ['bar'], }) self.assertIsInstance(value_source, SubcaseValueSource)
def test_is_closed(self): value_source = as_value_source({ 'subcase_value_source': { 'case_property': 'foo' }, 'is_closed': False, }) self.assertIsInstance(value_source, SubcaseValueSource)
def test_one_value(self): json_doc = {"foo": {"bar": "baz"}} value_source = as_value_source({ "case_property": "bar", "jsonpath": "foo.bar", }) external_value = value_source.get_import_value(json_doc) self.assertEqual(external_value, "baz")
def get_export_data(config, properties, case_trigger_info): export_data = {} for property_, value_source_config in config.items(): value_source = as_value_source(value_source_config) if (property_ in properties and value_source.can_export and value_source.get_value(case_trigger_info)): export_data[property_] = value_source.get_value(case_trigger_info) return export_data
def test_no_values(self): json_doc = {"foo": {"bar": "baz"}} value_source = as_value_source({ "case_property": "bar", "jsonpath": "foo.qux", }) external_value = value_source.get_import_value(json_doc) self.assertIsNone(external_value)
def test_relationship(self): value_source = as_value_source({ 'supercase_value_source': { 'case_property': 'foo' }, 'relationship': 'extension', }) self.assertIsInstance(value_source, SupercaseValueSource)
def test_referenced_type(self): value_source = as_value_source({ 'supercase_value_source': { 'case_property': 'foo' }, 'referenced_type': 'bar', }) self.assertIsInstance(value_source, SupercaseValueSource)
def test_identifier(self): value_source = as_value_source({ 'supercase_value_source': { 'case_property': 'foo' }, 'identifier': 'bar', }) self.assertIsInstance(value_source, SupercaseValueSource)
def test_many_values(self): json_doc = {"foo": [{"bar": "baz"}, {"bar": "qux"}]} value_source = as_value_source({ "case_property": "bar", "jsonpath": "foo[*].bar", }) external_value = value_source.get_import_value(json_doc) self.assertEqual(external_value, ["baz", "qux"])
def test_doc_type(self): case_property = as_value_source({ "doc_type": "CaseProperty", "case_property": "foo", }) self.assertIsInstance(case_property, CaseProperty) self.assertEqual(case_property.case_property, "foo") with self.assertRaises(AttributeError): case_property.doc_type
def get_value_source(self) -> ValueSource: """ Returns a ValueSource for building FHIR resources. """ if self.value_source_config: return as_value_source(self.value_source_config) if not (self.case_property and self.jsonpath): raise ConfigurationError( 'Unable to set FHIR resource property value without case ' 'property and JSONPath.') value_source_config = { 'case_property': self.case_property.name, 'jsonpath': self.jsonpath, } if self.value_map: value_source_config['value_map'] = self.value_map return as_value_source(value_source_config)
def test_with_form_user_ancestor_location_field_doc_type(self): json_object = as_value_source({ "doc_type": "FormUserAncestorLocationField", "form_user_ancestor_location_field": "dhis_id", }) self.assertIsInstance(json_object, FormUserAncestorLocationField) self.assertEqual(json_object.form_user_ancestor_location_field, "dhis_id")
def test_deserialize(self): """ deserialize() should convert from external data type to CommCare data type """ one = as_value_source({ "value": 1.0, "value_data_type": COMMCARE_DATA_TYPE_DECIMAL, "commcare_data_type": COMMCARE_DATA_TYPE_TEXT, "external_data_type": COMMCARE_DATA_TYPE_INTEGER, }) self.assertEqual(one.deserialize("foo"), '1')
def get_encounter_datetime_value_sources( repeater: OpenmrsRepeater) -> List[ValueSource]: value_sources = [] for form_config in repeater.openmrs_config.form_configs: encounter_datetime_config = form_config.openmrs_start_datetime if encounter_datetime_config and "case_property" in encounter_datetime_config: value_source = as_value_source(encounter_datetime_config) if value_source.can_import: if not value_source.jsonpath: value_source.jsonpath = "encounterDateTime" value_sources.append(value_source) return value_sources
def test_get_commcare_value(self): """ get_commcare_value() should convert from value data type to CommCare data type """ one = as_value_source({ "value": 1.0, "value_data_type": COMMCARE_DATA_TYPE_DECIMAL, "commcare_data_type": COMMCARE_DATA_TYPE_INTEGER, "external_data_type": COMMCARE_DATA_TYPE_TEXT, }) self.assertEqual(one.get_commcare_value('foo'), 1)
def _get_values_for_concept(self, form_config): values_for_concept = {} for obs in form_config.openmrs_observations: if not obs.concept: # Skip ObservationMappings for importing all observations. continue value_source = as_value_source(obs.value) if value_source.can_export and not is_blank( value_source.get_value(self.info)): values_for_concept[obs.concept] = [ value_source.get_value(self.info) ] return values_for_concept
def get_diagnosis_mappings( repeater: OpenmrsRepeater ) -> DefaultDict[str, List[ObservationMapping]]: diag_mappings = defaultdict(list) for form_config in repeater.openmrs_config.form_configs: for diag_mapping in form_config.bahmni_diagnoses: value_source = as_value_source(diag_mapping.value) if (value_source.can_import and (diag_mapping.case_property or diag_mapping.indexed_case_mapping)): concept = diag_mapping.concept or None diag_mappings[concept].append(diag_mapping) return diag_mappings
def run(self): """ Returns WorkflowTasks for creating and updating OpenMRS patient identifiers. """ subtasks = [] existing_patient_identifiers = { identifier['identifierType']['uuid']: (identifier['uuid'], identifier['identifier']) for identifier in self.patient['identifiers'] } for patient_identifier_type, dict_ in self.openmrs_config.case_config.patient_identifiers.items( ): value_source = as_value_source(dict_) if not value_source.can_export: continue if patient_identifier_type == PERSON_UUID_IDENTIFIER_TYPE_ID: # Don't try to sync the OpenMRS person UUID; It's not a # user-defined identifier and it can't be changed. continue identifier = value_source.get_value(self.info) # If the patient is new, and its case property that # corresponds to the identifier is blank, then the # patient's identifier will have been generated by # repeater_helpers.generate_identifier(). The case will have # been updated by repeater_helpers.save_match_ids() but # self.info will not contain the newly-generated identifier. # `identifier` will be None. Don't try to update the # patient's identifier to None; it's already set correctly. if not identifier: continue if patient_identifier_type in existing_patient_identifiers: identifier_uuid, existing_identifier = existing_patient_identifiers[ patient_identifier_type] if identifier != existing_identifier: subtasks.append( UpdatePatientIdentifierTask(self.requests, self.patient['uuid'], identifier_uuid, patient_identifier_type, identifier, existing_identifier)) else: subtasks.append( CreatePatientIdentifierTask(self.requests, self.patient['uuid'], patient_identifier_type, identifier)) return subtasks
def get_identifiers(): identifiers = [] for patient_identifier_type, value_source_config in case_config.patient_identifiers.items( ): value_source = as_value_source(value_source_config) if (patient_identifier_type != PERSON_UUID_IDENTIFIER_TYPE_ID and value_source.can_export): identifier = (value_source.get_value(info) or generate_identifier(requests, patient_identifier_type)) if identifier: identifiers.append({ 'identifierType': patient_identifier_type, 'identifier': identifier }) return identifiers
def test_as_value_source(self): @attr.s(auto_attribs=True, kw_only=True) class StringValueSource(ValueSource): test_value: str @classmethod def get_schema_params(cls): (schema, *other_args), kwargs = super().get_schema_params() schema.update({"test_value": Use(str)}) # Casts value as string return (schema, *other_args), kwargs data = {"test_value": 10} value_source = as_value_source(data) self.assertEqual(data, {"test_value": 10}) self.assertIsInstance(value_source, StringValueSource) self.assertEqual(value_source.test_value, "10")
def get_values_for_concept(form_config, info): """ Returns a dictionary mapping OpenMRS concept UUIDs to lists of values. Each value will be exported as a separate Observation. """ values_for_concept = defaultdict(list) for obs in form_config.openmrs_observations: if obs.concept == ALL_CONCEPTS: # ALL_CONCEPTS is a special value for importing all # Observations as extension cases. It's not applicable here. continue value_source = as_value_source(obs.value) if value_source.can_export and not is_blank( value_source.get_value(info)): values_for_concept[obs.concept].append( value_source.get_value(info)) return values_for_concept
def get_observation_mappings( repeater: OpenmrsRepeater ) -> DefaultDict[str, List[ObservationMapping]]: obs_mappings = defaultdict(list) for form_config in repeater.openmrs_config.form_configs: for obs_mapping in form_config.openmrs_observations: value_source = as_value_source(obs_mapping.value) if (value_source.can_import and (obs_mapping.case_property or obs_mapping.indexed_case_mapping)): # If obs_mapping.concept is "" or None, the mapping # should apply to any concept concept = obs_mapping.concept or None # It's possible that an OpenMRS concept appears more # than once in form_configs. We are using a # defaultdict(list) so that earlier definitions # don't get overwritten by later ones: obs_mappings[concept].append(obs_mapping) return obs_mappings
def get_case_block_for_indexed_case( mapping: ObservationMapping, external_data: dict, parent_case_attrs: CaseAttrs, ) -> CaseBlock: parent_case_id, parent_case_type, default_owner_id = parent_case_attrs relationship = mapping.indexed_case_mapping.relationship case_block_kwargs = { "index": { mapping.indexed_case_mapping.identifier: IndexAttrs( parent_case_type, parent_case_id, relationship, ) }, "update": {} } for value_source_config in mapping.indexed_case_mapping.case_properties: value_source = as_value_source(value_source_config) value = value_source.get_import_value(external_data) if value_source.case_property in CASE_BLOCK_ARGS: case_block_kwargs[value_source.case_property] = value else: case_block_kwargs["update"][value_source.case_property] = value case_id = uuid.uuid4().hex case_type = mapping.indexed_case_mapping.case_type case_block_kwargs.setdefault("owner_id", default_owner_id) if not case_block_kwargs["owner_id"]: raise ConfigurationError(_( f'Unable to determine mobile worker to own new "{case_type}" ' f'{relationship} case or parent case "{parent_case_id}"' )) case_block = CaseBlock( create=True, case_id=case_id, case_type=case_type, **case_block_kwargs ) return case_block
def run(self): """ Returns WorkflowTasks for creating and updating OpenMRS person attributes. """ subtasks = [] existing_person_attributes = { attribute['attributeType']['uuid']: (attribute['uuid'], attribute['value']) for attribute in self.attributes } for person_attribute_type, value_source_dict in self.openmrs_config.case_config.person_attributes.items( ): value_source = as_value_source(value_source_dict) if not value_source.can_export: continue value = value_source.get_value(self.info) if person_attribute_type in existing_person_attributes: attribute_uuid, existing_value = existing_person_attributes[ person_attribute_type] if value != existing_value: if value in ("", None): subtasks.append( DeletePersonAttributeTask(self.requests, self.person_uuid, attribute_uuid, person_attribute_type, existing_value)) else: subtasks.append( UpdatePersonAttributeTask(self.requests, self.person_uuid, attribute_uuid, person_attribute_type, value, existing_value)) else: subtasks.append( CreatePersonAttributeTask(self.requests, self.person_uuid, person_attribute_type, value)) return subtasks
def test_set_external_data(self): value_source_configs = [ { 'case_property': 'name', 'jsonpath': '$.name[0].text', }, { 'subcase_value_source': { 'case_property': 'given_names', # Use counter1 to skip the name set by the parent case 'jsonpath': '$.name[{counter1}].given[0]', }, 'case_types': ['person_name'], }, { 'subcase_value_source': { 'case_property': 'family_name', 'jsonpath': '$.name[{counter1}].family', }, 'case_types': ['person_name'], } ] external_data = {} case_trigger_info = get_case_trigger_info_for_case( self.host_case, value_source_configs, ) for value_source_config in value_source_configs: value_source = as_value_source(value_source_config) value_source.set_external_value(external_data, case_trigger_info) name = external_data['name'] self.assertIn({'text': 'Ted'}, name) self.assertIn({ 'given': ['Theodore John'], 'family': 'Kaczynski' }, name) self.assertIn({'given': ['Unabomber']}, name)