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: 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