def update_patient(repeater, patient_uuid): """ Fetch patient from OpenMRS, submit case update for all mapped case properties. .. NOTE:: OpenMRS UUID must be saved to "external_id" case property """ _assert( len(repeater.white_listed_case_types) == 1, 'Unable to update patients from OpenMRS unless a single case type is ' 'specified. domain: "{}". repeater: "{}".'.format( repeater.domain, repeater.get_id ) ) case_type = repeater.white_listed_case_types[0] patient = get_patient_by_uuid(repeater.requests, patient_uuid) case, error = importer_util.lookup_case( EXTERNAL_ID, patient_uuid, repeater.domain, case_type=case_type, ) if error == LookupErrors.NotFound: owner = get_one_commcare_user_at_location(repeater.domain, repeater.location_id) _assert( owner, 'No users found at location "{}" to own patients added from ' 'OpenMRS atom feed. domain: "{}". repeater: "{}".'.format( repeater.location_id, repeater.domain, repeater.get_id ) ) case_block = get_addpatient_caseblock(case_type, owner, patient, repeater) else: _assert( error != LookupErrors.MultipleResults, # Multiple cases matched to the same patient. # Could be caused by: # * The cases were given the same identifier value. It could # be user error, or case config assumed identifier was # unique but it wasn't. # * PatientFinder matched badly. # * Race condition where a patient was previously added to # both CommCare and OpenMRS. 'More than one case found matching unique OpenMRS UUID. ' 'domain: "{}". case external_id: "{}". repeater: "{}".'.format( repeater.domain, patient_uuid, repeater.get_id ) ) case_block = get_updatepatient_caseblock(case, patient, repeater) if case_block: submit_case_blocks( [case_block.as_string()], repeater.domain, xmlns=XMLNS_OPENMRS, device_id=OPENMRS_ATOM_FEED_DEVICE_ID + repeater.get_id, )
def update_patient(repeater, patient_uuid): """ Fetch patient from OpenMRS, submit case update for all mapped case properties. .. NOTE:: OpenMRS UUID must be saved to "external_id" case property """ if len(repeater.white_listed_case_types) != 1: raise ConfigurationError( _(f'{repeater.domain}: {repeater}: Error in settings: Unable to update ' f'patients from OpenMRS unless only one case type is specified.') ) case_type = repeater.white_listed_case_types[0] try: patient = get_patient_by_uuid(repeater.requests, patient_uuid) except (RequestException, ValueError) as err: raise OpenmrsException( _(f'{repeater.domain}: {repeater}: Error fetching Patient ' f'{patient_uuid!r}: {err}')) from err case, error = importer_util.lookup_case( EXTERNAL_ID, patient_uuid, repeater.domain, case_type=case_type, ) if error == LookupErrors.NotFound: if not repeater.openmrs_config.case_config.import_creates_cases: # We can't create cases via the Atom feed, just update them. # Nothing to do here. return default_owner: Optional[CommCareUser] = repeater.first_user case_block = get_addpatient_caseblock(case_type, default_owner, patient, repeater) elif error == LookupErrors.MultipleResults: # Multiple cases have been matched to the same patient. # Could be caused by: # * The cases were given the same identifier value. It could # be user error, or case config assumed identifier was # unique but it wasn't. # * PatientFinder matched badly. # * Race condition where a patient was previously added to # both CommCare and OpenMRS. raise DuplicateCaseMatch( _(f'{repeater.domain}: {repeater}: More than one case found ' f'matching unique OpenMRS UUID. case external_id: "{patient_uuid}"' )) else: case_block = get_updatepatient_caseblock(case, patient, repeater) if case_block: submit_case_blocks( [case_block.as_text()], repeater.domain, xmlns=XMLNS_OPENMRS, device_id=OPENMRS_ATOM_FEED_DEVICE_ID + repeater.get_id, )
def create_case( repeater: OpenmrsRepeater, patient_uuid: str, ) -> CaseBlock: case_type = repeater.white_listed_case_types[0] patient = get_patient_by_uuid(repeater.requests, patient_uuid) default_owner: Optional[CommCareUser] = repeater.first_user case_block = get_addpatient_caseblock(case_type, default_owner, patient, repeater) return case_block
def update_patient(repeater, patient_uuid): """ Fetch patient from OpenMRS, submit case update for all mapped case properties. .. NOTE:: OpenMRS UUID must be saved to "external_id" case property """ _assert( len(repeater.white_listed_case_types) == 1, 'Unable to update patients from OpenMRS unless a single case type is ' 'specified. domain: "{}". repeater: "{}".'.format( repeater.domain, repeater.get_id)) case_type = repeater.white_listed_case_types[0] patient = get_patient_by_uuid(repeater.requests, patient_uuid) case, error = importer_util.lookup_case( EXTERNAL_ID, patient_uuid, repeater.domain, case_type=case_type, ) if error == LookupErrors.NotFound: owner = get_one_commcare_user_at_location(repeater.domain, repeater.location_id) _assert( owner, 'No users found at location "{}" to own patients added from ' 'OpenMRS atom feed. domain: "{}". repeater: "{}".'.format( repeater.location_id, repeater.domain, repeater.get_id)) case_block = get_addpatient_caseblock(case_type, owner, patient, repeater) else: _assert( error != LookupErrors.MultipleResults, # Multiple cases matched to the same patient. # Could be caused by: # * The cases were given the same identifier value. It could # be user error, or case config assumed identifier was # unique but it wasn't. # * PatientFinder matched badly. # * Race condition where a patient was previously added to # both CommCare and OpenMRS. 'More than one case found matching unique OpenMRS UUID. ' 'domain: "{}". case external_id: "{}". repeater: "{}".'.format( repeater.domain, patient_uuid, repeater.get_id)) case_block = get_updatepatient_caseblock(case, patient, repeater) if case_block: submit_case_blocks( [case_block.as_text()], repeater.domain, xmlns=XMLNS_OPENMRS, device_id=OPENMRS_ATOM_FEED_DEVICE_ID + repeater.get_id, )
def test_valid_uuid(self): patient = get_patient_by_uuid(self.requests, uuid='c83d9989-585f-4db3-bf55-ca1d0ee7c0af') self.assertEqual(patient, self.patient)
def test_invalid_uuid(self): with self.assertRaises(ValueError): # OpenMRS UUIDs have "-" separators get_patient_by_uuid(self.requests, uuid='c83d9989585f4db3bf55ca1d0ee7c0af')
def test_empty(self): patient = get_patient_by_uuid(self.requests, uuid='') self.assertIsNone(patient)
def test_none(self): patient = get_patient_by_uuid(self.requests, uuid=None) self.assertIsNone(patient)
def test_invalid_uuid(self): patient = get_patient_by_uuid(self.requests, uuid='c83d9989585f4db3bf55ca1d0ee7c0af') # OpenMRS UUIDs have "-" separators self.assertIsNone(patient)
def import_encounter(repeater, encounter_uuid): # It's possible that an OpenMRS concept appears more than once in # form_configs. Use a defaultdict(list) so that earlier definitions # don't get overwritten by later ones: def fields_from_observations(observations, mappings): """ Traverse a tree of observations, and return the ones mapped to case properties. """ fields = {} for obs in observations: if obs['concept']['uuid'] in mappings: for mapping in mappings[obs['concept']['uuid']]: fields[mapping.case_property] = mapping.value.deserialize( obs['value']) if obs['groupMembers']: fields.update( fields_from_observations(obs['groupMembers'], mappings)) return fields response = repeater.requests.get( '/ws/rest/v1/bahmnicore/bahmniencounter/' + encounter_uuid, {'includeAll': 'true'}, raise_for_status=True) encounter = response.json() case_property_updates = fields_from_observations( encounter['observations'], repeater.observation_mappings) if case_property_updates: case_blocks = [] patient_uuid = encounter['patientUuid'] case_type = repeater.white_listed_case_types[0] case, error = importer_util.lookup_case( EXTERNAL_ID, patient_uuid, repeater.domain, case_type=case_type, ) if case: case_id = case.get_id elif error == LookupErrors.NotFound: # The encounter is for a patient that has not yet been imported patient = get_patient_by_uuid(repeater.requests, patient_uuid) owner = get_one_commcare_user_at_location(repeater.domain, repeater.location_id) case_block = get_addpatient_caseblock(case_type, owner, patient, repeater) case_blocks.append(case_block) case_id = case_block.case_id else: _assert( error != LookupErrors.MultipleResults, 'More than one case found matching unique OpenMRS UUID. ' 'domain: "{}". case external_id: "{}". repeater: "{}".'.format( repeater.domain, patient_uuid, repeater.get_id)) return case_blocks.append( CaseBlock( case_id=case_id, create=False, update=case_property_updates, )) submit_case_blocks( [cb.as_text() for cb in case_blocks], repeater.domain, xmlns=XMLNS_OPENMRS, device_id=OPENMRS_ATOM_FEED_DEVICE_ID + repeater.get_id, )
def import_encounter(repeater, encounter_uuid): # It's possible that an OpenMRS concept appears more than once in # form_configs. Use a defaultdict(list) so that earlier definitions # don't get overwritten by later ones: def fields_from_observations(observations, mappings): """ Traverse a tree of observations, and return the ones mapped to case properties. """ fields = {} for obs in observations: if obs['concept']['uuid'] in mappings: for mapping in mappings[obs['concept']['uuid']]: fields[mapping.case_property] = mapping.value.deserialize(obs['value']) if obs['groupMembers']: fields.update(fields_from_observations(obs['groupMembers'], mappings)) return fields response = repeater.requests.get( '/ws/rest/v1/bahmnicore/bahmniencounter/' + encounter_uuid, {'includeAll': 'true'}, raise_for_status=True ) encounter = response.json() case_property_updates = fields_from_observations(encounter['observations'], repeater.observation_mappings) if case_property_updates: case_blocks = [] patient_uuid = encounter['patientUuid'] case_type = repeater.white_listed_case_types[0] case, error = importer_util.lookup_case( EXTERNAL_ID, patient_uuid, repeater.domain, case_type=case_type, ) if case: case_id = case.get_id elif error == LookupErrors.NotFound: # The encounter is for a patient that has not yet been imported patient = get_patient_by_uuid(repeater.requests, patient_uuid) owner = get_one_commcare_user_at_location(repeater.domain, repeater.location_id) case_block = get_addpatient_caseblock(case_type, owner, patient, repeater) case_blocks.append(case_block) case_id = case_block.case_id else: _assert( error != LookupErrors.MultipleResults, 'More than one case found matching unique OpenMRS UUID. ' 'domain: "{}". case external_id: "{}". repeater: "{}".'.format( repeater.domain, patient_uuid, repeater.get_id ) ) return case_blocks.append(CaseBlock( case_id=case_id, create=False, update=case_property_updates, )) submit_case_blocks( [cb.as_string() for cb in case_blocks], repeater.domain, xmlns=XMLNS_OPENMRS, device_id=OPENMRS_ATOM_FEED_DEVICE_ID + repeater.get_id, )