Class: DdeService
- Inherits:
-
Object
- Object
- DdeService
- Includes:
- ModelUtils
- Defined in:
- app/services/dde_service.rb
Defined Under Namespace
Classes: DdeMahisError
Constant Summary collapse
- DdeMahis_CONFIG_PATH =
Rails.root.join('config', 'dde.yml')
- LOGGER =
Rails.logger
- PATIENT_SEARCH_RESULTS_LIMIT =
Limit all find queries for local patients to this
10
Instance Attribute Summary collapse
-
#visit_type ⇒ Object
Returns the value of attribute visit_type.
Class Method Summary collapse
Instance Method Summary collapse
-
#create_patient(patient) ⇒ Object
Registers local OpenMRS patient in DdeMahis.
-
#create_patient_footprint(patient, date = nil, creator_id = nil) ⇒ Object
Pushes a footprint for patient in current visit_type to DdeMahis.
-
#dde_patient_to_local_person(dde_patient) ⇒ Object
Converts a dde_patient object into an object that can be passed to the person_service to create or update a person.
- #find_patient_updates(local_patient_id) ⇒ Object
- #find_patients_by_name_and_gender(given_name, family_name, gender) ⇒ Object
- #find_patients_by_npid(npid) ⇒ Object
-
#import_patients_by_doc_id(doc_id) ⇒ Object
Import patients from DdeMahis using doc id.
-
#import_patients_by_name_and_gender(given_name, family_name, gender) ⇒ Object
Similar to import_patients_by_npid but uses name and gender instead of npid.
-
#import_patients_by_npid(npid) ⇒ Object
Imports patients from DdeMahis to the local database.
-
#initialize(visit_type:) ⇒ DdeService
constructor
A new instance of DdeService.
-
#match_patients_by_demographics(family_name:, given_name:, birthdate:, gender:, home_district:, home_traditional_authority:, home_village:, birthdate_estimated: 0) ⇒ Object
Matches patients using a bunch of demographics.
-
#merge_patients(primary_patients_ids, secondary_patient_ids) ⇒ Object
Trigger a merge of patients in DdeMahis.
- #reassign_patient_npid(patient_ids) ⇒ Object
- #remaining_npids ⇒ Object
-
#save_remote_patient(remote_patient) ⇒ Object
Convert a DdeMahis person to an openmrs person.
- #test_connection ⇒ Object
-
#update_local_patient(patient, update_npid: false) ⇒ Object
Updates local patient with demographics currently in DdeMahis.
-
#update_patient(patient) ⇒ Object
Updates patient demographics in DdeMahis.
- #void_patient(patient, reason) ⇒ Object
Methods included from ModelUtils
#concept, #concept_id_to_name, #concept_name, #concept_name_to_id, #drug, #encounter_type, #global_property, #order_type, #patient_identifier_type, #report_type, #user_property
Constructor Details
#initialize(visit_type:) ⇒ DdeService
Returns a new instance of DdeService.
18 19 20 21 22 |
# File 'app/services/dde_service.rb', line 18 def initialize(visit_type:) raise InvalidParameterError, 'VisitType (visit_type_id) is required' unless visit_type @visit_type = visit_type end |
Instance Attribute Details
#visit_type ⇒ Object
Returns the value of attribute visit_type.
14 15 16 |
# File 'app/services/dde_service.rb', line 14 def visit_type @visit_type end |
Class Method Details
.dde_enabled? ⇒ Boolean
24 25 26 27 28 29 30 31 32 33 |
# File 'app/services/dde_service.rb', line 24 def self.dde_enabled? property = GlobalProperty.find_by_property('dde_enabled')&.property_value return false unless property case property when /true/i then true when /false/i then false else raise "Invalid value for property dde_enabled: #{property.property_value}" end end |
Instance Method Details
#create_patient(patient) ⇒ Object
Registers local OpenMRS patient in DdeMahis
On success patient get two identifiers under the types 'Dde Person Document ID' and 'National id'. The 'Dde Person Document ID' is the patient's record ID in the local DdeMahis instance and the 'National ID' is the national unique identifier for the patient.
55 56 57 |
# File 'app/services/dde_service.rb', line 55 def create_patient(patient) push_local_patient_to_dde(patient) end |
#create_patient_footprint(patient, date = nil, creator_id = nil) ⇒ Object
Pushes a footprint for patient in current visit_type to DdeMahis
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
# File 'app/services/dde_service.rb', line 97 def create_patient_footprint(patient, date = nil, creator_id = nil) LOGGER.debug("Pushing footprint to DdeMahis for patient ##{patient.patient_id}") doc_id = find_patient_doc_id(patient) unless doc_id LOGGER.debug("Patient ##{patient.patient_id} is not a DdeMahis patient") return end response, status = dde_client.post('update_footprint', person_uuid: doc_id, location_id: Location.current_location_health_center.location_id, visit_type_id: visit_type.id, encounter_datetime: date || Date.tody, user_id: creator_id || User.current.user_id) LOGGER.warn("Failed to push patient footprint to DdeMahis: #{status} - #{response}") unless status == 200 end |
#dde_patient_to_local_person(dde_patient) ⇒ Object
Converts a dde_patient object into an object that can be passed to the person_service to create or update a person.
293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 |
# File 'app/services/dde_service.rb', line 293 def dde_patient_to_local_person(dde_patient) attributes = dde_patient.fetch('attributes') # ActiveSupport::HashWithIndifferentAccess.new( # birthdate: dde_patient.fetch('birthdate'), # birthdate_estimated: dde_patient.fetch('birthdate_estimated'), # gender: dde_patient.fetch('gender'), # given_name: dde_patient.fetch('given_name'), # family_name: dde_patient.fetch('family_name'), # middle_name: dde_patient.fetch('middle_name'), # home_village: attributes.fetch('home_village'), # home_traditional_authority: attributes.fetch('home_traditional_authority'), # home_district: attributes.fetch('home_district'), # current_village: attributes.fetch('current_village'), # current_traditional_authority: attributes.fetch('current_traditional_authority'), # current_district: attributes.fetch('current_district') # # cell_phone_number: attributes.fetch('cellphone_number'), # # occupation: attributes.fetch('occupation') # ) { birthdate: dde_patient.fetch('birthdate'), birthdate_estimated: dde_patient.fetch('birthdate_estimated'), gender: dde_patient.fetch('gender'), names: [ { given_name: dde_patient.fetch('given_name'), family_name: dde_patient.fetch('family_name'), middle_name: dde_patient.fetch('middle_name') } ], addresses: [ { address1: attributes.fetch('home_district'), address3: attributes.fetch('current_district'), county_district: attributes.fetch('home_traditional_authority'), state_province: attributes.fetch('current_traditional_authority'), address2: attributes.fetch('home_village'), city_village: attributes.fetch('current_village') } ] } end |
#find_patient_updates(local_patient_id) ⇒ Object
191 192 193 194 195 196 197 198 199 200 201 202 203 204 |
# File 'app/services/dde_service.rb', line 191 def find_patient_updates(local_patient_id) dde_doc_id_type = PatientIdentifierType.where(name: 'Dde Person Document ID') doc_id = PatientIdentifier.find_by(patient_id: local_patient_id, identifier_type: dde_doc_id_type) &.identifier return nil unless doc_id remote_patient = find_remote_patients_by_doc_id(doc_id).first return nil unless remote_patient Matcher.find_differences(Person.find(local_patient_id), remote_patient) rescue DdeMahisError => e Rails.logger.warn("Check for DdeMahis patient updates failed: #{e.message}") nil end |
#find_patients_by_name_and_gender(given_name, family_name, gender) ⇒ Object
178 179 180 181 182 183 184 185 186 187 188 189 |
# File 'app/services/dde_service.rb', line 178 def find_patients_by_name_and_gender(given_name, family_name, gender) locals = [] begin locals = patient_service.find_patients_by_name_and_gender(given_name, family_name, gender).limit(PATIENT_SEARCH_RESULTS_LIMIT) remotes = find_remote_patients_by_name_and_gender(given_name, family_name, gender) package_patients(locals, remotes) rescue StandardError => e Rails.logger.warn("Error packaging patients: #{e.message}") package_patients(locals, []) end end |
#find_patients_by_npid(npid) ⇒ Object
171 172 173 174 175 176 |
# File 'app/services/dde_service.rb', line 171 def find_patients_by_npid(npid) locals = patient_service.find_patients_by_npid(npid).limit(PATIENT_SEARCH_RESULTS_LIMIT) remotes = find_remote_patients_by_npid(npid) package_patients(locals, remotes, auto_push_singular_local: true) end |
#import_patients_by_doc_id(doc_id) ⇒ Object
Import patients from DdeMahis using doc id
141 142 143 144 145 146 147 |
# File 'app/services/dde_service.rb', line 141 def import_patients_by_doc_id(doc_id) doc_id_type = patient_identifier_type('Dde Person Document ID') locals = patient_service.find_patients_by_identifier(doc_id, doc_id_type).limit(PATIENT_SEARCH_RESULTS_LIMIT) remotes = find_remote_patients_by_doc_id(doc_id) import_remote_patient(locals, remotes) end |
#import_patients_by_name_and_gender(given_name, family_name, gender) ⇒ Object
Similar to import_patients_by_npid but uses name and gender instead of npid
159 160 161 162 163 164 165 166 167 168 169 |
# File 'app/services/dde_service.rb', line 159 def import_patients_by_name_and_gender(given_name, family_name, gender) locals = patient_service.find_patients_by_name_and_gender(given_name, family_name, gender).limit(PATIENT_SEARCH_RESULTS_LIMIT) remotes = begin find_remote_patients_by_name_and_gender(given_name, family_name, gender) rescue StandardError [] end import_remote_patient(locals, remotes) end |
#import_patients_by_npid(npid) ⇒ Object
Imports patients from DdeMahis to the local database
150 151 152 153 154 155 156 |
# File 'app/services/dde_service.rb', line 150 def import_patients_by_npid(npid) doc_id_type = patient_identifier_type('National id') locals = patient_service.find_patients_by_identifier(npid, doc_id_type).limit(PATIENT_SEARCH_RESULTS_LIMIT) remotes = find_remote_patients_by_npid(npid) import_remote_patient(locals, remotes) end |
#match_patients_by_demographics(family_name:, given_name:, birthdate:, gender:, home_district:, home_traditional_authority:, home_village:, birthdate_estimated: 0) ⇒ Object
Matches patients using a bunch of demographics
207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 |
# File 'app/services/dde_service.rb', line 207 def match_patients_by_demographics(family_name:, given_name:, birthdate:, gender:, home_district:, home_traditional_authority:, home_village:, birthdate_estimated: 0) response, status = dde_client.post( 'search/people', family_name: family_name, given_name: given_name, gender: gender, birthdate: birthdate, birthdate_estimated: !birthdate_estimated.zero?, attributes: { home_district: home_district, home_traditional_authority: , home_village: home_village } ) raise DdeMahisError, "DdeMahis patient search failed: #{status} - #{response}" unless status == 200 response.collect do |match| doc_id = match['person']['id'] patient = patient_service.find_patients_by_identifier( doc_id, patient_identifier_type('Dde Person Document ID') ).first match['person']['patient_id'] = patient&.id match end end |
#merge_patients(primary_patients_ids, secondary_patient_ids) ⇒ Object
Trigger a merge of patients in DdeMahis
236 237 238 |
# File 'app/services/dde_service.rb', line 236 def merge_patients(primary_patients_ids, secondary_patient_ids) merging_service.merge_patients(primary_patients_ids, secondary_patient_ids) end |
#reassign_patient_npid(patient_ids) ⇒ Object
240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 |
# File 'app/services/dde_service.rb', line 240 def reassign_patient_npid(patient_ids) patient_id = patient_ids['patient_id'] doc_id = patient_ids['doc_id'] raise InvalidParameterError, 'patient_id and/or doc_id required' if patient_id.blank? && doc_id.blank? if doc_id.blank? # Only have patient id thus we have patient locally only return push_local_patient_to_dde(Patient.find(patient_ids['patient_id'])) end # NOTE: Fail patient retrieval as early as possible before making any # changes to DdeMahis (ie if patient_id does not exist) patient = patient_id.blank? ? nil : Patient.find(patient_id) # We have a doc_id thus we can re-assign npid in DdeMahis # Check if person if available in DdeMahis if not add person using doc_id response, status = dde_client.post('search_by_doc_id', doc_id: doc_id) if !response.blank? && status.to_i == 200 response, status = dde_client.post('reassign_npid', doc_id: doc_id) elsif response.blank? && status.to_i == 200 return push_local_patient_to_dde(Patient.find(patient_ids['patient_id'])) end unless status == 200 && !response.empty? # The DdeMahis's reassign_npid end point responds with a 200 - OK but returns # an empty object when patient with given doc_id is not found. raise DdeMahisError, "Failed to reassign npid: DdeMahis Response => #{status} - #{response}" end return save_remote_patient(response) unless patient merging_service.link_local_to_remote_patient(patient, response) end |
#remaining_npids ⇒ Object
59 60 61 62 63 64 |
# File 'app/services/dde_service.rb', line 59 def remaining_npids response, status = dde_client.get("/location_npid_status?location_id=#{Location.current_location.id}") raise DdeMahisError, "Failed to fetch remaining npids: #{status} - #{response}" unless status == 200 response end |
#save_remote_patient(remote_patient) ⇒ Object
Convert a DdeMahis person to an openmrs person.
NOTE: This creates a person on the database.
278 279 280 281 282 283 284 285 286 287 288 |
# File 'app/services/dde_service.rb', line 278 def save_remote_patient(remote_patient) LOGGER.debug "Converting DdeMahis person to openmrs: #{remote_patient}" params = dde_patient_to_local_person(remote_patient) Person.transaction do person = person_service.create_person(params) patient = Patient.create(patient_id: person.id) merging_service.link_local_to_remote_patient(patient, remote_patient) end end |
#test_connection ⇒ Object
35 36 37 38 39 40 41 42 43 44 45 46 |
# File 'app/services/dde_service.rb', line 35 def test_connection response = { connection_available: false, message: 'No connection to DdeMahis', status: 500 } begin result, status = dde_client response[:connection_available] = status == 200 response[:message] = result rescue StandardError => exception LOGGER.error "Failed to connect to DdeMahis: #{exception.message}" response[:message] = exception. end response end |
#update_local_patient(patient, update_npid: false) ⇒ Object
Updates local patient with demographics currently in DdeMahis.
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
# File 'app/services/dde_service.rb', line 116 def update_local_patient(patient, update_npid: false) doc_id = patient_doc_id(patient) unless doc_id Rails.logger.warn("No DdeMahis doc_id found for patient ##{patient.patient_id}") push_local_patient_to_dde(patient) return patient end dde_patient = find_remote_patients_by_doc_id(doc_id).first unless dde_patient Rails.logger.warn("Couldn't find patient ##{patient.patient_id} in DdeMahis by doc_id ##{doc_id}") push_local_patient_to_dde(patient) return patient end if update_npid merging_service.link_local_to_remote_patient(patient, dde_patient) return patient end person_service.update_person(patient.person, dde_patient_to_local_person(dde_patient)) patient end |
#update_patient(patient) ⇒ Object
Updates patient demographics in DdeMahis.
Local patient is not affected in anyway by the update
86 87 88 89 90 91 92 93 |
# File 'app/services/dde_service.rb', line 86 def update_patient(patient) dde_patient = openmrs_to_dde_patient(patient) response, status = dde_client.post('update_person', dde_patient) raise DdeMahisError, "Failed to update person in DdeMahis: #{response}" unless status == 200 patient end |
#void_patient(patient, reason) ⇒ Object
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
# File 'app/services/dde_service.rb', line 66 def void_patient(patient, reason) raise ArgumentError, "Can't request a DdeMahis void for a non-voided patient" unless patient.voided? raise ArgumentError, 'void_reason is required' if reason.blank? doc_id = PatientIdentifier.unscoped .where(identifier_type: dde_doc_id_type, patient: patient) .order(:date_voided) .last &.identifier return patient unless doc_id response, status = dde_client.delete("void_person/#{doc_id}?void_reason=#{reason}") raise DdeMahisError, "Failed to void person in DdeMahis: #{status} - #{response}" unless status == 200 patient end |