openmrs_data_sanitizer 1.0.6 → 1.0.8

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 45352f6a9ff782926a46e2e93973f3a7873b8316bf482481d09c1543de7b958c
4
- data.tar.gz: ef10ff0800b3895cd22de64c0171255d3870888b15fb302d41f4c0fff5acc89d
3
+ metadata.gz: 40a55f5fb47f9307da0c2e0a5905f5554dee6688c1f4abf09889c4a7852fca95
4
+ data.tar.gz: 18ebfa45e8aefdd2fd3bf0cab02d0187ba9d3ac16e4f37e50a9de982cacd4e6d
5
5
  SHA512:
6
- metadata.gz: a931566411fae2f5cf78b5e59757a9ae7c2610c6916d67610623a8906cd1865c94b3c2bca2adda5ca9737e601a4d983e1a36349ad305ce7beb4a186905d22e33
7
- data.tar.gz: 9748ee31837097d5f9d4c1210f79b569f678dc78feb7a841c7cac65b5a9332e03cb12f2805727d9b89c7c273f2f38d464253edc9e6fd3785029f1cc433d41fa4
6
+ metadata.gz: 6db161bf332f91467f74e8f489cc536d06aac21689dc8114e296d70fbb1851d25a58face6b05141634d74806bbd9ea03a17d509ba87e8605e22a94795c8902fd
7
+ data.tar.gz: 9b0dfacd32c8bbbf5d9154bcf1402878e279bbf756ee37300d179e8d456d43b589ba857af87156619372679c798c713eae2505b42d671ed185db8c9b4884a1f1
@@ -681,7 +681,7 @@ module OpenmrsDataSanitizer
681
681
  FROM #{schema}.encounter e
682
682
  INNER JOIN #{schema}.obs ON e.encounter_id = obs.encounter_id AND obs.voided = 0 AND obs.concept_id = 5090 -- Height concept_id
683
683
  WHERE e.voided = 0 and e.encounter_type = 6 and e.program_id = 1
684
- GROUP BY obs.person_id, DATE(obs.obs_datetime);
684
+ GROUP BY e.patient_id, DATE(obs.obs_datetime);
685
685
  SQL
686
686
  end
687
687
 
@@ -694,7 +694,7 @@ module OpenmrsDataSanitizer
694
694
  AND obs.voided = 0
695
695
  AND obs.concept_id = 5089
696
696
  WHERE e.voided = 0 and e.encounter_type = 6 and e.program_id = 1
697
- GROUP BY obs.person_id, DATE(obs.obs_datetime);
697
+ GROUP BY e.patient_id, DATE(obs.obs_datetime);
698
698
  SQL
699
699
  end
700
700
 
@@ -808,37 +808,35 @@ module OpenmrsDataSanitizer
808
808
  AND obs.voided = 0
809
809
  AND obs.concept_id = 5096
810
810
  WHERE e.voided = 0 and e.encounter_type = 7 and e.program_id = 1
811
- GROUP BY obs.person_id, DATE(obs.obs_datetime);
811
+ GROUP BY e.patient_id, DATE(obs.obs_datetime);
812
812
  SQL
813
813
  end
814
814
 
815
815
  def insert_data_sanitizer_arv_medication
816
816
  ActiveRecord::Base.connection.execute <<~SQL
817
817
  INSERT INTO #{schema}.data_sanitizer_arv_medication (patient_id, order_id, visit_date, drug_runout_date, num_unique_arvs, unique_arvs_given, drug_names)
818
- SELECT e.patient_id, o.order_id, DATE(o.start_date) AS visit_date, DATE(MIN(o.auto_expire_date)) AS drug_runout_date,
818
+ SELECT o.patient_id, o.order_id, DATE(o.start_date) AS visit_date, DATE(MIN(o.auto_expire_date)) AS drug_runout_date,
819
819
  COUNT(DISTINCT d.drug_id) AS num_unique_arvs,GROUP_CONCAT(DISTINCT d.drug_id SEPARATOR ', ') AS unique_arvs_given,
820
820
  GROUP_CONCAT(DISTINCT d.name SEPARATOR ', ') AS drug_names
821
821
  FROM #{schema}.orders o
822
822
  INNER JOIN #{schema}.drug_order da ON da.order_id = o.order_id AND o.voided = 0 AND da.quantity > 0
823
823
  INNER JOIN #{schema}.drug d ON d.drug_id = da.drug_inventory_id
824
- INNER JOIN #{schema}.obs ON obs.order_id = o.order_id AND obs.voided = 0
825
- INNER JOIN #{schema}.encounter e ON e.program_id = 1 AND e.encounter_id = obs.encounter_id AND e.encounter_type = 54
824
+ INNER JOIN #{schema}.encounter e ON e.program_id = 1 AND e.encounter_id = o.encounter_id AND e.encounter_type = 54
826
825
  INNER JOIN #{schema}.arv_drug ON arv_drug.drug_id = d.drug_id
827
- GROUP BY obs.person_id, o.order_id, DATE(o.start_date);
826
+ GROUP BY o.patient_id, DATE(o.start_date);
828
827
  SQL
829
828
  end
830
829
 
831
830
  def insert_data_sanitizer_arv_orders
832
831
  ActiveRecord::Base.connection.execute <<~SQL
833
832
  INSERT INTO #{schema}.data_sanitizer_arv_orders(patient_id, order_id, encounter_id, visit_date, drug_id, drug_name, units, equivalent_daily_dose, instructions, start_date, runout_date, quantity)
834
- SELECT m.patient_id, o.order_id, orders.encounter_id , m.visit_date,
835
- d.drug_id, d.name, d.units, o.equivalent_daily_dose, orders.instructions,
836
- orders.start_date, orders.auto_expire_date,SUM(o.quantity)
837
- FROM #{schema}.data_sanitizer_arv_medication m
838
- INNER JOIN #{schema}.drug_order o ON o.order_id = m.order_id
839
- INNER JOIN #{schema}.drug d ON d.drug_id = o.drug_inventory_id
840
- INNER JOIN #{schema}.orders ON orders.order_id = o.order_id
841
- GROUP BY d.drug_id, o.order_id, m.visit_date;
833
+ SELECT e.patient_id, o.order_id, o.encounter_id, DATE(o.start_date) AS visit_date, da.drug_inventory_id AS drug_id, d.name AS drug_name, d.units, da.equivalent_daily_dose, o.instructions, DATE(o.start_date), DATE(o.auto_expire_date), da.quantity
834
+ FROM #{schema}.orders o
835
+ INNER JOIN #{schema}.encounter e ON e.encounter_id = o.encounter_id AND e.program_id = 1 AND e.voided = 0
836
+ INNER JOIN #{schema}.drug_order da ON da.order_id = o.order_id AND da.quantity > 0
837
+ INNER JOIN #{schema}.drug d ON d.drug_id = da.drug_inventory_id
838
+ INNER JOIN #{schema}.arv_drug ad ON ad.drug_id = d.drug_id
839
+ WHERE o.voided = 0
842
840
  SQL
843
841
  end
844
842
 
@@ -13,13 +13,14 @@ module OpenmrsDataSanitizer
13
13
  # rubocop:disable Metrics/ClassLength
14
14
  # AWS DataSanitizer
15
15
  class DataSanitizer
16
- attr_accessor :regimen_combinations, :concept_names, :faker_names, :sites
16
+ attr_accessor :regimen_combinations, :concept_names, :faker_names, :sites, :skip
17
17
 
18
- def initialize(sites: [])
18
+ def initialize(sites: [], skip: true)
19
19
  @concept_names = Concurrent::Hash.new
20
20
  @faker_names = Concurrent::Hash.new
21
21
  @regimen_combinations = {}
22
22
  @sites = sites
23
+ @skip = skip
23
24
  load_regimen_combinations
24
25
  end
25
26
 
@@ -47,7 +48,7 @@ module OpenmrsDataSanitizer
47
48
  queue = Queue.new
48
49
  sites.each { |loc| queue << loc }
49
50
 
50
- threads = Array.new(10) do
51
+ threads = Array.new(60) do
51
52
  Thread.new do
52
53
  until queue.empty?
53
54
  loc = begin
@@ -57,29 +58,24 @@ module OpenmrsDataSanitizer
57
58
  end
58
59
  next unless loc
59
60
 
60
- thread_variables # Set thread variables before processing
61
61
  process_location(loc) # Process location
62
- write_data_to_files # Write data to files
63
- clear_thread_variables # Clear thread variables after processing
64
62
  end
65
63
  end
66
64
  end
67
65
 
68
66
  threads.each(&:join)
67
+ close_files
69
68
  end
70
69
 
71
- def thread_variables
72
- Thread.current[:fhir_encounters] = Concurrent::Array.new
73
- Thread.current[:fhir_observations] = Concurrent::Array.new
74
- Thread.current[:fhir_medication_dispense] = Concurrent::Array.new
75
- Thread.current[:patients_json] = Concurrent::Array.new
76
- end
77
-
78
- def clear_thread_variables
79
- Thread.current[:fhir_encounters] = nil
80
- Thread.current[:fhir_observations] = nil
81
- Thread.current[:fhir_medication_dispense] = nil
82
- Thread.current[:patients_json] = nil
70
+ def close_files
71
+ dir_path = Rails.root.join('log/openmrs_data_sanitizer')
72
+ file_path = dir_path.join('*.json')
73
+ Dir[file_path].each do |file|
74
+ # Remove trailing comma and append closing bracket
75
+ system("sed -i '$s/,$/]/' #{file}")
76
+ # Log the file closure
77
+ Rails.logger.info "Closed file: #{file}"
78
+ end
83
79
  end
84
80
 
85
81
  def process_location(loc)
@@ -90,7 +86,7 @@ module OpenmrsDataSanitizer
90
86
  site_name = site['facility']
91
87
  schema = site['schema']
92
88
 
93
- OpenmrsDataSanitizer::DataAggregator.new(schema:).aggregate
89
+ OpenmrsDataSanitizer::DataAggregator.new(schema:).aggregate unless skip
94
90
 
95
91
  process_patients(schema, site_name)
96
92
  rescue StandardError => e
@@ -109,13 +105,6 @@ module OpenmrsDataSanitizer
109
105
  process_medication(schema:)
110
106
  end
111
107
 
112
- def write_data_to_files
113
- write_to_file(Thread.current[:patients_json].to_json, 'patients') unless Thread.current[:patients_json].blank?
114
- write_to_file(Thread.current[:fhir_encounters].to_json, 'visits') unless Thread.current[:fhir_encounters].blank?
115
- write_to_file(Thread.current[:fhir_observations].to_json, 'observations') unless Thread.current[:fhir_observations].blank?
116
- write_to_file(Thread.current[:fhir_medication_dispense].to_json, 'medications') unless Thread.current[:fhir_medication_dispense].blank?
117
- end
118
-
119
108
  # ===================================
120
109
  # REGION: REGIMEN COMBINATIONS
121
110
  # ===================================
@@ -156,14 +145,14 @@ module OpenmrsDataSanitizer
156
145
 
157
146
  # rubocop:disable Metrics/AbcSize
158
147
  def build_patient_json(patient, site_name)
159
- patient_id = patient['person_id'].to_i
160
- village_name = get_or_generate_faker_value(patient['village_name'], Faker::Address, :community)
161
- cell_number = get_or_generate_faker_value(patient['phone_number'], Faker::PhoneNumber, :phone_number)
162
- family_name = get_or_generate_faker_value(patient['family_name'], Faker::Name, :last_name)
163
- given_name = get_or_generate_faker_value(patient['given_name'], Faker::Name, :first_name)
164
- middle_name = get_or_generate_faker_value(patient['middle_name'], Faker::Name, :middle_name)
165
-
166
- Thread.current[:patients_json] << FHIR::Patient.new(
148
+ patient_id = patient['patient_id'].to_i
149
+ village_name = get_or_generate_faker_value(patient['village_name']&.titlecase, Faker::Address, :community)
150
+ cell_number = get_or_generate_faker_value(patient['phone_number']&.titlecase, Faker::PhoneNumber, :phone_number)
151
+ family_name = get_or_generate_faker_value(patient['family_name']&.titlecase, Faker::Name, :last_name)
152
+ given_name = get_or_generate_faker_value(patient['given_name']&.titlecase, Faker::Name, :first_name)
153
+ middle_name = get_or_generate_faker_value(patient['middle_name']&.titlecase, Faker::Name, :middle_name)
154
+
155
+ fhir_patient = FHIR::Patient.new(
167
156
  id: patient_id,
168
157
  identifier: [{ system: "#{site_name}_#{patient_id}", value: patient_id }],
169
158
  name: [{ use: 'official', family: family_name, given: [given_name, middle_name] }],
@@ -172,6 +161,7 @@ module OpenmrsDataSanitizer
172
161
  address: [{ use: 'home', village: village_name }],
173
162
  telecom: [{ system: 'phone', value: cell_number, use: 'mobile' }]
174
163
  )
164
+ write_to_file(fhir_patient.to_json, 'patients') unless fhir_patient.blank?
175
165
  end
176
166
 
177
167
  def fetch_gender(gender:)
@@ -213,10 +203,11 @@ module OpenmrsDataSanitizer
213
203
 
214
204
  def aws_fhir_encounter(visit:, regimen:)
215
205
  patient_id = visit['patient_id'].to_i
216
- Thread.current[:fhir_encounters] << create_fhir_encounter(patient_id, visit['visit_date'])
206
+ fhir_encounter = create_fhir_encounter(patient_id, visit['visit_date'])
207
+ write_to_file(fhir_encounter.to_json, 'visits') unless fhir_encounter.blank?
217
208
 
218
209
  observations = process_indicators(visit, regimen)
219
- create_fhir_observations(observations, patient_id, visit['visit_date'])
210
+ create_fhir_observations(observations, patient_id, visit['visit_date'], fhir_encounter.id)
220
211
  end
221
212
 
222
213
  # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
@@ -276,11 +267,11 @@ module OpenmrsDataSanitizer
276
267
  end
277
268
 
278
269
  # rubocop:disable Metrics/PerceivedComplexity
279
- def create_fhir_observations(observations, patient_id, visit_date)
270
+ def create_fhir_observations(observations, patient_id, visit_date, encounter_id)
280
271
  observations.each do |obs|
281
272
  next if obs.blank? || obs[:code].blank? || obs[:value].blank?
282
273
 
283
- Thread.current[:fhir_observations] << FHIR::Observation.new(
274
+ fhir_obs = FHIR::Observation.new(
284
275
  status: 'final',
285
276
  code: {
286
277
  coding: [
@@ -295,20 +286,19 @@ module OpenmrsDataSanitizer
295
286
  reference: "Patient/#{patient_id}"
296
287
  },
297
288
  encounter: {
298
- reference: "Encounter/#{Thread.current[:fhir_encounters].last.id}"
289
+ reference: "Encounter/#{encounter_id}"
299
290
  },
300
291
  effectiveDateTime: visit_date
301
292
  )
302
-
303
293
  if obs[:unit]
304
- Thread.current[:fhir_observations].last.valueQuantity = {
294
+ fhir_obs.valueQuantity = {
305
295
  value: obs[:value],
306
296
  unit: obs[:unit],
307
297
  system: 'EGPAF Malawi EMR',
308
298
  code: obs[:code]
309
299
  }
310
300
  else
311
- Thread.current[:fhir_observations].last.valueCodeableConcept = {
301
+ fhir_obs.valueCodeableConcept = {
312
302
  coding: [
313
303
  {
314
304
  system: 'EGPAF Malawi EMR',
@@ -322,6 +312,7 @@ module OpenmrsDataSanitizer
322
312
  ]
323
313
  }
324
314
  end
315
+ write_to_file(fhir_obs.to_json, 'observations') unless fhir_obs.blank?
325
316
  end
326
317
  end
327
318
  # rubocop:enable Metrics/CyclomaticComplexity, Metrics/AbcSize, Metrics/MethodLength, Metrics/BlockLength, Metrics/PerceivedComplexity
@@ -343,8 +334,8 @@ module OpenmrsDataSanitizer
343
334
 
344
335
  # rubocop:disable Metrics/MethodLength, Metrics/AbcSize, Metrics/BlockLength
345
336
  def create_fhir_medications(orders:)
346
- Thread.current[:fhir_medication_dispense] << (orders || []).map do |order|
347
- FHIR::MedicationDispense.new(
337
+ (orders || []).each do |order|
338
+ fhir_med = FHIR::MedicationDispense.new(
348
339
  identifier: {
349
340
  value: order['order_id'].to_i
350
341
  },
@@ -386,6 +377,7 @@ module OpenmrsDataSanitizer
386
377
  }
387
378
  }
388
379
  )
380
+ write_to_file(fhir_med.to_json, 'medications') unless fhir_med.blank?
389
381
  end
390
382
  end
391
383
  # rubocop:enable Metrics/MethodLength, Metrics/AbcSize, Metrics/BlockLength
@@ -420,14 +412,15 @@ module OpenmrsDataSanitizer
420
412
 
421
413
  # Use the mutex to handle concurrent writes
422
414
  FILE_MUTEX.synchronize do
423
- if File.exist?(file_path)
424
- system("sed -i '$s/\([][^{},]\)$/,/g' #{file_path}")
425
- json_file.sub!('[', '')
426
- Rails.logger.info "Removed last bracket from file: #{file_path}"
415
+ if !File.exist?(file_path)
416
+ File.open(file_path, 'w') do |out_file|
417
+ out_file.puts('[')
418
+ Rails.logger.info "Created file: #{file_path}"
419
+ end
427
420
  end
428
421
 
429
422
  File.open(file_path, 'a') do |out_file|
430
- out_file.puts(json_file)
423
+ out_file.puts("#{json_file},")
431
424
  Rails.logger.info "Appended to file: #{file_path}"
432
425
  end
433
426
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module OpenmrsDataSanitizer
4
- VERSION = '1.0.6'
4
+ VERSION = '1.0.8'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: openmrs_data_sanitizer
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.6
4
+ version: 1.0.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mwatha
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-09-03 00:00:00.000000000 Z
11
+ date: 2024-10-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -142,7 +142,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
142
142
  - !ruby/object:Gem::Version
143
143
  version: '0'
144
144
  requirements: []
145
- rubygems_version: 3.5.17
145
+ rubygems_version: 3.4.1
146
146
  signing_key:
147
147
  specification_version: 4
148
148
  summary: This gem will mask all patient identifyable data before exporting to AWS