openmrs_data_sanitizer 1.0.3 → 1.0.4

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: fa93214174e11f30a2ac4a89f33babc9fea061e7fed3765f2679241ec28b8955
4
- data.tar.gz: d70e7d5a57cdac1fe270a32e9bf37a5b523d7b1b9ca9524d6ce65d4e8a0ee820
3
+ metadata.gz: 871a8c260924d6911e5ed550ad158e3914d10eab5a93fc473bb37d56bcbcc641
4
+ data.tar.gz: 9af6e3f50d1beec93f505cedacaf0722bc66d4dacb69dbc3c6104166a7c333c5
5
5
  SHA512:
6
- metadata.gz: d2fe7b43e4e5909e814ee99066e7c256be2f87a7cf42bdd6d8be90ebee1b81bbdfeea6c845b5a59dda2d3dbceebcf1edc6c9e61ec11c12d8b07d4ff447d73d3c
7
- data.tar.gz: aad5a77b0677e7d7043ae61bff9609dfdc323768abefbf9a6a5d53e7a37b60be00e791896fb343a255a5cc03cee90fc94922bde427d2743ac6a297f1e333e2a5
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') != 5
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') != 21
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
- return unless count_table_columns('data_sanitizer_visits') != 35
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.patient_id = obs.person_id
643
- AND e.voided = 0
644
- AND e.encounter_type = 6
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.patient_id = obs.person_id
659
- AND e.voided = 0
660
- AND e.program_id = 1
661
- AND e.encounter_type = 6
662
- AND obs.voided = 0
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.patient_id = obs.person_id
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
- GROUP BY obs.person_id, DATE(obs.obs_datetime)
683
- ORDER BY obs_datetime DESC;
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.patient_id = obs.person_id
695
- AND e.voided = 0
696
- AND e.encounter_type = 51
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
- AND person.gender IN('Female','F')
702
- GROUP BY obs.person_id, DATE(obs.obs_datetime)
703
- ORDER BY obs_datetime DESC;
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.patient_id = obs.person_id
715
- AND e.voided = 0
716
- AND e.program_id = 1
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
- AND person.gender IN('Female','F')
722
- GROUP BY obs.person_id, DATE(obs.obs_datetime)
723
- ORDER BY obs_datetime DESC;
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.patient_id = obs.person_id
735
- AND e.voided = 0
736
- AND e.program_id = 1
737
- AND e.encounter_type = 53
738
- AND obs.voided = 0
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
- AND t.obs_id = t2.obs_group_id
756
- AND t.voided = 0
757
- AND t2.voided = 0
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
- AND e.program_id = 1
760
- AND e.encounter_type = 53
761
- AND e.voided = 0
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.encounter_type = 68
776
- AND e.encounter_id = obs.encounter_id
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.patient_id = obs.person_id
795
- AND e.voided = 0
796
- AND e.encounter_type = 7
797
- AND e.program_id = 1
798
- AND obs.voided = 0
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
- DATE(o.start_date) AS visit_date,
810
- DATE(MIN(o.auto_expire_date)) AS drug_runout_date,
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.voided = 0
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
- m.patient_id, o.order_id, orders.encounter_id , m.visit_date,
834
- d.drug_id, d.name, d.units, o.equivalent_daily_dose, orders.instructions,
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 FROM #{schema}.encounter e
872
- INNER JOIN #{schema}.obs t1 ON t1.encounter_id = e.encounter_id AND e.voided = 0
873
- AND t1.voided = 0 AND e.encounter_type = 52 AND t1.concept_id = 7562
874
- INNER JOIN #{schema}.concept_name cn ON cn.concept_id = t1.value_coded AND cn.voided = 0
875
- WHERE LENGTH(cn.name) > 0
876
- GROUP BY e.patient_id ORDER BY t1.obs_datetime DESC, t1.date_created DESC
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 FROM #{schema}.encounter e
884
- INNER JOIN #{schema}.obs t1 ON t1.encounter_id = e.encounter_id AND e.voided = 0
885
- AND t1.voided = 0 AND e.encounter_type = 52 AND t1.concept_id = 7563
886
- INNER JOIN #{schema}.concept_name cn ON cn.concept_id = t1.value_coded AND cn.voided = 0
887
- WHERE LENGTH(cn.name) > 0
888
- GROUP BY e.patient_id ORDER BY t1.obs_datetime DESC, t1.date_created DESC;
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 :fhir_encounters, :fhir_observations, :regimen_combinations,
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
- process_location(loc)
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
- write_data_to_files
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(patients_ids:, schema:)
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.match(/f/i) ? 'female' : 'male'
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(patients_ids:, schema:)
194
+ def fetch_visits(schema:)
185
195
  ActiveRecord::Base.connection.select_all <<~SQL
186
- SELECT * FROM #{schema}.data_sanitizer_visits
187
- WHERE patient_id IN(#{patients_ids.join(',')})
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
- @faker_names[attribute] ||= faker_module.send(faker_method)
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
- puts "Created file: #{file_path}"
430
+ Rails.logger.info "Appended to file: #{file_path}"
417
431
  end
418
432
  end
419
433
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module OpenmrsDataSanitizer
4
- VERSION = '1.0.3'
4
+ VERSION = '1.0.4'
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.3
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-08-26 00:00:00.000000000 Z
11
+ date: 2024-09-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby