malawi_hiv_program_reports 1.0.12 → 1.0.13

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: 88faa7e9640f4c16749d15f38fe4dc3ae068850cda349e2f5816b9fd3452c4b5
4
- data.tar.gz: 11134ce6349f51dee3e3cb5507e2d03c26d2c6dd9ab21993fc61cf31938c9e6a
3
+ metadata.gz: e822549d8adf92be3c36169ba9b0f279b8e36837e237dff82bf7a06f1eed7a6a
4
+ data.tar.gz: df4680fed4a17a65e077a9648fd06d752a816b8845c80141a99d9e895eb5bcee
5
5
  SHA512:
6
- metadata.gz: 4e5ab0ea1bcbeabad67e7f9b1ef7d0fb29c7477f6fbda180e757df8d1ae6729af1e0f393b4a754f981358e57cbb96fafabb09a2cd42dd3122673e63908121f51
7
- data.tar.gz: 6222839d0182b965055094bbeb1a7ddfa7b364df27bc544acaa6e31a542ab9aac36a6741ff937423b919d5d9912708cf467a3a0312ff94c956a8fc5a5cccbcf9
6
+ metadata.gz: f948b554218cf4420b06a37a98028bbceebb06aad04a61d3cce9651aadfbc429dc6603d853e03d51eb5bbe51688b4bfd7b704301c4f53c99031985dfb1cca53b
7
+ data.tar.gz: 1214999f3ee1fbb72287e31f634e28aa650ec6a9ba9b5cedb29c38416f7a53cedd0adf4d521bada6a1d562b1054a9087e3e43174752d8fbf7cf6939889a1854a
@@ -86,11 +86,12 @@ module MalawiHivProgramReports
86
86
  ActiveRecord::Base.connection.execute <<-SQL
87
87
  CREATE TABLE temp_register_start_date (
88
88
  patient_id INT NOT NULL,
89
- site_id INT DEFAULT NULL,
89
+ site_id INT NOT NULL,
90
90
  start_date DATE NOT NULL,
91
- PRIMARY KEY (patient_id)
91
+ PRIMARY KEY (patient_id, site_id)
92
92
  ) #{adapter == 'mysql2' ? 'ENGINE=InnoDB DEFAULT CHARSET=utf8' : ''};
93
93
  SQL
94
+ ActiveRecord::Base.connection.execute 'CREATE INDEX trsd_date ON temp_register_start_date (start_date)'
94
95
  end
95
96
 
96
97
  def exe_temp_order_details_table(adapter:)
@@ -19,6 +19,8 @@ module MalawiHivProgramReports
19
19
 
20
20
  def update_cummulative_outcomes
21
21
  initialize_table
22
+ create_tmp_max_drug_orders
23
+ create_tmp_min_auto_expire_date
22
24
 
23
25
  # HIC SUNT DRACONIS: The order of the operations below matters,
24
26
  # do not change it unless you know what you are doing!!!
@@ -208,7 +210,7 @@ module MalawiHivProgramReports
208
210
  AND voided = 0 #{site_manager(operator: 'AND', column: 'patient_state.site_id', location: @location)}
209
211
  )
210
212
  AND patients.patient_id NOT IN (SELECT patient_id FROM temp_patient_outcomes #{site_manager(operator: 'WHERE', column: 'patient_program.site_id', location: @location)} )
211
- GROUP BY patients.patient_id
213
+ GROUP BY patients.patient_id HAVING cum_outcome = 'Defaulted'
212
214
  SQL
213
215
  end
214
216
 
@@ -237,6 +239,59 @@ module MalawiHivProgramReports
237
239
  SQL
238
240
  end
239
241
 
242
+ # rubocop:disable Metrics/MethodLength
243
+ def create_tmp_max_drug_orders
244
+ date = ActiveRecord::Base.connection.quote(end_date)
245
+ ActiveRecord::Base.connection.execute 'DROP TABLE IF EXISTS tmp_max_drug_orders'
246
+ ActiveRecord::Base.connection.execute <<~SQL
247
+ CREATE TABLE tmp_max_drug_orders(
248
+ patient_id INT(11) PRIMARY KEY,
249
+ start_date DATETIME NOT NULL,
250
+ site_id INT NOT NULL
251
+ )
252
+ SQL
253
+ ActiveRecord::Base.connection.execute 'CREATE INDEX idx_tmp_max_drug_orders ON tmp_max_drug_orders (patient_id, start_date)'
254
+ ActiveRecord::Base.connection.execute 'CREATE INDEX tmdo_site_id ON tmp_max_drug_orders (site_id)'
255
+ ActiveRecord::Base.connection.execute <<~SQL
256
+ INSERT INTO tmp_max_drug_orders
257
+ SELECT o.patient_id, MAX(o.start_date) AS start_date, o.site_id
258
+ FROM orders o
259
+ INNER JOIN temp_earliest_start_date tesd ON tesd.patient_id = o.patient_id AND tesd.site_id = o.site_id #{site_manager(operator: 'AND', column: 'o.site_id', location: @location)}
260
+ INNER JOIN drug_order ON o.order_id = drug_order.order_id AND quantity > 0 #{site_manager(operator: 'AND', column: 'drug_order.site_id', location: @location)}
261
+ INNER JOIN arv_drug ad ON ad.drug_id = drug_order.drug_inventory_id
262
+ WHERE o.order_type_id = #{drug_order_type.order_type_id}
263
+ AND o.start_date < (DATE(#{date}) + INTERVAL 1 DAY)
264
+ AND o.voided = 0 #{site_manager(operator: 'AND', column: 'o.site_id', location: @location)}
265
+ AND o.patient_id NOT IN (SELECT patient_id FROM temp_patient_outcomes #{site_manager(operator: 'WHERE', column: 'site_id', location: @location)})
266
+ GROUP BY o.patient_id
267
+ SQL
268
+ end
269
+
270
+ def create_tmp_min_auto_expire_date
271
+ ActiveRecord::Base.connection.execute 'DROP TABLE IF EXISTS tmp_min_auto_expire_date'
272
+ ActiveRecord::Base.connection.execute <<~SQL
273
+ CREATE TABLE tmp_min_auto_expire_date(
274
+ patient_id INT(11) PRIMARY KEY,
275
+ auto_expire_date DATETIME NOT NULL,
276
+ site_id INT NOT NULL
277
+ )
278
+ SQL
279
+ ActiveRecord::Base.connection.execute 'CREATE INDEX idx_tmp_min_auto_expire_date ON tmp_min_auto_expire_date (patient_id, auto_expire_date)'
280
+ ActiveRecord::Base.connection.execute 'CREATE INDEX tmaed_site_id ON tmp_min_auto_expire_date (site_id)'
281
+ ActiveRecord::Base.connection.execute <<~SQL
282
+ INSERT INTO tmp_min_auto_expire_date
283
+ SELECT patient_id, MIN(auto_expire_date) AS auto_expire_date, o.site_id
284
+ FROM orders o
285
+ INNER JOIN tmp_max_drug_orders USING (patient_id, start_date, site_id)
286
+ INNER JOIN drug_order ON o.order_id = drug_order.order_id AND quantity > 0 #{site_manager(operator: 'AND', column: 'drug_order.site_id', location: @location)}
287
+ INNER JOIN arv_drug ad ON ad.drug_id = drug_order.drug_inventory_id
288
+ WHERE o.order_type_id = #{drug_order_type.order_type_id}
289
+ AND o.voided = 0 #{site_manager(operator: 'AND', column: 'o.site_id', location: @location)}
290
+ GROUP BY patient_id HAVING auto_expire_date IS NOT NULL
291
+ SQL
292
+ end
293
+ # rubocop:enable Metrics/MethodLength
294
+
240
295
  # Loads all patients who are on treatment
241
296
  def load_patients_on_treatment
242
297
  date = ActiveRecord::Base.connection.quote(end_date)
@@ -270,35 +325,9 @@ module MalawiHivProgramReports
270
325
  ARV dispensations. In other words filter out any `on ARVs` states whose
271
326
  dispensation's may have been voided or states that were created manually
272
327
  without any drugs being dispensed. */
273
- INNER JOIN (
274
- SELECT orders.patient_id, MIN(orders.auto_expire_date) AS auto_expire_date
275
- FROM orders
276
- INNER JOIN drug_order ON orders.order_id = drug_order.order_id #{site_manager(operator: 'AND', column: 'drug_order.site_id', location: @location)}
277
- INNER JOIN (
278
- SELECT patient_id, MAX(start_date) AS start_date
279
- FROM orders
280
- INNER JOIN drug_order ON orders.order_id = drug_order.order_id #{site_manager(operator: 'AND', column: 'drug_order.site_id', location: @location)} AND drug_order.quantity > 0
281
- WHERE order_type_id = #{drug_order_type.order_type_id}
282
- AND concept_id IN (#{arv_drugs_concept_set.to_sql})
283
- AND orders.start_date < #{interval_manager(date:, value: 1, interval: 'DAY', operator: '+')}
284
- AND voided = 0 #{site_manager(operator: 'AND', column: 'orders.site_id', location: @location)}
285
- AND patient_id IN (SELECT patient_id FROM temp_earliest_start_date #{site_manager(operator: 'WHERE', column: 'site_id', location: @location)} )
286
- AND patient_id NOT IN (SELECT patient_id FROM temp_patient_outcomes #{site_manager(operator: 'WHERE', column: 'site_id', location: @location)} )
287
- GROUP BY patient_id
288
- ) AS max_drug_orders
289
- ON max_drug_orders.patient_id = orders.patient_id
290
- AND max_drug_orders.start_date = orders.start_date #{site_manager(operator: 'AND', column: 'orders.site_id', location: @location)}
291
- WHERE order_type_id = #{drug_order_type.order_type_id}
292
- AND concept_id IN (#{arv_drugs_concept_set.to_sql})
293
- AND orders.start_date < #{interval_manager(date:, value: 1, interval: 'DAY', operator: '+')}
294
- AND quantity > 0
295
- AND voided = 0 #{site_manager(operator: 'AND', column: 'orders.site_id', location: @location)}
296
- AND orders.patient_id IN (SELECT patient_id FROM temp_earliest_start_date #{site_manager(operator: 'WHERE', column: 'site_id', location: @location)})
297
- AND orders.patient_id NOT IN (SELECT patient_id FROM temp_patient_outcomes #{site_manager(operator: 'WHERE', column: 'site_id', location: @location)})
298
- GROUP BY orders.patient_id
299
- ) AS first_order_to_expire
328
+ INNER JOIN tmp_min_auto_expire_date AS first_order_to_expire
300
329
  ON (first_order_to_expire.auto_expire_date >= #{date} OR #{timestampdiff_manager(date1: 'DATE(first_order_to_expire.auto_expire_date)', date2: date, interval: 'DAY')} <= #{@definition == 'pepfar' ? 28 : 56})
301
- AND first_order_to_expire.patient_id = patient_program.patient_id #{site_manager(operator: 'AND', column: 'patient_program.site_id', location: @location)}
330
+ AND first_order_to_expire.patient_id = patient_program.patient_id #{site_manager(operator: 'AND', column: 'first_order_to_expire.site_id', location: @location)} #{site_manager(operator: 'AND', column: 'patient_program.site_id', location: @location)}
302
331
  WHERE patients.date_enrolled <= #{date} #{site_manager(operator: 'AND', column: 'patients.site_id', location: @location)}
303
332
  AND patients.patient_id NOT IN (SELECT patient_id FROM temp_patient_outcomes #{site_manager(operator: 'WHERE', column: 'site_id', location: @location)} )
304
333
  GROUP BY patients.patient_id #{@adapter == 'mysql2' ? '' : ',patient_state.start_date'}
@@ -9,7 +9,7 @@ module MalawiHivProgramReports
9
9
  def patient_regimens(date, location)
10
10
  @location = location
11
11
  @adapter = ActiveRecord::Base.connection.adapter_name.downcase
12
- date = ActiveRecord::Base.connection.quote(date)
12
+ ActiveRecord::Base.connection.quote(date)
13
13
 
14
14
  ActiveRecord::Base.connection.select_all <<~SQL
15
15
  SELECT prescriptions.patient_id,
@@ -19,33 +19,17 @@ module MalawiHivProgramReports
19
19
  FROM (
20
20
  SELECT orders.patient_id,
21
21
  #{@adapter == 'mysql2' ? 'GROUP_CONCAT(DISTINCT drug_order.drug_inventory_id ORDER BY drug_order.drug_inventory_id ASC) AS drugs,' : "(SELECT STRING_AGG(drug_inventory_id::VARCHAR, ',') FROM (SELECT DISTINCT drug_order.drug_inventory_id FROM drug_order ORDER BY drug_order.drug_inventory_id ASC) AS subquery) AS drugs,"}
22
- recent_prescription.prescription_date
22
+ DATE(tmdo.start_date) prescription_date
23
23
  FROM temp_patient_outcomes AS outcomes
24
+ INNER JOIN tmp_max_drug_orders tmdo ON tmdo.patient_id = outcomes.patient_id AND outcomes.cum_outcome = 'On antiretrovirals' #{site_manager(operator: 'AND', column: 'tmdo.site_id', location: @location)}
24
25
  INNER JOIN orders
25
26
  ON orders.patient_id = outcomes.patient_id
26
27
  AND orders.concept_id IN (#{arv_drugs_concept_set.to_sql})
27
28
  AND orders.voided = 0 #{site_manager(operator: 'AND', column: 'orders.site_id', location: @location)}
29
+ AND DATE(orders.start_date) = DATE(tmdo.start_date)
28
30
  INNER JOIN drug_order
29
31
  ON drug_order.order_id = orders.order_id AND drug_order.quantity > 0 #{site_manager(operator: 'AND', column: 'drug_order.site_id', location: @location)}
30
32
  /* Only select drugs prescribed on the last prescription day */
31
- INNER JOIN (
32
- SELECT patient_id, DATE(MAX(start_date)) AS prescription_date
33
- FROM orders
34
- INNER JOIN drug_order
35
- ON drug_order.order_id = orders.order_id
36
- AND drug_order.quantity > 0 #{site_manager(operator: 'AND', column: 'drug_order.site_id', location: @location)}
37
- WHERE orders.voided = 0 #{site_manager(operator: 'AND', column: 'orders.site_id', location: @location)}
38
- AND orders.concept_id IN (#{arv_drugs_concept_set.to_sql})
39
- AND orders.start_date < #{interval_manager(date:, value: 1, interval: 'DAY', operator: '+')}
40
- AND orders.patient_id IN (
41
- SELECT patient_id FROM temp_patient_outcomes WHERE cum_outcome = 'On antiretrovirals' #{site_manager(operator: 'AND', column: 'site_id', location: @location)}
42
- )
43
- GROUP BY orders.patient_id
44
- ) AS recent_prescription
45
- ON recent_prescription.patient_id = orders.patient_id
46
- AND orders.start_date
47
- BETWEEN recent_prescription.prescription_date
48
- AND #{interval_manager(date: 'recent_prescription.prescription_date', value: 1, interval: 'DAY', operator: '+')}
49
33
  GROUP BY orders.patient_id #{@adapter == 'mysql2' ? '' : ', recent_prescription.prescription_date'}
50
34
  ) AS prescriptions
51
35
  LEFT JOIN (
@@ -29,9 +29,11 @@ module MalawiHivProgramReports
29
29
  drop_temp_register_start_date_table
30
30
  drop_temp_other_patient_types
31
31
  drop_temp_order_details
32
+ drop_art_start_date
32
33
  create_temp_other_patient_types(end_date)
33
34
  create_temp_register_start_date_table(end_date)
34
35
  create_temp_order_details(end_date)
36
+ create_art_start_date(end_date)
35
37
  load_data_into_temp_earliest_start_date(end_date.to_date, occupation)
36
38
  update_cum_outcome(end_date)
37
39
  end
@@ -43,9 +45,11 @@ module MalawiHivProgramReports
43
45
  drop_temp_register_start_date_table
44
46
  drop_temp_other_patient_types
45
47
  drop_temp_order_details
48
+ drop_art_start_date
46
49
  create_temp_other_patient_types(end_date)
47
50
  create_temp_register_start_date_table(end_date)
48
51
  create_temp_order_details(end_date)
52
+ create_art_start_date(end_date)
49
53
  load_data_into_temp_earliest_start_date(end_date.to_date, occupation)
50
54
 
51
55
  # create_tmp_patient_table_2(end_date)
@@ -92,7 +96,7 @@ module MalawiHivProgramReports
92
96
  cohort_struct.quarterly_all_males = males(quarter_start_date, end_date)
93
97
 
94
98
  # Pregnant females (all ages)
95
- create_temp_pregnant_obs(start_date, end_date)
99
+ create_temp_pregnant_obs(cum_start_date, end_date)
96
100
  cohort_struct.pregnant_females_all_ages = pregnant_females_all_ages(start_date, end_date)
97
101
  cohort_struct.cum_pregnant_females_all_ages = pregnant_females_all_ages(cum_start_date, end_date)
98
102
  cohort_struct.quarterly_pregnant_females_all_ages = pregnant_females_all_ages(quarter_start_date, end_date)
@@ -678,11 +682,11 @@ module MalawiHivProgramReports
678
682
  def load_data_into_temp_cohort_members_table(end_date)
679
683
  end_date = ActiveRecord::Base.connection.quote(end_date)
680
684
 
681
- type_of_patient_concept = concept('Type of patient').concept_id
682
- new_patient_concept = concept('New patient').concept_id
683
- drug_refill_concept = concept('Drug refill').concept_id
684
- external_concept = concept('External Consultation').concept_id
685
- program_id = program('HIV program').id
685
+ concept('Type of patient').concept_id
686
+ concept('New patient').concept_id
687
+ concept('Drug refill').concept_id
688
+ concept('External Consultation').concept_id
689
+ program('HIV program').id
686
690
 
687
691
  ActiveRecord::Base.connection.execute <<~SQL
688
692
  INSERT INTO temp_cohort_members
@@ -693,7 +697,7 @@ module MalawiHivProgramReports
693
697
  person.birthdate,
694
698
  #{@adapter == 'mysql2' ? 'person.birthdate_estimated' : '(CASE WHEN person.birthdate_estimated = 0 THEN false ELSE true END)'} AS birthdate_estimated,
695
699
  person.death_date,
696
- person.gender, #{
700
+ LEFT(person.gender, 1) gender, #{
697
701
  if @adapter == 'mysql2'
698
702
  <<~SQL
699
703
  IF(person.birthdate IS NOT NULL, TIMESTAMPDIFF(YEAR, person.birthdate, DATE(COALESCE(art_start_date_obs.value_datetime, MIN(art_order.start_date)))), NULL) AS age_at_initiation,
@@ -720,65 +724,21 @@ module MalawiHivProgramReports
720
724
  ORDER BY obs_datetime DESC, date_created DESC LIMIT 1) as reason_for_starting_art,
721
725
  pa.value AS occupation
722
726
  FROM patient_program
723
- INNER JOIN person ON person.person_id = patient_program.patient_id #{site_manager(operator: 'AND', column: 'person.site_id', location: @location)}
727
+ INNER JOIN person ON person.person_id = patient_program.patient_id AND person.voided = 0 #{site_manager(operator: 'AND', column: 'person.site_id', location: @location)}
724
728
  LEFT JOIN (#{current_occupation_query}) pa ON pa.person_id = patient_program.patient_id #{site_manager(operator: 'AND', column: 'pa.site_id', location: @location)}
725
729
  LEFT JOIN patient_state AS outcome
726
730
  ON outcome.patient_program_id = patient_program.patient_program_id #{site_manager(operator: 'AND', column: 'outcome.site_id', location: @location)}
727
- LEFT JOIN encounter AS clinic_registration_encounter
728
- ON clinic_registration_encounter.encounter_type = (
729
- SELECT encounter_type_id FROM encounter_type WHERE LOWER(name) = LOWER('HIV CLINIC REGISTRATION') LIMIT 1
730
- )
731
- AND clinic_registration_encounter.patient_id = patient_program.patient_id
732
- AND clinic_registration_encounter.program_id = patient_program.program_id
733
- AND clinic_registration_encounter.encounter_datetime < #{interval_manager(date: end_date, value: 1, interval: 'DAY', operator: '+')}
734
- AND clinic_registration_encounter.voided = 0 #{site_manager(operator: 'AND', column: 'clinic_registration_encounter.site_id', location: @location)}
735
- LEFT JOIN obs AS art_start_date_obs
736
- ON art_start_date_obs.concept_id = 2516
737
- AND art_start_date_obs.person_id = patient_program.patient_id
738
- AND art_start_date_obs.voided = 0 #{site_manager(operator: 'AND', column: 'art_start_date_obs.site_id', location: @location)}
739
- AND art_start_date_obs.obs_datetime < #{interval_manager(date: end_date, value: 1, interval: 'DAY', operator: '+')}
740
- AND art_start_date_obs.encounter_id = clinic_registration_encounter.encounter_id
741
- /* TODO: Re-enable the following condition. Has been removed because LLH and PIH
742
- were noted to be dropping patients because of it. Seems these sites may have orders
743
- without corresponding encounters. Adding this condition bumps up performance a bit. */
744
- /* INNER JOIN encounter AS prescription_encounter
745
- ON prescription_encounter.patient_id = patient_program.patient_id
746
- AND prescription_encounter.program_id = patient_program.program_id
747
- AND prescription_encounter.encounter_datetime < DATE(#{end_date}) + INTERVAL 1 DAY
748
- AND prescription_encounter.encounter_type IN (SELECT encounter_type_id FROM encounter_type WHERE name LIKE 'Treatment')
749
- AND prescription_encounter.voided = 0
750
- LEFT JOIN temp_register_start_date AS patient_type_obs
751
- ON patient_type_obs.patient_id = patient_program.patient_id #{site_manager(operator: 'AND', column: 'patient_type_obs.site_id', location: @location)}
752
- INNER JOIN orders AS art_order
753
- ON art_order.patient_id = patient_program.patient_id
754
- -- AND art_order.encounter_id = prescription_encounter.encounter_id
755
- AND art_order.concept_id IN (SELECT concept_id FROM concept_set WHERE concept_set = 1085)
756
- AND art_order.start_date < #{interval_manager(date: end_date, value: 1, interval: 'DAY', operator: '+')}
757
- AND art_order.order_type_id = #{order_type('Drug order').id}
758
- AND art_order.start_date >= COALESCE(patient_type_obs.start_date, DATE('1901-01-01'))
759
- AND art_order.voided = 0 #{site_manager(operator: 'AND', column: 'art_order.site_id', location: @location)}
760
- INNER JOIN drug_order
761
- ON drug_order.order_id = art_order.order_id
762
- AND drug_order.quantity > 0 #{site_manager(operator: 'AND', column: 'drug_order.site_id', location: @location)} */
731
+ LEFT JOIN temp_art_start_date AS art_start_date_obs
732
+ ON art_start_date_obs.patient_id = patient_program.patient_id #{site_manager(operator: 'AND', column: 'art_start_date_obs.site_id', location: @location)}
763
733
  INNER JOIN temp_order_details AS art_order ON art_order.patient_id = patient_program.patient_id #{site_manager(operator: 'AND', column: 'art_order.site_id', location: @location)}
734
+ AND art_order.start_date <= DATE(#{end_date})
764
735
  WHERE patient_program.voided = 0
765
736
  AND outcome.voided = 0
766
737
  AND patient_program.program_id = 1
767
738
  AND outcome.state = 7
768
739
  AND outcome.start_date IS NOT NULL #{site_manager(operator: 'AND', column: 'patient_program.site_id', location: @location)}
769
- /*AND patient_program.patient_id NOT IN (
770
- SELECT e.patient_id FROM encounter e
771
- LEFT JOIN (SELECT * FROM obs WHERE concept_id = #{type_of_patient_concept} AND voided = 0 AND value_coded = #{new_patient_concept}) AS new_patient ON e.patient_id = new_patient.person_id
772
- LEFT JOIN (SELECT * FROM obs WHERE concept_id = #{type_of_patient_concept} AND voided = 0 AND value_coded = #{drug_refill_concept}) AS refill ON e.patient_id = refill.person_id
773
- LEFT JOIN (SELECT * FROM obs WHERE concept_id = #{type_of_patient_concept} AND voided = 0 AND value_coded = #{external_concept}) AS external ON e.patient_id = external.person_id
774
- WHERE e.program_id = #{program_id} AND (refill.value_coded IS NOT NULL OR external.value_coded IS NOT NULL)
775
- AND new_patient.value_coded IS NULL
776
- AND e.encounter_datetime < DATE(#{end_date}) + INTERVAL 1 DAY
777
- AND e.encounter_type IN (SELECT encounter_type_id FROM encounter_type WHERE name = 'REGISTRATION' AND retired = 0)
778
- GROUP BY e.patient_id
779
- )*/
780
740
  GROUP by patient_program.patient_id #{@adapter == 'mysql2' ? '' : ',person.birthdate, person.birthdate_estimated, person.death_date, person.gender, pa.value'}
781
- HAVING #{@adapter == 'mysql2' ? 'date_enrolled' : 'art_order.start_date'} <= #{end_date}
741
+ HAVING reason_for_starting_art IS NOT NULL
782
742
  SQL
783
743
  remove_drug_refills_and_external_consultation(end_date)
784
744
  end
@@ -858,6 +818,44 @@ module MalawiHivProgramReports
858
818
  SQL
859
819
  end
860
820
 
821
+ def drop_art_start_date
822
+ ActiveRecord::Base.connection.execute <<~SQL
823
+ DROP TABLE IF EXISTS temp_art_start_date
824
+ SQL
825
+ end
826
+
827
+ def create_art_start_date(end_date)
828
+ ActiveRecord::Base.connection.execute <<-SQL
829
+ CREATE TABLE temp_art_start_date (
830
+ patient_id INT(11) NOT NULL,
831
+ value_datetime DATE NOT NULL,
832
+ site_id INT(11) NOT NULL,
833
+ PRIMARY KEY (patient_id)
834
+ )
835
+ SQL
836
+ ActiveRecord::Base.connection.execute 'CREATE INDEX tasd_date ON temp_art_start_date (value_datetime)'
837
+ ActiveRecord::Base.connection.execute 'CREATE INDEX tasd_site ON temp_art_start_date (site_id)'
838
+ load_art_start_date(end_date)
839
+ end
840
+
841
+ def load_art_start_date(end_date)
842
+ ActiveRecord::Base.connection.execute <<-SQL
843
+ INSERT INTO temp_art_start_date
844
+ SELECT o.person_id, DATE(MIN(o.value_datetime)) value_datetime, o.site_id
845
+ FROM encounter e
846
+ INNER JOIN obs o ON o.encounter_id = e.encounter_id#{' '}
847
+ AND o.concept_id = 2516#{' '}
848
+ AND e.encounter_type = 9#{' '}
849
+ AND e.program_id = 1#{' '}
850
+ AND e.voided = 0 #{site_manager(operator: 'AND', column: 'e.site_id', location: @location)}
851
+ AND e.encounter_datetime < DATE('#{end_date}') + INTERVAL 1 DAY
852
+ AND o.obs_datetime < (DATE('#{end_date}') + INTERVAL 1 DAY)
853
+ AND e.voided = 0 #{site_manager(operator: 'AND', column: 'o.site_id', location: @location)}
854
+ WHERE e.voided = 0 #{site_manager(operator: 'AND', column: 'e.site_id', location: @location)}
855
+ GROUP BY o.person_id
856
+ SQL
857
+ end
858
+
861
859
  def create_temp_order_details(end_date)
862
860
  exe_temp_order_details_table(adapter: @adapter)
863
861
  ActiveRecord::Base.connection.execute <<~SQL
@@ -1001,19 +999,18 @@ module MalawiHivProgramReports
1001
999
  ActiveRecord::Base.connection.execute('CREATE INDEX patient_id_site_id_index ON temp_patient_tb_status (patient_id, site_id)')
1002
1000
  ActiveRecord::Base.connection.execute('CREATE INDEX patient_id_tb_status_index ON temp_patient_tb_status (patient_id, tb_status)')
1003
1001
 
1002
+ prepare_latest_tb_status_table
1003
+ create_temp_latest_tb_status(end_date)
1004
+
1004
1005
  ActiveRecord::Base.connection.execute <<~SQL
1005
- INSERT INTO temp_patient_tb_status (patient_id, tb_status)
1006
- SELECT e.patient_id, obs.value_coded
1007
- FROM temp_earliest_start_date e
1008
- INNER JOIN temp_patient_outcomes o ON o.patient_id = e.patient_id #{site_manager(operator: 'AND', column: 'o.site_id', location: @location)}
1009
- RIGHT JOIN obs ON obs.person_id = o.patient_id #{site_manager(operator: 'AND', column: 'obs.site_id', location: @location)}
1010
- WHERE e.date_enrolled <= '#{end_date}' AND obs.obs_datetime <= '#{end_date} 23:59:59'
1011
- AND LOWER(cum_outcome) = LOWER('On antiretrovirals') AND obs.voided = 0
1006
+ INSERT INTO temp_patient_tb_status
1007
+ SELECT e.person_id, obs.value_coded, e.site_id
1008
+ FROM temp_latest_tb_status e
1009
+ INNER JOIN obs ON obs.person_id = e.person_id AND obs.voided = 0
1012
1010
  AND obs.concept_id = 7459 #{site_manager(operator: 'AND', column: 'e.site_id', location: @location)}
1013
- AND obs.obs_datetime = (
1014
- SELECT MAX(t.obs_datetime) FROM obs t WHERE t.concept_id = 7459 AND t.voided = 0
1015
- AND t.person_id = e.patient_id AND t.obs_datetime <= '#{end_date} 23:59:59' #{site_manager(operator: 'AND', column: 't.site_id', location: @location)}
1016
- ) GROUP BY e.patient_id #{@adapter == 'mysql2' ? '' : ', obs.value_coded'}
1011
+ AND obs.obs_datetime = e.obs_datetime #{site_manager(operator: 'AND', column: 'obs.site_id', location: @location)}
1012
+ #{site_manager(operator: 'WHERE', column: 'e.site_id', location: @location)}
1013
+ GROUP BY e.person_id;
1017
1014
  SQL
1018
1015
  end
1019
1016
 
@@ -1023,6 +1020,34 @@ module MalawiHivProgramReports
1023
1020
 
1024
1021
  private
1025
1022
 
1023
+ def prepare_latest_tb_status_table
1024
+ ActiveRecord::Base.connection.execute <<~SQL
1025
+ CREATE TABLE IF NOT EXISTS temp_latest_tb_status(
1026
+ person_id INT PRIMARY KEY,
1027
+ obs_datetime DATETIME,
1028
+ site_id INT NOT NULL
1029
+ )
1030
+ SQL
1031
+ unless ActiveRecord::Base.connection.index_exists?(:temp_latest_tb_status, :obs_datetime)
1032
+ ActiveRecord::Base.connection.execute 'CREATE INDEX tlts_date ON temp_latest_tb_status(obs_datetime)'
1033
+ end
1034
+ unless ActiveRecord::Base.connection.index_exists?(:temp_latest_tb_status, :site_id)
1035
+ ActiveRecord::Base.connection.execute 'CREATE INDEX tlts_site ON temp_latest_tb_status(site_id)'
1036
+ end
1037
+ ActiveRecord::Base.connection.execute 'TRUNCATE temp_latest_tb_status'
1038
+ end
1039
+
1040
+ def create_temp_latest_tb_status(end_date)
1041
+ ActiveRecord::Base.connection.select_all <<~SQL
1042
+ INSERT INTO temp_latest_tb_status
1043
+ SELECT t.person_id, MAX(t.obs_datetime) obs_datetime, t.site_id
1044
+ FROM obs t
1045
+ INNER JOIN temp_patient_outcomes o ON o.patient_id = t.person_id AND o.cum_outcome = 'On antiretrovirals' #{site_manager(operator: 'AND', column: 'o.site_id', location: @location)} #{site_manager(operator: 'AND', column: 't.site_id', location: @location)}
1046
+ WHERE t.concept_id = 7459 AND t.voided = 0 AND t.obs_datetime <= '#{end_date} 23:59:59' #{site_manager(operator: 'AND', column: 't.site_id', location: @location)}
1047
+ GROUP BY t.person_id
1048
+ SQL
1049
+ end
1050
+
1026
1051
  def total_patients_with_screened_bp(total_alive_and_on_art, _start_date, end_date)
1027
1052
  return 0 if total_alive_and_on_art.blank? || total_alive_and_on_art.empty?
1028
1053
 
@@ -1030,23 +1055,13 @@ module MalawiHivProgramReports
1030
1055
  .select(:concept_id)
1031
1056
 
1032
1057
  results = ActiveRecord::Base.connection.select_all <<~SQL
1033
- SELECT o.person_id
1034
- FROM obs o
1035
- INNER JOIN (
1036
- SELECT person_id, MAX(obs.obs_datetime) AS obs_datetime
1037
- FROM obs
1038
- WHERE voided = 0 AND concept_id IN (#{bp_concepts.to_sql})
1039
- AND (value_text IS NOT NULL OR value_numeric IS NOT NULL)
1040
- AND obs_datetime < #{interval_manager(date: end_date, value: 1, interval: 'DAY', operator: '+')} AND obs_datetime >= #{interval_manager(date: end_date, value: 12, interval: 'MONTH', operator: '-')}
1041
- AND #{in_manager(column: 'person_id', values: total_alive_and_on_art)} #{site_manager(operator: 'AND', column: 'obs.site_id', location: @location)}
1042
- GROUP BY person_id
1043
- ) AS max_obs
1044
- ON max_obs.person_id = o.person_id
1045
- AND max_obs.obs_datetime = o.obs_datetime
1046
- WHERE o.voided = 0 #{site_manager(operator: 'AND', column: 'o.site_id', location: @location)}
1047
- AND o.concept_id IN (#{bp_concepts.to_sql})
1048
- AND (o.value_text IS NOT NULL OR o.value_numeric IS NOT NULL)
1049
- GROUP BY o.person_id
1058
+ SELECT person_id
1059
+ FROM obs
1060
+ WHERE voided = 0 AND concept_id IN (#{bp_concepts.to_sql})
1061
+ AND (value_text IS NOT NULL OR value_numeric IS NOT NULL)
1062
+ AND obs_datetime < #{interval_manager(date: end_date, value: 1, interval: 'DAY', operator: '+')} AND obs_datetime >= #{interval_manager(date: end_date, value: 12, interval: 'MONTH', operator: '-')}
1063
+ AND #{in_manager(column: 'person_id', values: total_alive_and_on_art)} #{site_manager(operator: 'AND', column: 'obs.site_id', location: @location)}
1064
+ GROUP BY person_id
1050
1065
  SQL
1051
1066
 
1052
1067
  ((results.count.to_f / total_alive_and_on_art.count) * 100).to_i
@@ -1139,8 +1154,8 @@ module MalawiHivProgramReports
1139
1154
 
1140
1155
  return [] if patient_ids.blank?
1141
1156
 
1142
- results = ActiveRecord::Base.connection.select_all(
1143
- "SELECT ods.patient_id
1157
+ results = ActiveRecord::Base.connection.select_all <<~SQL
1158
+ SELECT ods.patient_id
1144
1159
  FROM orders ods
1145
1160
  INNER JOIN drug_order dos ON ods.order_id = dos.order_id AND ods.voided = 0 #{site_manager(operator: 'AND',
1146
1161
  column: 'dos.site_id', location: @location)}
@@ -1149,21 +1164,8 @@ module MalawiHivProgramReports
1149
1164
  AND #{in_manager(column: 'ods.patient_id', values: patient_ids)}
1150
1165
  AND ods.start_date BETWEEN '#{start_date.to_date.strftime('%Y-%m-%d 00:00:00')}'
1151
1166
  AND '#{end_date.to_date.strftime('%Y-%m-%d 23:59:59')}'
1152
- AND DATE(ods.start_date) = (SELECT MAX(DATE(o.start_date)) FROM orders o
1153
- INNER JOIN drug_order d ON o.order_id = d.order_id AND o.voided = 0 #{site_manager(
1154
- operator: 'AND', column: 'd.site_id', location: @location
1155
- )}
1156
- WHERE #{in_manager(column: 'o.concept_id',
1157
- values: [
1158
- isoniazid_concept_id, pyridoxine_concept_id
1159
- ])}
1160
- AND o.patient_id = ods.patient_id #{site_manager(operator: 'AND',
1161
- column: 'o.site_id', location: @location)}
1162
- AND d.quantity IS NOT NULL
1163
- AND o.start_date BETWEEN '#{start_date.to_date.strftime('%Y-%m-%d 00:00:00')}'
1164
- AND '#{end_date.to_date.strftime('%Y-%m-%d 23:59:59')}')
1165
- GROUP BY ods.patient_id"
1166
- )
1167
+ GROUP BY ods.patient_id
1168
+ SQL
1167
1169
 
1168
1170
  ((results.count.to_f / patient_ids.count) * 100).to_i
1169
1171
  end
@@ -1178,8 +1180,8 @@ module MalawiHivProgramReports
1178
1180
 
1179
1181
  return [] if patient_ids.blank?
1180
1182
 
1181
- results = ActiveRecord::Base.connection.select_all(
1182
- "SELECT ods.patient_id
1183
+ results = ActiveRecord::Base.connection.select_all <<~SQL
1184
+ SELECT ods.patient_id
1183
1185
  FROM orders ods
1184
1186
  INNER JOIN drug_order dos ON ods.order_id = dos.order_id AND ods.voided = 0 #{site_manager(operator: 'AND',
1185
1187
  column: 'dos.site_id', location: @location)}
@@ -1188,24 +1190,13 @@ module MalawiHivProgramReports
1188
1190
  AND ods.patient_id in (#{patient_ids.join(',')})
1189
1191
  AND ods.start_date BETWEEN '#{start_date.to_date.strftime('%Y-%m-%d 00:00:00')}'
1190
1192
  AND '#{end_date.to_date.strftime('%Y-%m-%d 23:59:59')}'
1191
- AND DATE(ods.start_date) = (SELECT MAX(DATE(o.start_date)) FROM orders o
1192
- INNER JOIN drug_order d ON o.order_id = d.order_id AND o.voided = 0 #{site_manager(
1193
- operator: 'AND', column: 'd.site_id', location: @location
1194
- )}
1195
- WHERE o.concept_id = #{cpt_concept_id} #{site_manager(operator: 'AND',
1196
- column: 'o.site_id', location: @location)}
1197
- AND d.quantity > 0
1198
- AND o.patient_id = ods.patient_id
1199
- AND o.start_date BETWEEN '#{start_date.to_date.strftime('%Y-%m-%d 00:00:00')}'
1200
- AND '#{end_date.to_date.strftime('%Y-%m-%d 23:59:59')}')
1201
-
1202
- GROUP BY ods.patient_id"
1203
- )
1193
+ GROUP BY ods.patient_id
1194
+ SQL
1204
1195
 
1205
1196
  ((results.count.to_f / patient_ids.count) * 100).to_i
1206
1197
  end
1207
1198
 
1208
- def total_breastfeeding_women(_patients_list, total_pregnant_women, _start_date, end_date)
1199
+ def total_breastfeeding_women(_patients_list, total_pregnant_women, _start_date, _end_date)
1209
1200
  total_pregnant_women = if total_pregnant_women.empty?
1210
1201
  [0]
1211
1202
  else
@@ -1228,39 +1219,24 @@ module MalawiHivProgramReports
1228
1219
  ON enc.encounter_id = obs.encounter_id
1229
1220
  AND enc.voided = 0 #{site_manager(operator: 'AND', column: 'enc.site_id', location: @location)}
1230
1221
  AND enc.encounter_type IN (#{encounter_types.to_sql})
1222
+ AND obs.voided = 0 AND obs.concept_id IN (#{breastfeeding_concepts.to_sql}) #{site_manager(operator: 'AND', column: 'obs.site_id', location: @location)}
1231
1223
  INNER JOIN temp_earliest_start_date e
1232
1224
  ON e.patient_id = enc.patient_id #{site_manager(operator: 'AND', column: 'e.site_id', location: @location)}
1233
1225
  AND LEFT(e.gender, 1) = 'F'
1226
+ AND e.patient_id NOT IN (#{total_pregnant_women.join(',')})
1234
1227
  INNER JOIN temp_patient_outcomes
1235
1228
  ON temp_patient_outcomes.patient_id = e.patient_id #{site_manager(operator: 'AND', column: 'temp_patient_outcomes.site_id', location: @location)}
1236
1229
  AND temp_patient_outcomes.cum_outcome = 'On antiretrovirals'
1237
- INNER JOIN (
1238
- SELECT person_id, MAX(obs_datetime) AS obs_datetime
1239
- FROM obs
1240
- INNER JOIN encounter
1241
- ON encounter.encounter_id = obs.encounter_id
1242
- AND encounter.encounter_type IN (#{encounter_types.to_sql})
1243
- AND encounter.voided = 0 #{site_manager(operator: 'AND', column: 'encounter.site_id', location: @location)}
1244
- WHERE person_id IN (SELECT patient_id FROM temp_patient_outcomes WHERE cum_outcome = 'On antiretrovirals')
1245
- AND concept_id IN (#{breastfeeding_concepts.to_sql})
1246
- AND obs.voided = 0 #{site_manager(operator: 'AND', column: 'obs.site_id', location: @location)}
1247
- AND obs_datetime < #{interval_manager(date: end_date, value: 1, interval: 'DAY', operator: '+')}
1248
- GROUP BY person_id
1249
- ) AS max_obs
1250
- ON max_obs.person_id = obs.person_id
1251
- AND max_obs.obs_datetime = obs.obs_datetime
1252
- WHERE obs.person_id = e.patient_id
1253
- AND #{in_manager(column: 'obs.person_id', values: total_pregnant_women.join(','), negation: true)}
1254
- AND obs.obs_datetime < #{interval_manager(date: end_date, value: 1, interval: 'DAY', operator: '+')}
1255
- AND obs.concept_id IN (#{breastfeeding_concepts.to_sql})
1256
- AND obs.voided = 0 #{site_manager(operator: 'AND', column: 'obs.site_id', location: @location)}
1230
+ INNER JOIN tmp_max_drug_orders AS max_obs ON max_obs.patient_id = obs.person_id
1231
+ AND DATE(max_obs.start_date) = DATE(obs.obs_datetime) #{site_manager(operator: 'AND', column: 'max_obs.site_id', location: @location)}
1232
+ WHERE obs.person_id = e.patient_id #{site_manager(operator: 'AND', column: 'obs.site_id', location: @location)}
1257
1233
  GROUP BY obs.person_id #{@adapter == 'mysql2' ? '' : ', obs.value_coded'}
1258
1234
  HAVING value_coded = 1065
1259
1235
  ORDER BY MAX(obs.obs_datetime) DESC;
1260
1236
  SQL
1261
1237
  end
1262
1238
 
1263
- def total_pregnant_women(_patients_list, _start_date, end_date)
1239
+ def total_pregnant_women(_patients_list, _start_date, _end_date)
1264
1240
  encounter_types = ::EncounterType.where('LOWER(name) IN (?)',
1265
1241
  ['HIV CLINIC CONSULTATION'.downcase, 'HIV STAGING'.downcase])
1266
1242
  .select(:encounter_type_id)
@@ -1272,32 +1248,19 @@ module MalawiHivProgramReports
1272
1248
  ActiveRecord::Base.connection.select_all <<~SQL
1273
1249
  SELECT obs.person_id, obs.value_coded
1274
1250
  FROM obs obs
1275
- INNER JOIN encounter enc
1276
- ON enc.encounter_id = obs.encounter_id
1277
- AND enc.voided = 0 #{site_manager(operator: 'AND', column: 'enc.site_id', location: @location)}
1278
- AND enc.encounter_type IN (#{encounter_types.to_sql})
1279
- INNER JOIN temp_earliest_start_date e
1280
- ON e.patient_id = enc.patient_id #{site_manager(operator: 'AND', column: 'e.site_id', location: @location)}
1281
- AND LEFT(e.gender, 1) = 'F'
1251
+ INNER JOIN encounter enc
1252
+ ON enc.encounter_id = obs.encounter_id
1253
+ AND enc.voided = 0 #{site_manager(operator: 'AND', column: 'enc.site_id', location: @location)}
1254
+ AND enc.encounter_type IN (#{encounter_types.to_sql})
1255
+ AND obs.voided = 0 AND obs.concept_id IN (#{pregnant_concepts.to_sql}) #{site_manager(operator: 'AND', column: 'obs.site_id', location: @location)}
1256
+ INNER JOIN temp_earliest_start_date e
1257
+ ON e.patient_id = enc.patient_id #{site_manager(operator: 'AND', column: 'e.site_id', location: @location)}
1258
+ AND LEFT(e.gender, 1) = 'F'
1282
1259
  INNER JOIN temp_patient_outcomes
1283
1260
  ON temp_patient_outcomes.patient_id = e.patient_id #{site_manager(operator: 'AND', column: 'temp_patient_outcomes.site_id', location: @location)}
1284
1261
  AND temp_patient_outcomes.cum_outcome = 'On antiretrovirals'
1285
- INNER JOIN (
1286
- SELECT person_id, MAX(obs_datetime) AS obs_datetime
1287
- FROM obs
1288
- INNER JOIN encounter
1289
- ON encounter.encounter_id = obs.encounter_id #{site_manager(operator: 'AND', column: 'encounter.site_id', location: @location)}
1290
- AND encounter.encounter_type IN (#{encounter_types.to_sql})
1291
- AND encounter.voided = 0
1292
- WHERE concept_id IN (#{pregnant_concepts.to_sql})
1293
- AND obs_datetime < #{interval_manager(date: end_date, value: 1, interval: 'DAY', operator: '+')}
1294
- AND obs.voided = 0 #{site_manager(operator: 'AND', column: 'obs.site_id', location: @location)}
1295
- GROUP BY person_id
1296
- ) AS max_obs
1297
- ON max_obs.person_id = obs.person_id
1298
- AND max_obs.obs_datetime = obs.obs_datetime
1299
- WHERE obs.concept_id IN (#{pregnant_concepts.to_sql})
1300
- AND obs.voided = 0 #{site_manager(operator: 'AND', column: 'obs.site_id', location: @location)}
1262
+ INNER JOIN tmp_max_drug_orders AS max_obs ON max_obs.patient_id = obs.person_id
1263
+ AND DATE(max_obs.start_date) = DATE(obs.obs_datetime) #{site_manager(operator: 'AND', column: 'max_obs.site_id', location: @location)}
1301
1264
  GROUP BY obs.person_id #{@adapter == 'mysql2' ? '' : ', obs.value_coded'}
1302
1265
  HAVING obs.value_coded = 1065
1303
1266
  ORDER BY MAX(obs.obs_datetime) DESC;
@@ -1338,28 +1301,13 @@ module MalawiHivProgramReports
1338
1301
  def latest_art_adherence(patients_alive_and_on_art, _start_date, end_date)
1339
1302
  patients_alive_and_on_art = Set.new(patients_alive_and_on_art.map { |patient| patient['patient_id'] })
1340
1303
  end_date = ActiveRecord::Base.connection.quote(end_date)
1304
+ create_tmp_max_adherence(end_date)
1341
1305
 
1342
1306
  not_adherent = ActiveRecord::Base.connection.select_all <<~SQL
1343
1307
  SELECT adherence.person_id
1344
1308
  FROM obs AS adherence
1345
- INNER JOIN (
1346
- SELECT obs.person_id, DATE(MAX(obs.obs_datetime)) AS visit_date
1347
- FROM obs
1348
- INNER JOIN orders
1349
- ON orders.order_id = obs.order_id #{site_manager(operator: 'AND', column: 'orders.site_id', location: @location)}
1350
- AND orders.concept_id IN (#{arv_drug_concepts.to_sql})
1351
- AND orders.order_type_id = #{drug_order_type.order_type_id}
1352
- AND orders.voided = 0
1353
- INNER JOIN temp_patient_outcomes
1354
- ON temp_patient_outcomes.patient_id = obs.person_id #{site_manager(operator: 'AND', column: 'temp_patient_outcomes.site_id', location: @location)}
1355
- AND LOWER(temp_patient_outcomes.cum_outcome) = LOWER('On antiretrovirals')
1356
- WHERE obs.concept_id = #{drug_order_adherence_concept.concept_id}
1357
- AND obs.obs_datetime < #{interval_manager(date: end_date, value: 1, interval: 'DAY', operator: '+')}
1358
- AND (obs.value_numeric IS NOT NULL OR obs.value_text IS NOT NULL)
1359
- AND obs.voided = 0 #{site_manager(operator: 'AND', column: 'obs.site_id', location: @location)}
1360
- GROUP BY obs.person_id
1361
- ) AS max_adherence
1362
- ON max_adherence.person_id = adherence.person_id
1309
+ INNER JOIN tmp_max_adherence AS max_adherence
1310
+ ON max_adherence.person_id = adherence.person_id #{site_manager(operator: 'AND', column: 'max_adherence.site_id', location: @location)}
1363
1311
  AND adherence.obs_datetime >= max_adherence.visit_date #{site_manager(operator: 'AND', column: 'adherence.site_id', location: @location)}
1364
1312
  AND adherence.obs_datetime < #{interval_manager(date: 'max_adherence.visit_date', value: 1, interval: 'DAY', operator: '+')}
1365
1313
  INNER JOIN orders
@@ -1383,27 +1331,11 @@ module MalawiHivProgramReports
1383
1331
  adherent = ActiveRecord::Base.connection.select_all <<~SQL
1384
1332
  SELECT adherence.person_id
1385
1333
  FROM obs AS adherence
1386
- INNER JOIN (
1387
- SELECT obs.person_id, DATE(MAX(obs.obs_datetime)) AS visit_date
1388
- FROM obs
1389
- INNER JOIN orders
1390
- ON orders.order_id = obs.order_id
1391
- AND orders.concept_id IN (#{arv_drug_concepts.to_sql})
1392
- AND orders.order_type_id = #{drug_order_type.order_type_id}
1393
- AND orders.voided = 0 #{site_manager(operator: 'AND', column: 'orders.site_id', location: @location)}
1394
- INNER JOIN temp_patient_outcomes
1395
- ON temp_patient_outcomes.patient_id = obs.person_id #{site_manager(operator: 'AND', column: 'temp_patient_outcomes.site_id', location: @location)}
1396
- AND #{in_manager(column: 'temp_patient_outcomes.patient_id', values: not_adherent.blank? ? [0] : not_adherent.join(','), negation: true)}
1397
- AND LOWER(temp_patient_outcomes.cum_outcome) = LOWER('On antiretrovirals')
1398
- WHERE obs.concept_id = #{drug_order_adherence_concept.concept_id}
1399
- AND obs.obs_datetime < #{interval_manager(date: end_date, value: 1, interval: 'DAY', operator: '+')}
1400
- AND (obs.value_numeric IS NOT NULL OR obs.value_text IS NOT NULL)
1401
- AND obs.voided = 0 #{site_manager(operator: 'AND', column: 'obs.site_id', location: @location)}
1402
- GROUP BY obs.person_id
1403
- ) AS max_adherence
1404
- ON max_adherence.person_id = adherence.person_id
1334
+ INNER JOIN tmp_max_adherence AS max_adherence
1335
+ ON max_adherence.person_id = adherence.person_id #{site_manager(operator: 'AND', column: 'max_adherence.site_id', location: @location)}
1405
1336
  AND adherence.obs_datetime >= max_adherence.visit_date #{site_manager(operator: 'AND', column: 'adherence.site_id', location: @location)}
1406
1337
  AND adherence.obs_datetime < #{interval_manager(date: 'max_adherence.visit_date', value: 1, interval: 'DAY', operator: '+')}
1338
+ AND max_adherence.person_id NOT IN (#{not_adherent.blank? ? 0 : not_adherent.join(',')})
1407
1339
  INNER JOIN orders
1408
1340
  ON orders.order_id = adherence.order_id
1409
1341
  AND orders.order_type_id = #{drug_order_type.order_type_id}
@@ -1424,6 +1356,43 @@ module MalawiHivProgramReports
1424
1356
  [adherent.uniq, not_adherent.uniq, unknown_adherence]
1425
1357
  end
1426
1358
 
1359
+ def create_tmp_max_adherence(end_date)
1360
+ drop_tmp_max_adherence
1361
+ ActiveRecord::Base.connection.execute <<~SQL
1362
+ CREATE TABLE tmp_max_adherence (
1363
+ person_id INT PRIMARY KEY,
1364
+ visit_date DATE,
1365
+ site_id INT NOT NULL
1366
+ )
1367
+ SQL
1368
+
1369
+ ActiveRecord::Base.connection.execute('CREATE INDEX tma_date ON tmp_max_adherence (visit_date)')
1370
+ ActiveRecord::Base.connection.execute('CREATE INDEX tma_site ON tmp_max_adherence (site_id)')
1371
+
1372
+ ActiveRecord::Base.connection.execute <<~SQL
1373
+ INSERT INTO tmp_max_adherence
1374
+ SELECT obs.person_id, DATE(MAX(obs.obs_datetime)) AS visit_date, obs.site_id
1375
+ FROM obs
1376
+ INNER JOIN orders
1377
+ ON orders.order_id = obs.order_id
1378
+ AND orders.concept_id IN (SELECT `concept_set`.`concept_id` FROM `concept_set` WHERE `concept_set`.`concept_set` = 1085)
1379
+ AND orders.order_type_id = 1
1380
+ AND orders.voided = 0 #{site_manager(operator: 'AND', column: 'orders.site_id', location: @location)}
1381
+ INNER JOIN temp_patient_outcomes
1382
+ ON temp_patient_outcomes.patient_id = obs.person_id
1383
+ AND temp_patient_outcomes.cum_outcome = 'On antiretrovirals' #{site_manager(operator: 'AND', column: 'temp_patient_outcomes.site_id', location: @location)}
1384
+ WHERE obs.concept_id = 6987
1385
+ AND obs.obs_datetime < (DATE(#{end_date}) + INTERVAL 1 DAY)
1386
+ AND (obs.value_numeric IS NOT NULL OR obs.value_text IS NOT NULL)
1387
+ AND obs.voided = 0 #{site_manager(operator: 'AND', column: 'obs.site_id', location: @location)}
1388
+ GROUP BY obs.person_id;
1389
+ SQL
1390
+ end
1391
+
1392
+ def drop_tmp_max_adherence
1393
+ ActiveRecord::Base.connection.execute('DROP TABLE IF EXISTS tmp_max_adherence')
1394
+ end
1395
+
1427
1396
  def adherence_encounter
1428
1397
  @adherence_encounter ||= encounter_type('ART ADHERENCE')
1429
1398
  end
@@ -1514,9 +1483,8 @@ module MalawiHivProgramReports
1514
1483
  SELECT e.*, s.has_se
1515
1484
  FROM temp_earliest_start_date e
1516
1485
  INNER JOIN temp_patient_side_effects s ON s.patient_id = e.patient_id #{site_manager(operator: 'AND', column: 's.site_id', location: @location)}
1517
- INNER JOIN temp_patient_outcomes o ON o.patient_id = e.patient_id #{site_manager(operator: 'AND', column: 'o.site_id', location: @location)}
1518
- WHERE LOWER(o.cum_outcome) = LOWER('On antiretrovirals') #{site_manager(operator: 'AND', column: 'e.site_id', location: @location)}
1519
- AND DATE(e.date_enrolled) <= '#{end_date.to_date}';
1486
+ INNER JOIN temp_patient_outcomes o ON o.patient_id = e.patient_id AND LOWER(o.cum_outcome) = LOWER('On antiretrovirals') #{site_manager(operator: 'AND', column: 'o.site_id', location: @location)}
1487
+ WHERE DATE(e.date_enrolled) <= '#{end_date.to_date}' #{site_manager(operator: 'AND', column: 'e.site_id', location: @location)};
1520
1488
  SQL
1521
1489
 
1522
1490
  (records || []).each do |data|
@@ -1631,10 +1599,10 @@ module MalawiHivProgramReports
1631
1599
  ActiveRecord::Base.connection.select_all <<~SQL
1632
1600
  SELECT t.patient_id
1633
1601
  FROM temp_earliest_start_date t
1634
- INNER JOIN obs ON t.patient_id = obs.person_id #{site_manager(operator: 'AND', column: 'obs.site_id', location: @location)} AND obs.voided = 0
1635
- WHERE t.date_enrolled BETWEEN '#{start_date}' AND '#{end_date}'
1636
- AND ((obs.value_coded = #{concept_id} AND obs.concept_id = #{who_stages_criteria}) OR (obs.concept_id = #{concept_id} AND obs.value_coded = #{yes_concept_id}))
1637
- AND DATE(obs_datetime) <= DATE(date_enrolled) #{site_manager(operator: 'AND', column: 't.site_id', location: @location)}
1602
+ INNER JOIN obs ON t.patient_id = obs.person_id
1603
+ AND ((value_coded = #{concept_id} AND concept_id = #{who_stages_criteria}) OR (concept_id = #{concept_id}) AND value_coded = #{yes_concept_id} )
1604
+ AND voided = 0 AND DATE(obs_datetime) <= DATE(date_enrolled) #{site_manager(operator: 'AND', column: 'obs.site_id', location: @location)}
1605
+ WHERE t.date_enrolled BETWEEN '#{start_date}' AND '#{end_date}' #{site_manager(operator: 'AND', column: 't.site_id', location: @location)}
1638
1606
  GROUP BY patient_id
1639
1607
  SQL
1640
1608
  end
@@ -1650,12 +1618,12 @@ module MalawiHivProgramReports
1650
1618
  ActiveRecord::Base.connection.select_all <<~SQL
1651
1619
  SELECT t.patient_id
1652
1620
  FROM temp_earliest_start_date t
1653
- INNER JOIN obs ON t.patient_id = obs.person_id #{site_manager(operator: 'AND', column: 'obs.site_id', location: @location)}
1654
- WHERE date_enrolled BETWEEN '#{start_date}' AND '#{end_date}'
1655
- AND ( (#{in_manager(column: 'value_coded', values: [eptb_concept_id, pulmonary_tb_concept_id, current_ptb_concept_id])} AND concept_id = #{who_stages_criteria} )
1656
- OR#{' '}
1621
+ INNER JOIN obs ON t.patient_id = obs.person_id AND voided = 0
1622
+ AND DATE(obs_datetime) <= DATE(date_enrolled) #{site_manager(operator: 'AND', column: 'obs.site_id', location: @location)}
1623
+ AND ( (#{in_manager(column: 'value_coded', values: [eptb_concept_id, pulmonary_tb_concept_id, current_ptb_concept_id])} AND concept_id = #{who_stages_criteria} )
1624
+ OR
1657
1625
  (#{in_manager(column: 'concept_id', values: [eptb_concept_id, pulmonary_tb_concept_id, current_ptb_concept_id])} AND value_coded = #{yes_concept_id}))
1658
- AND voided = 0 AND DATE(obs_datetime) <= DATE(date_enrolled) #{site_manager(operator: 'AND', column: 't.site_id', location: @location)}
1626
+ WHERE date_enrolled BETWEEN '#{start_date}' AND '#{end_date}' #{site_manager(operator: 'AND', column: 't.site_id', location: @location)}
1659
1627
  GROUP BY patient_id
1660
1628
  SQL
1661
1629
  end
@@ -1949,30 +1917,25 @@ module MalawiHivProgramReports
1949
1917
  ActiveRecord::Base.connection.execute 'DROP TABLE IF EXISTS temp_pregnant_obs;'
1950
1918
  ActiveRecord::Base.connection.execute <<~SQL
1951
1919
  CREATE TABLE temp_pregnant_obs
1952
- SELECT o.person_id,o.value_coded, o.obs_datetime, o.site_id
1920
+ SELECT o.person_id,o.value_coded, DATE(o.obs_datetime) obs_datetime, o.site_id
1953
1921
  FROM obs o
1954
1922
  WHERE o.concept_id IN (6131,1755,7972,7563)
1955
- AND o.value_coded IN (1065,1755)#{' '}
1923
+ AND o.value_coded IN (1065,1755)
1956
1924
  AND o.voided = 0 #{site_manager(operator: 'AND', column: 'o.location_id', location: @location)}
1957
1925
  AND o.obs_datetime >= '#{start_date}' AND o.obs_datetime < '#{end_date}' + INTERVAL 1 DAY;
1958
1926
  SQL
1959
1927
  ActiveRecord::Base.connection.execute 'CREATE INDEX fre_person ON temp_pregnant_obs(person_id);'
1960
1928
  ActiveRecord::Base.connection.execute 'CREATE INDEX fre_obs_time ON temp_pregnant_obs(obs_datetime);'
1929
+ ActiveRecord::Base.connection.execute 'CREATE INDEX fre_site ON temp_pregnant_obs(site_id);'
1961
1930
  end
1962
1931
 
1963
1932
  def pregnant_females_all_ages(start_date, end_date)
1964
- concept('Yes').concept_id
1965
- concept('IS PATIENT PREGNANT?').concept_id
1966
- concept('PATIENT PREGNANT').concept_id
1967
- concept('PREGNANT AT INITIATION?').concept_id
1968
- concept('Reason for ART eligibility').concept_id
1969
-
1970
1933
  # (patient_id_plus_date_enrolled || []).each do |patient_id, date_enrolled|
1971
1934
  registered = ActiveRecord::Base.connection.select_all <<~SQL
1972
1935
  SELECT tesd.*, ft.value_coded
1973
1936
  FROM temp_earliest_start_date tesd#{' '}
1974
- INNER JOIN temp_pregnant_obs ft ON ft.person_id = tesd.patient_id AND DATE(ft.obs_datetime) = DATE(tesd.earliest_start_date)
1975
- AND tesd.gender = 'F'
1937
+ INNER JOIN temp_pregnant_obs ft ON ft.person_id = tesd.patient_id AND ft.obs_datetime = tesd.earliest_start_date
1938
+ AND tesd.gender = 'F' #{site_manager(operator: 'AND', column: 'ft.site_id', location: @location)}
1976
1939
  WHERE tesd.gender = 'F' and tesd.date_enrolled >= DATE('#{start_date}') AND tesd.date_enrolled <= DATE('#{end_date}') #{site_manager(operator: 'AND', column: 'tesd.site_id', location: @location)}
1977
1940
  GROUP BY tesd.patient_id
1978
1941
  SQL
@@ -1983,8 +1946,8 @@ module MalawiHivProgramReports
1983
1946
  WHERE date_enrolled BETWEEN '#{start_date}' AND '#{end_date}'
1984
1947
  AND gender IN ('F','Female') #{site_manager(operator: 'AND', column: 'site_id', location: @location)}
1985
1948
  AND reason_for_starting_art IN (6131,1755,7972,7563)
1986
- GROUP BY patient_id
1987
1949
  SQL
1950
+
1988
1951
  pregnant_at_initiation_ids = []
1989
1952
  (pregnant_at_initiation || []).each do |patient|
1990
1953
  pregnant_at_initiation_ids << patient['patient_id'].to_i
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MalawiHivProgramReports
4
- VERSION = '1.0.12'
4
+ VERSION = '1.0.13'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: malawi_hiv_program_reports
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.12
4
+ version: 1.0.13
5
5
  platform: ruby
6
6
  authors:
7
7
  - Roy Chanunkha
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-03-20 00:00:00.000000000 Z
11
+ date: 2024-03-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails