malawi_hiv_program_reports 1.0.12 → 1.0.13

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