openmrs_data_sanitizer 1.0.6 → 1.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ea1ff9af55bd7fa8cc3659a91ffd9995cb6f91b7b5c1297b31c99fbb7c264f5d
|
4
|
+
data.tar.gz: 5fe2a537ea70364ab0d3dd5da607f12627799154d46f14581527f6a38ac39eea
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d20b6330c65ec39e01f0602dd540c9c8f77df1670a28efc581bf08918957c6620a83eaf2944065757d6714ae0507d63669adb7f40b2e2746d4f6e9444e43c094
|
7
|
+
data.tar.gz: 1382c14116c18556c52c47da591095250dbf44fff7ace6dfbf37f3bad4ad8310bd75dedff4e1c5ab0b578ac69e06913c90751be73944f538317ce5fb09e0a0e9
|
@@ -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
|
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
|
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
|
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
|
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}.
|
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
|
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
|
835
|
-
|
836
|
-
|
837
|
-
|
838
|
-
INNER JOIN #{schema}.
|
839
|
-
INNER JOIN #{schema}.
|
840
|
-
|
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.encounter_type = 54
|
836
|
+
INNER JOIN #{schema}.drug_order da ON da.order_id = o.order_id AND o.voided = 0 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(
|
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
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
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['
|
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
|
-
|
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
|
-
|
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
|
-
|
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/#{
|
289
|
+
reference: "Encounter/#{encounter_id}"
|
299
290
|
},
|
300
291
|
effectiveDateTime: visit_date
|
301
292
|
)
|
302
|
-
|
303
293
|
if obs[:unit]
|
304
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
425
|
-
|
426
|
-
|
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
|
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.
|
4
|
+
version: 1.0.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mwatha
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-10-10 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.
|
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
|