openmrs_data_sanitizer 1.0.3 → 1.0.4
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: 871a8c260924d6911e5ed550ad158e3914d10eab5a93fc473bb37d56bcbcc641
|
4
|
+
data.tar.gz: 9af6e3f50d1beec93f505cedacaf0722bc66d4dacb69dbc3c6104166a7c333c5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8117cb24ce418d40e297585b23d0d5f675af86290067a6d484dee81fe0a6a85fc3f3a62b2c383fc55983120269ea702182906368b9ddd795737861183e9253ee
|
7
|
+
data.tar.gz: 8a145dc8da6d99a3ec3ae2287a5a44927a187c580b405d109d639f0385e340e9fa605512e06ba94f6ebf48e4b07695dddbb91bd8bbca78d7ff7e13e1b64e913a
|
@@ -95,7 +95,7 @@ module OpenmrsDataSanitizer
|
|
95
95
|
drop_data_sanitizer_encounter_dates_table
|
96
96
|
create_data_sanitizer_encounter_dates_table
|
97
97
|
end
|
98
|
-
if count_table_columns('data_sanitizer_patient_outcomes') !=
|
98
|
+
if count_table_columns('data_sanitizer_patient_outcomes') != 6
|
99
99
|
drop_data_sanitizer_patient_outcomes_table
|
100
100
|
create_data_sanitizer_patient_outcomes_table
|
101
101
|
end
|
@@ -108,17 +108,22 @@ module OpenmrsDataSanitizer
|
|
108
108
|
drop_data_sanitizer_patient_reason_for_starting_table
|
109
109
|
create_data_sanitizer_patient_reason_for_starting_table
|
110
110
|
end
|
111
|
-
if count_table_columns('data_sanitizer_patient_detailed_side_effects') !=
|
111
|
+
if count_table_columns('data_sanitizer_patient_detailed_side_effects') != 24
|
112
112
|
drop_data_sanitizer_patient_detailed_side_effects_table
|
113
113
|
create_data_sanitizer_patient_detailed_side_effects_table
|
114
114
|
end
|
115
|
-
|
115
|
+
if count_table_columns('data_sanitizer_patients') != 8
|
116
|
+
drop_data_sanitizer_patients_table
|
117
|
+
create_data_sanitizer_patients_table
|
118
|
+
end
|
119
|
+
return unless count_table_columns('data_sanitizer_visits') != 37
|
116
120
|
|
117
121
|
drop_data_sanitizer_visits_table
|
118
122
|
create_data_sanitizer_visits_table
|
119
123
|
end
|
120
124
|
|
121
125
|
def process_data
|
126
|
+
insert_data_sanitizer_patients
|
122
127
|
insert_data_sanitizer_patients_height
|
123
128
|
insert_data_sanitizer_patients_weight
|
124
129
|
insert_data_sanitizer_patient_present
|
@@ -144,7 +149,7 @@ module OpenmrsDataSanitizer
|
|
144
149
|
data_sanitizer_side_effect data_sanitizer_adherence data_sanitizer_appointment
|
145
150
|
data_sanitizer_arv_medication data_sanitizer_arv_orders data_sanitizer_encounter_dates
|
146
151
|
data_sanitizer_patient_outcomes data_sanitizer_patient_who_stage data_sanitizer_patient_reason_for_starting
|
147
|
-
data_sanitizer_patient_detailed_side_effects data_sanitizer_visits ]
|
152
|
+
data_sanitizer_patient_detailed_side_effects data_sanitizer_visits data_sanitizer_patients]
|
148
153
|
table_names.each do |table_name|
|
149
154
|
ActiveRecord::Base.connection.execute("TRUNCATE TABLE #{schema}.#{table_name}")
|
150
155
|
end
|
@@ -415,6 +420,21 @@ module OpenmrsDataSanitizer
|
|
415
420
|
SQL
|
416
421
|
create_data_sanitizer_visits_index
|
417
422
|
end
|
423
|
+
|
424
|
+
def create_data_sanitizer_patients_table
|
425
|
+
ActiveRecord::Base.connection.execute <<~SQL
|
426
|
+
CREATE TABLE IF NOT EXISTS #{schema}.data_sanitizer_patients (
|
427
|
+
patient_id INT PRIMARY KEY,
|
428
|
+
given_name VARCHAR(100),
|
429
|
+
middle_name VARCHAR(100),
|
430
|
+
family_name VARCHAR(100),
|
431
|
+
gender VARCHAR(1),
|
432
|
+
birthdate DATE,
|
433
|
+
phone_number VARCHAR(100),
|
434
|
+
village_name VARCHAR(100)
|
435
|
+
);
|
436
|
+
SQL
|
437
|
+
end
|
418
438
|
# rubocop:enable Metrics/MethodLength
|
419
439
|
|
420
440
|
# ========================
|
@@ -527,6 +547,12 @@ module OpenmrsDataSanitizer
|
|
527
547
|
# DATABASE TABLE DELETE METHODS
|
528
548
|
# ========================
|
529
549
|
|
550
|
+
def drop_data_sanitizer_patients_table
|
551
|
+
ActiveRecord::Base.connection.execute <<~SQL
|
552
|
+
DROP TABLE IF EXISTS #{schema}.data_sanitizer_patients;
|
553
|
+
SQL
|
554
|
+
end
|
555
|
+
|
530
556
|
def drop_data_sanitizer_patients_height_table
|
531
557
|
ActiveRecord::Base.connection.execute <<~SQL
|
532
558
|
DROP TABLE IF EXISTS #{schema}.data_sanitizer_patients_height;
|
@@ -634,19 +660,28 @@ module OpenmrsDataSanitizer
|
|
634
660
|
# ========================
|
635
661
|
|
636
662
|
# rubocop:disable Metrics/MethodLength
|
663
|
+
def insert_data_sanitizer_patients
|
664
|
+
ActiveRecord::Base.connection.execute <<~SQL
|
665
|
+
INSERT INTO #{schema}.data_sanitizer_patients (patient_id, given_name, middle_name, family_name, gender, birthdate, phone_number, village_name)
|
666
|
+
SELECT p.person_id, n.given_name, n.middle_name, n.family_name, IF(p.gender is NULL, 'U', LEFT(p.gender,1)), p.birthdate, phone.value, village.value
|
667
|
+
FROM #{schema}.person p
|
668
|
+
INNER JOIN #{schema}.patient ON patient.patient_id = p.person_id AND p.voided = 0
|
669
|
+
LEFT JOIN #{schema}.person_name n ON n.person_id = p.person_id AND n.voided = 0
|
670
|
+
LEFT JOIN #{schema}.person_attribute phone ON phone.person_id = p.person_id AND phone.voided = 0 AND phone.person_attribute_type_id = 12
|
671
|
+
LEFT JOIN #{schema}.person_attribute village ON village.person_id = p.person_id AND village.voided = 0 AND village.person_attribute_type_id = 19
|
672
|
+
WHERE p.voided = 0
|
673
|
+
GROUP BY p.person_id;
|
674
|
+
SQL
|
675
|
+
end
|
676
|
+
|
637
677
|
def insert_data_sanitizer_patients_height
|
638
678
|
ActiveRecord::Base.connection.execute <<~SQL
|
639
679
|
INSERT INTO #{schema}.data_sanitizer_patients_height (patient_id, height, visit_date)
|
640
680
|
SELECT e.patient_id, ROUND(obs.value_numeric), DATE(obs.obs_datetime) visit_date
|
641
681
|
FROM #{schema}.encounter e
|
642
|
-
INNER JOIN #{schema}.obs ON e.
|
643
|
-
|
644
|
-
|
645
|
-
AND e.program_id = 1
|
646
|
-
AND obs.voided = 0
|
647
|
-
AND obs.concept_id = 5090 -- Height concept_id
|
648
|
-
GROUP BY obs.person_id, DATE(obs.obs_datetime)
|
649
|
-
ORDER BY obs_datetime DESC;
|
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
|
+
WHERE e.voided = 0 and e.encounter_type = 6 and e.program_id = 1
|
684
|
+
GROUP BY obs.person_id, DATE(obs.obs_datetime);
|
650
685
|
SQL
|
651
686
|
end
|
652
687
|
|
@@ -655,14 +690,11 @@ module OpenmrsDataSanitizer
|
|
655
690
|
INSERT INTO #{schema}.data_sanitizer_patients_weight (patient_id, weight, visit_date)
|
656
691
|
SELECT e.patient_id, ROUND(obs.value_numeric), DATE(obs.obs_datetime) visit_date
|
657
692
|
FROM #{schema}.encounter e
|
658
|
-
INNER JOIN #{schema}.obs ON e.
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
AND obs.concept_id = 5089
|
664
|
-
GROUP BY obs.person_id, DATE(obs.obs_datetime)
|
665
|
-
ORDER BY obs_datetime DESC;
|
693
|
+
INNER JOIN #{schema}.obs ON e.encounter_id = obs.encounter_id
|
694
|
+
AND obs.voided = 0
|
695
|
+
AND obs.concept_id = 5089
|
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);
|
666
698
|
SQL
|
667
699
|
end
|
668
700
|
|
@@ -673,14 +705,11 @@ module OpenmrsDataSanitizer
|
|
673
705
|
(CASE WHEN obs.value_coded = 1065 THEN 'YES' ELSE 'NO' END) AS patient_present,
|
674
706
|
DATE(obs.obs_datetime) visit_date
|
675
707
|
FROM #{schema}.encounter e
|
676
|
-
INNER JOIN #{schema}.obs ON e.
|
677
|
-
AND e.voided = 0
|
678
|
-
AND e.encounter_type = 51
|
679
|
-
AND e.program_id = 1
|
708
|
+
INNER JOIN #{schema}.obs ON e.encounter_id = obs.encounter_id
|
680
709
|
AND obs.voided = 0
|
681
710
|
AND obs.concept_id = 1805
|
682
|
-
|
683
|
-
|
711
|
+
WHERE e.voided = 0 and e.encounter_type = 51 and e.program_id = 1
|
712
|
+
GROUP BY obs.person_id, DATE(obs.obs_datetime);
|
684
713
|
SQL
|
685
714
|
end
|
686
715
|
|
@@ -691,16 +720,13 @@ module OpenmrsDataSanitizer
|
|
691
720
|
(CASE WHEN obs.value_coded = 1065 THEN 'YES' ELSE 'NO' END) AS guardian_present,
|
692
721
|
DATE(obs.obs_datetime) visit_date
|
693
722
|
FROM #{schema}.encounter e
|
694
|
-
INNER JOIN #{schema}.obs ON e.
|
695
|
-
|
696
|
-
|
697
|
-
AND e.program_id = 1
|
698
|
-
AND obs.voided = 0
|
699
|
-
AND obs.concept_id = 6794
|
723
|
+
INNER JOIN #{schema}.obs ON e.encounter_id = obs.encounter_id
|
724
|
+
AND obs.voided = 0
|
725
|
+
AND obs.concept_id = 6794
|
700
726
|
INNER JOIN #{schema}.person ON person.person_id = obs.person_id
|
701
|
-
|
702
|
-
|
703
|
-
|
727
|
+
AND person.gender IN('Female','F')
|
728
|
+
WHERE e.voided = 0 and e.encounter_type = 51 and e.program_id = 1
|
729
|
+
GROUP BY obs.person_id, DATE(obs.obs_datetime);
|
704
730
|
SQL
|
705
731
|
end
|
706
732
|
|
@@ -711,16 +737,13 @@ module OpenmrsDataSanitizer
|
|
711
737
|
(CASE WHEN obs.value_coded = 1065 THEN 'YES' ELSE 'NO' END) AS pregnant_status,
|
712
738
|
DATE(obs.obs_datetime) visit_date
|
713
739
|
FROM #{schema}.encounter e
|
714
|
-
INNER JOIN #{schema}.obs ON e.
|
715
|
-
|
716
|
-
|
717
|
-
AND e.encounter_type = 53
|
718
|
-
AND obs.voided = 0
|
719
|
-
AND obs.concept_id IN(6131, 1755)
|
740
|
+
INNER JOIN #{schema}.obs ON e.encounter_id = obs.encounter_id
|
741
|
+
AND obs.voided = 0
|
742
|
+
AND obs.concept_id IN(6131, 1755)
|
720
743
|
INNER JOIN #{schema}.person ON person.person_id = obs.person_id
|
721
|
-
|
722
|
-
|
723
|
-
|
744
|
+
AND person.gender IN('Female','F')
|
745
|
+
WHERE e.voided = 0 and e.encounter_type = 53 and e.program_id = 1
|
746
|
+
GROUP BY obs.person_id, DATE(obs.obs_datetime);
|
724
747
|
SQL
|
725
748
|
end
|
726
749
|
|
@@ -731,34 +754,28 @@ module OpenmrsDataSanitizer
|
|
731
754
|
(CASE WHEN obs.value_coded = 1065 THEN 'YES' ELSE 'NO' END) AS breastfeeding_status,
|
732
755
|
DATE(obs.obs_datetime) visit_date
|
733
756
|
FROM #{schema}.encounter e
|
734
|
-
INNER JOIN #{schema}.obs ON e.
|
735
|
-
|
736
|
-
|
737
|
-
|
738
|
-
|
739
|
-
AND obs.concept_id IN(834,5632, 8039,7965)
|
740
|
-
GROUP BY obs.person_id, DATE(obs.obs_datetime)
|
741
|
-
ORDER BY obs_datetime DESC;
|
757
|
+
INNER JOIN #{schema}.obs ON e.encounter_id = obs.encounter_id
|
758
|
+
AND obs.voided = 0
|
759
|
+
AND obs.concept_id IN(834,5632, 8039,7965)
|
760
|
+
WHERE e.voided = 0 and e.encounter_type = 53 and e.program_id = 1
|
761
|
+
GROUP BY obs.person_id, DATE(obs.obs_datetime);
|
742
762
|
SQL
|
743
763
|
end
|
744
764
|
|
745
765
|
def insert_data_sanitizer_side_effect
|
746
766
|
ActiveRecord::Base.connection.execute <<~SQL
|
747
767
|
INSERT INTO #{schema}.data_sanitizer_side_effect (patient_id, visit_date, concept_id, value_coded, available)
|
748
|
-
SELECT t.person_id,
|
749
|
-
DATE(t.obs_datetime) visit_date,
|
750
|
-
t2.concept_id,
|
751
|
-
t2.value_coded,
|
768
|
+
SELECT t.person_id,DATE(t.obs_datetime) visit_date,t2.concept_id,t2.value_coded,
|
752
769
|
(CASE WHEN t2.value_coded = 1065 THEN 'YES' ELSE 'NO' END) available
|
753
770
|
FROM #{schema}.obs t
|
754
771
|
INNER JOIN #{schema}.obs t2 ON t.concept_id = 7755
|
755
|
-
|
756
|
-
|
757
|
-
|
772
|
+
AND t.obs_id = t2.obs_group_id
|
773
|
+
AND t.voided = 0
|
774
|
+
AND t2.voided = 0
|
758
775
|
INNER JOIN #{schema}.encounter e ON e.encounter_id = t.encounter_id
|
759
|
-
|
760
|
-
|
761
|
-
|
776
|
+
AND e.program_id = 1
|
777
|
+
AND e.encounter_type = 53
|
778
|
+
AND e.voided = 0
|
762
779
|
GROUP BY t.person_id, DATE(t.obs_datetime), t.value_coded, t2.value_coded;
|
763
780
|
SQL
|
764
781
|
end
|
@@ -766,61 +783,46 @@ module OpenmrsDataSanitizer
|
|
766
783
|
def insert_data_sanitizer_adherence
|
767
784
|
ActiveRecord::Base.connection.execute <<~SQL
|
768
785
|
INSERT INTO #{schema}.data_sanitizer_adherence (patient_id, visit_date, adherence)
|
769
|
-
SELECT o.person_id,
|
770
|
-
DATE(o.visit_date) visit_date,
|
786
|
+
SELECT o.person_id, DATE(o.visit_date) visit_date,
|
771
787
|
ROUND(MAX(CASE WHEN (REPLACE(adherence, '%', '')) BETWEEN 95 AND 105 THEN (REPLACE(adherence, '%', '')) ELSE 0 END)) AS adherence
|
772
788
|
FROM (
|
773
789
|
SELECT obs.person_id, DATE(obs_datetime) AS visit_date, IF(value_numeric REGEXP '^[+-]?[0-9]+(\.[0-9]+)?%?$', CAST(REPLACE(value_numeric, '%', '') AS DECIMAL(10, 2)), 0) AS adherence
|
774
790
|
FROM #{schema}.obs
|
775
|
-
INNER JOIN #{schema}.encounter e ON e.
|
776
|
-
AND e.
|
791
|
+
INNER JOIN #{schema}.encounter e ON e.encounter_id = obs.encounter_id
|
792
|
+
AND e.encounter_type = 68
|
777
793
|
AND e.program_id = 1
|
778
794
|
WHERE obs.voided = 0
|
779
795
|
AND obs.concept_id = 6987 -- Drug adherence concept_id
|
780
796
|
AND (obs.value_numeric IS NOT NULL OR obs.value_text IS NOT NULL)
|
781
797
|
) AS o
|
782
798
|
GROUP BY o.person_id, o.visit_date
|
783
|
-
ORDER BY o.person_id, o.visit_date;
|
784
799
|
SQL
|
785
800
|
end
|
786
801
|
|
787
802
|
def insert_data_sanitizer_appointment
|
788
803
|
ActiveRecord::Base.connection.execute <<~SQL
|
789
804
|
INSERT INTO #{schema}.data_sanitizer_appointment (patient_id, value_datetime, visit_date)
|
790
|
-
SELECT e.patient_id,
|
791
|
-
DATE(value_datetime),
|
792
|
-
DATE(obs.obs_datetime) visit_date
|
805
|
+
SELECT e.patient_id, DATE(value_datetime),DATE(obs.obs_datetime) visit_date
|
793
806
|
FROM #{schema}.encounter e
|
794
|
-
INNER JOIN #{schema}.obs ON e.
|
795
|
-
|
796
|
-
|
797
|
-
|
798
|
-
|
799
|
-
AND obs.concept_id = 5096
|
800
|
-
GROUP BY obs.person_id, DATE(obs.obs_datetime)
|
801
|
-
ORDER BY obs_datetime DESC;
|
807
|
+
INNER JOIN #{schema}.obs ON e.encounter_id = obs.encounter_id
|
808
|
+
AND obs.voided = 0
|
809
|
+
AND obs.concept_id = 5096
|
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);
|
802
812
|
SQL
|
803
813
|
end
|
804
814
|
|
805
815
|
def insert_data_sanitizer_arv_medication
|
806
816
|
ActiveRecord::Base.connection.execute <<~SQL
|
807
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)
|
808
|
-
SELECT e.patient_id, o.order_id ,
|
809
|
-
|
810
|
-
|
811
|
-
COUNT(DISTINCT d.drug_id) AS num_unique_arvs,
|
812
|
-
GROUP_CONCAT(DISTINCT d.drug_id SEPARATOR ', ') AS unique_arvs_given,
|
813
|
-
GROUP_CONCAT(DISTINCT d.name SEPARATOR ', ') AS 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,
|
819
|
+
COUNT(DISTINCT d.drug_id) AS num_unique_arvs,GROUP_CONCAT(DISTINCT d.drug_id SEPARATOR ', ') AS unique_arvs_given,
|
820
|
+
GROUP_CONCAT(DISTINCT d.name SEPARATOR ', ') AS drug_names
|
814
821
|
FROM #{schema}.orders o
|
815
|
-
INNER JOIN #{schema}.drug_order da ON da.order_id = o.order_id
|
816
|
-
AND o.voided = 0
|
817
|
-
AND da.quantity > 0
|
822
|
+
INNER JOIN #{schema}.drug_order da ON da.order_id = o.order_id AND o.voided = 0 AND da.quantity > 0
|
818
823
|
INNER JOIN #{schema}.drug d ON d.drug_id = da.drug_inventory_id
|
819
|
-
INNER JOIN #{schema}.obs ON obs.order_id = o.order_id
|
820
|
-
AND obs.
|
821
|
-
INNER JOIN #{schema}.encounter e ON e.program_id = 1
|
822
|
-
AND e.encounter_id = obs.encounter_id
|
823
|
-
AND e.encounter_type = 54
|
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
826
|
INNER JOIN #{schema}.arv_drug ON arv_drug.drug_id = d.drug_id
|
825
827
|
GROUP BY obs.person_id, o.order_id, DATE(o.start_date);
|
826
828
|
SQL
|
@@ -829,10 +831,9 @@ module OpenmrsDataSanitizer
|
|
829
831
|
def insert_data_sanitizer_arv_orders
|
830
832
|
ActiveRecord::Base.connection.execute <<~SQL
|
831
833
|
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)
|
832
|
-
SELECT
|
833
|
-
|
834
|
-
|
835
|
-
orders.start_date, orders.auto_expire_date,SUM(o.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)
|
836
837
|
FROM #{schema}.data_sanitizer_arv_medication m
|
837
838
|
INNER JOIN #{schema}.drug_order o ON o.order_id = m.order_id
|
838
839
|
INNER JOIN #{schema}.drug d ON d.drug_id = o.drug_inventory_id
|
@@ -856,36 +857,36 @@ module OpenmrsDataSanitizer
|
|
856
857
|
INSERT INTO #{schema}.data_sanitizer_patient_outcomes(patient_id, visit_date, end_date, state, concept_id, outcome)
|
857
858
|
SELECT p.patient_id,s.start_date, s.end_date, s.state, pws.concept_id, cn.name
|
858
859
|
FROM #{schema}.patient_program p
|
859
|
-
INNER JOIN #{schema}.patient_state s ON p.patient_program_id = s.patient_program_id
|
860
|
-
AND p.program_id = 1 AND p.voided = 0 AND s.voided = 0 AND s.state IS NOT NULL
|
860
|
+
INNER JOIN #{schema}.patient_state s ON p.patient_program_id = s.patient_program_id AND p.program_id = 1 AND p.voided = 0 AND s.voided = 0 AND s.state IS NOT NULL
|
861
861
|
INNER JOIN #{schema}.program_workflow_state pws ON s.state = pws.program_workflow_state_id AND pws.retired = 0 AND pws.terminal = 1
|
862
862
|
INNER JOIN #{schema}.concept_name cn ON cn.concept_id = pws.concept_id AND cn.voided = 0 AND cn.name IS NOT NULL AND LENGTH(cn.name) > 0
|
863
863
|
GROUP BY p.patient_id, DATE(s.start_date), DATE(p.date_enrolled)
|
864
|
-
ORDER BY DATE(s.start_date) DESC, DATE(p.date_enrolled) DESC;
|
865
864
|
SQL
|
866
865
|
end
|
867
866
|
|
868
867
|
def insert_data_sanitizer_patient_who_stage
|
869
868
|
ActiveRecord::Base.connection.execute <<~SQL
|
870
869
|
INSERT INTO #{schema}.data_sanitizer_patient_who_stage(patient_id, visit_date, who_stage)
|
871
|
-
SELECT e.patient_id, DATE(t1.obs_datetime) visit_date, cn.name
|
872
|
-
|
873
|
-
|
874
|
-
|
875
|
-
|
876
|
-
|
870
|
+
SELECT e.patient_id, DATE(t1.obs_datetime) visit_date, cn.name
|
871
|
+
FROM #{schema}.encounter e
|
872
|
+
INNER JOIN #{schema}.obs t1 ON t1.encounter_id = e.encounter_id
|
873
|
+
AND t1.voided = 0 AND t1.concept_id = 7562
|
874
|
+
INNER JOIN #{schema}.concept_name cn ON cn.concept_id = t1.value_coded AND cn.voided = 0 AND LENGTH(cn.name) > 0
|
875
|
+
WHERE e.voided = 0 and e.encounter_type = 52 and e.program_id = 1
|
876
|
+
GROUP BY e.patient_id
|
877
877
|
SQL
|
878
878
|
end
|
879
879
|
|
880
880
|
def insert_data_sanitizer_patient_reason_for_starting
|
881
881
|
ActiveRecord::Base.connection.execute <<~SQL
|
882
882
|
INSERT INTO #{schema}.data_sanitizer_patient_reason_for_starting(patient_id, visit_date, reason_for_starting_art)
|
883
|
-
SELECT e.patient_id, DATE(t1.obs_datetime) visit_date, cn.name
|
884
|
-
|
885
|
-
|
886
|
-
|
887
|
-
|
888
|
-
|
883
|
+
SELECT e.patient_id, DATE(t1.obs_datetime) visit_date, cn.name
|
884
|
+
FROM #{schema}.encounter e
|
885
|
+
INNER JOIN #{schema}.obs t1 ON t1.encounter_id = e.encounter_id
|
886
|
+
AND t1.voided = 0 AND t1.concept_id = 7563
|
887
|
+
INNER JOIN #{schema}.concept_name cn ON cn.concept_id = t1.value_coded AND cn.voided = 0 AND LENGTH(cn.name) > 0
|
888
|
+
WHERE e.voided = 0 and e.encounter_type = 52 and e.program_id = 1
|
889
|
+
GROUP BY e.patient_id
|
889
890
|
SQL
|
890
891
|
end
|
891
892
|
|
@@ -13,17 +13,11 @@ module OpenmrsDataSanitizer
|
|
13
13
|
# rubocop:disable Metrics/ClassLength
|
14
14
|
# AWS DataSanitizer
|
15
15
|
class DataSanitizer
|
16
|
-
attr_accessor :
|
17
|
-
:concept_names, :faker_names, :sites, :patients_json,
|
18
|
-
:fhir_medication_dispense
|
16
|
+
attr_accessor :regimen_combinations, :concept_names, :faker_names, :sites
|
19
17
|
|
20
18
|
def initialize(sites: [])
|
21
|
-
@fhir_encounters = Concurrent::Array.new
|
22
|
-
@fhir_observations = Concurrent::Array.new
|
23
|
-
@fhir_medication_dispense = Concurrent::Array.new
|
24
19
|
@concept_names = Concurrent::Hash.new
|
25
20
|
@faker_names = Concurrent::Hash.new
|
26
|
-
@patients_json = Concurrent::Array.new
|
27
21
|
@regimen_combinations = {}
|
28
22
|
@sites = sites
|
29
23
|
load_regimen_combinations
|
@@ -63,13 +57,29 @@ module OpenmrsDataSanitizer
|
|
63
57
|
end
|
64
58
|
next unless loc
|
65
59
|
|
66
|
-
|
60
|
+
thread_variables # Set thread variables before processing
|
61
|
+
process_location(loc) # Process location
|
62
|
+
write_data_to_files # Write data to files
|
63
|
+
clear_thread_variables # Clear thread variables after processing
|
67
64
|
end
|
68
65
|
end
|
69
66
|
end
|
70
67
|
|
71
68
|
threads.each(&:join)
|
72
|
-
|
69
|
+
end
|
70
|
+
|
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
|
73
83
|
end
|
74
84
|
|
75
85
|
def process_location(loc)
|
@@ -92,19 +102,18 @@ module OpenmrsDataSanitizer
|
|
92
102
|
|
93
103
|
def process_patients(schema, site_name)
|
94
104
|
patients = fetch_patients(schema:)
|
95
|
-
patients_ids = patients.map { |patient| patient['person_id'].to_i }
|
96
105
|
patients.map { |patient| build_patient_json(patient, site_name) }
|
97
106
|
|
98
|
-
visits = fetch_visits(
|
107
|
+
visits = fetch_visits(schema:)
|
99
108
|
process_visits(visits:)
|
100
109
|
process_medication(schema:)
|
101
110
|
end
|
102
111
|
|
103
112
|
def write_data_to_files
|
104
|
-
write_to_file(patients_json.to_json, 'patients')
|
105
|
-
write_to_file(fhir_encounters.to_json, 'visits')
|
106
|
-
write_to_file(fhir_observations.to_json, 'observations')
|
107
|
-
write_to_file(fhir_medication_dispense.to_json, 'medications')
|
113
|
+
write_to_file(Thread.current[:patients_json].to_json, 'patients')
|
114
|
+
write_to_file(Thread.current[:fhir_encounters].to_json, 'visits')
|
115
|
+
write_to_file(Thread.current[:fhir_observations].to_json, 'observations')
|
116
|
+
write_to_file(Thread.current[:fhir_medication_dispense].to_json, 'medications')
|
108
117
|
end
|
109
118
|
|
110
119
|
# ===================================
|
@@ -141,15 +150,7 @@ module OpenmrsDataSanitizer
|
|
141
150
|
|
142
151
|
def fetch_patients(schema:)
|
143
152
|
ActiveRecord::Base.connection.select_all <<~SQL
|
144
|
-
SELECT
|
145
|
-
p.person_id, given_name, middle_name, family_name, gender, birthdate,
|
146
|
-
phone.value phone_number, village.value village_name
|
147
|
-
FROM #{schema}.person p
|
148
|
-
INNER JOIN #{schema}.patient ON patient.patient_id = p.person_id AND p.voided = 0
|
149
|
-
INNER JOIN #{schema}.patient_program pp ON pp.patient_id = p.person_id AND pp.voided = 0 AND pp.program_id = 1
|
150
|
-
LEFT JOIN #{schema}.person_name n ON n.person_id = p.person_id AND n.voided = 0
|
151
|
-
LEFT JOIN #{schema}.person_attribute phone ON phone.person_id = p.person_id AND phone.voided = 0 AND phone.person_attribute_type_id = 12
|
152
|
-
LEFT JOIN #{schema}.person_attribute village ON village.person_id = p.person_id AND village.voided = 0 AND village.person_attribute_type_id = 19;
|
153
|
+
SELECT * FROM #{schema}.data_sanitizer_patients;
|
153
154
|
SQL
|
154
155
|
end
|
155
156
|
|
@@ -162,7 +163,7 @@ module OpenmrsDataSanitizer
|
|
162
163
|
given_name = get_or_generate_faker_value(patient['given_name'], Faker::Name, :first_name)
|
163
164
|
middle_name = get_or_generate_faker_value(patient['middle_name'], Faker::Name, :middle_name)
|
164
165
|
|
165
|
-
patients_json << FHIR::Patient.new(
|
166
|
+
Thread.current[:patients_json] << FHIR::Patient.new(
|
166
167
|
id: patient_id,
|
167
168
|
identifier: [{ system: "#{site_name}_#{patient_id}", value: patient_id }],
|
168
169
|
name: [{ use: 'official', family: family_name, given: [given_name, middle_name] }],
|
@@ -172,19 +173,29 @@ module OpenmrsDataSanitizer
|
|
172
173
|
telecom: [{ system: 'phone', value: cell_number, use: 'mobile' }]
|
173
174
|
)
|
174
175
|
end
|
175
|
-
# rubocop:enable Metrics/MethodLength, Metrics/AbcSize
|
176
176
|
|
177
177
|
def fetch_gender(gender:)
|
178
|
-
gender.
|
178
|
+
case gender.strip.downcase
|
179
|
+
when 'f'
|
180
|
+
'female'
|
181
|
+
when 'm'
|
182
|
+
'male'
|
183
|
+
when 'u'
|
184
|
+
'unknown'
|
185
|
+
else
|
186
|
+
'unknown'
|
187
|
+
end
|
179
188
|
rescue StandardError => e
|
180
189
|
Rails.logger.info("Error fetching gender for patient: #{e.message}")
|
181
190
|
'unknown'
|
182
191
|
end
|
192
|
+
# rubocop:enable Metrics/MethodLength, Metrics/AbcSize
|
183
193
|
|
184
|
-
def fetch_visits(
|
194
|
+
def fetch_visits(schema:)
|
185
195
|
ActiveRecord::Base.connection.select_all <<~SQL
|
186
|
-
SELECT
|
187
|
-
|
196
|
+
SELECT dsv.*
|
197
|
+
FROM #{schema}.data_sanitizer_visits dsv
|
198
|
+
INNER JOIN #{schema}.data_sanitizer_patients dsp ON dsp.patient_id = dsv.patient_id
|
188
199
|
SQL
|
189
200
|
end
|
190
201
|
|
@@ -202,7 +213,7 @@ module OpenmrsDataSanitizer
|
|
202
213
|
|
203
214
|
def aws_fhir_encounter(visit:, regimen:)
|
204
215
|
patient_id = visit['patient_id'].to_i
|
205
|
-
fhir_encounters << create_fhir_encounter(patient_id, visit['visit_date'])
|
216
|
+
Thread.current[:fhir_encounters] << create_fhir_encounter(patient_id, visit['visit_date'])
|
206
217
|
|
207
218
|
observations = process_indicators(visit, regimen)
|
208
219
|
create_fhir_observations(observations, patient_id, visit['visit_date'])
|
@@ -269,7 +280,7 @@ module OpenmrsDataSanitizer
|
|
269
280
|
observations.each do |obs|
|
270
281
|
next if obs.blank? || obs[:code].blank? || obs[:value].blank?
|
271
282
|
|
272
|
-
fhir_observations << FHIR::Observation.new(
|
283
|
+
Thread.current[:fhir_observations] << FHIR::Observation.new(
|
273
284
|
status: 'final',
|
274
285
|
code: {
|
275
286
|
coding: [
|
@@ -284,20 +295,20 @@ module OpenmrsDataSanitizer
|
|
284
295
|
reference: "Patient/#{patient_id}"
|
285
296
|
},
|
286
297
|
encounter: {
|
287
|
-
reference: "Encounter/#{fhir_encounters.last.id}"
|
298
|
+
reference: "Encounter/#{Thread.current[:fhir_encounters].last.id}"
|
288
299
|
},
|
289
300
|
effectiveDateTime: visit_date
|
290
301
|
)
|
291
302
|
|
292
303
|
if obs[:unit]
|
293
|
-
fhir_observations.last.valueQuantity = {
|
304
|
+
Thread.current[:fhir_observations].last.valueQuantity = {
|
294
305
|
value: obs[:value],
|
295
306
|
unit: obs[:unit],
|
296
307
|
system: 'EGPAF Malawi EMR',
|
297
308
|
code: obs[:code]
|
298
309
|
}
|
299
310
|
else
|
300
|
-
fhir_observations.last.valueCodeableConcept = {
|
311
|
+
Thread.current[:fhir_observations].last.valueCodeableConcept = {
|
301
312
|
coding: [
|
302
313
|
{
|
303
314
|
system: 'EGPAF Malawi EMR',
|
@@ -332,16 +343,14 @@ module OpenmrsDataSanitizer
|
|
332
343
|
|
333
344
|
# rubocop:disable Metrics/MethodLength, Metrics/AbcSize, Metrics/BlockLength
|
334
345
|
def create_fhir_medications(orders:)
|
335
|
-
fhir_medication_dispense << (orders || []).map do |order|
|
336
|
-
order_id = order['order_id'].to_i
|
337
|
-
encounter_id = order['encounter_id'].to_i
|
346
|
+
Thread.current[:fhir_medication_dispense] << (orders || []).map do |order|
|
338
347
|
FHIR::MedicationDispense.new(
|
339
348
|
identifier: {
|
340
|
-
value: order_id
|
349
|
+
value: order['order_id'].to_i
|
341
350
|
},
|
342
351
|
status: 'completed',
|
343
352
|
patient: {
|
344
|
-
reference: encounter_id
|
353
|
+
reference: order['encounter_id'].to_i
|
345
354
|
},
|
346
355
|
medication: {
|
347
356
|
code: {
|
@@ -388,7 +397,7 @@ module OpenmrsDataSanitizer
|
|
388
397
|
def get_or_generate_faker_value(attribute, faker_module, faker_method)
|
389
398
|
return '' if attribute.blank?
|
390
399
|
|
391
|
-
|
400
|
+
faker_names[attribute] ||= faker_module.send(faker_method)
|
392
401
|
end
|
393
402
|
|
394
403
|
def get_concept_name(name)
|
@@ -411,9 +420,14 @@ module OpenmrsDataSanitizer
|
|
411
420
|
|
412
421
|
# Use the mutex to handle concurrent writes
|
413
422
|
FILE_MUTEX.synchronize do
|
423
|
+
if File.exist?(file_path)
|
424
|
+
system("sed -i '$s/\([][^{},]\)$/,/g' #{file_path}")
|
425
|
+
json_file.sub!('[', '')
|
426
|
+
end
|
427
|
+
|
414
428
|
File.open(file_path, 'a') do |out_file|
|
415
429
|
out_file.puts(json_file)
|
416
|
-
|
430
|
+
Rails.logger.info "Appended to file: #{file_path}"
|
417
431
|
end
|
418
432
|
end
|
419
433
|
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.4
|
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-09-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: concurrent-ruby
|