malawi_hiv_program_reports 1.0.1 → 1.0.2

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.
Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/app/services/malawi_hiv_program_reports/README.md +16 -0
  3. data/app/services/malawi_hiv_program_reports/adapters/moh/custom.rb +199 -0
  4. data/app/services/malawi_hiv_program_reports/archiving_candidates.rb +130 -0
  5. data/app/services/malawi_hiv_program_reports/arv_refill_periods.rb +311 -0
  6. data/app/services/malawi_hiv_program_reports/clinic/README.md +5 -0
  7. data/app/services/malawi_hiv_program_reports/clinic/appointments_report.rb +317 -0
  8. data/app/services/malawi_hiv_program_reports/clinic/discrepancy_report.rb +42 -0
  9. data/app/services/malawi_hiv_program_reports/clinic/docs/hypertension_report.md +31 -0
  10. data/app/services/malawi_hiv_program_reports/clinic/drug_dispensations.rb +48 -0
  11. data/app/services/malawi_hiv_program_reports/clinic/external_consultation_clients.rb +69 -0
  12. data/app/services/malawi_hiv_program_reports/clinic/hypertension_report.rb +223 -0
  13. data/app/services/malawi_hiv_program_reports/clinic/ipt_coverage.rb +112 -0
  14. data/app/services/malawi_hiv_program_reports/clinic/ipt_report.rb +69 -0
  15. data/app/services/malawi_hiv_program_reports/clinic/lims_results.rb +55 -0
  16. data/app/services/malawi_hiv_program_reports/clinic/outcome_list.rb +127 -0
  17. data/app/services/malawi_hiv_program_reports/clinic/patients_alive_and_on_treatment.rb +57 -0
  18. data/app/services/malawi_hiv_program_reports/clinic/patients_due_for_viral_load.rb +39 -0
  19. data/app/services/malawi_hiv_program_reports/clinic/patients_on_antiretrovirals.rb +44 -0
  20. data/app/services/malawi_hiv_program_reports/clinic/patients_on_dtg.rb +36 -0
  21. data/app/services/malawi_hiv_program_reports/clinic/patients_on_treatment.rb +42 -0
  22. data/app/services/malawi_hiv_program_reports/clinic/patients_with_outdated_demographics.rb +173 -0
  23. data/app/services/malawi_hiv_program_reports/clinic/pregnant_patients.rb +91 -0
  24. data/app/services/malawi_hiv_program_reports/clinic/regimen_dispensation_data.rb +282 -0
  25. data/app/services/malawi_hiv_program_reports/clinic/regimen_switch.rb +456 -0
  26. data/app/services/malawi_hiv_program_reports/clinic/regimens_and_formulations.rb +182 -0
  27. data/app/services/malawi_hiv_program_reports/clinic/regimens_by_weight_and_gender.rb +108 -0
  28. data/app/services/malawi_hiv_program_reports/clinic/retention.rb +246 -0
  29. data/app/services/malawi_hiv_program_reports/clinic/stock_card_report.rb +65 -0
  30. data/app/services/malawi_hiv_program_reports/clinic/tpt_outcome.rb +494 -0
  31. data/app/services/malawi_hiv_program_reports/clinic/tx_rtt.rb +169 -0
  32. data/app/services/malawi_hiv_program_reports/clinic/viral_load.rb +292 -0
  33. data/app/services/malawi_hiv_program_reports/clinic/viral_load_disaggregated.rb +97 -0
  34. data/app/services/malawi_hiv_program_reports/clinic/viral_load_results.rb +175 -0
  35. data/app/services/malawi_hiv_program_reports/clinic/visits_report.rb +113 -0
  36. data/app/services/malawi_hiv_program_reports/clinic/vl_collection.rb +48 -0
  37. data/app/services/malawi_hiv_program_reports/cohort/outcomes.rb +338 -0
  38. data/app/services/malawi_hiv_program_reports/cohort/regimens.rb +69 -0
  39. data/app/services/malawi_hiv_program_reports/cohort/side_effects.rb +141 -0
  40. data/app/services/malawi_hiv_program_reports/cohort/tpt.rb +172 -0
  41. data/app/services/malawi_hiv_program_reports/moh/cohort.rb +278 -0
  42. data/app/services/malawi_hiv_program_reports/moh/cohort_builder.rb +2340 -0
  43. data/app/services/malawi_hiv_program_reports/moh/cohort_disaggregated.rb +608 -0
  44. data/app/services/malawi_hiv_program_reports/moh/cohort_disaggregated_additions.rb +208 -0
  45. data/app/services/malawi_hiv_program_reports/moh/cohort_disaggregated_builder.rb +526 -0
  46. data/app/services/malawi_hiv_program_reports/moh/cohort_struct.rb +219 -0
  47. data/app/services/malawi_hiv_program_reports/moh/cohort_survival_analysis.rb +203 -0
  48. data/app/services/malawi_hiv_program_reports/moh/moh_tpt.rb +223 -0
  49. data/app/services/malawi_hiv_program_reports/moh/tpt_newly_initiated.rb +235 -0
  50. data/app/services/malawi_hiv_program_reports/pepfar/defaulter_list.rb +25 -0
  51. data/app/services/malawi_hiv_program_reports/pepfar/maternal_status.rb +29 -0
  52. data/app/services/malawi_hiv_program_reports/pepfar/patient_start_vl.rb +45 -0
  53. data/app/services/malawi_hiv_program_reports/pepfar/regimen_switch.rb +479 -0
  54. data/app/services/malawi_hiv_program_reports/pepfar/sc_arvdisp.rb +174 -0
  55. data/app/services/malawi_hiv_program_reports/pepfar/sc_curr.rb +98 -0
  56. data/app/services/malawi_hiv_program_reports/pepfar/tb_prev.rb +163 -0
  57. data/app/services/malawi_hiv_program_reports/pepfar/tb_prev2.rb +222 -0
  58. data/app/services/malawi_hiv_program_reports/pepfar/tb_prev3.rb +421 -0
  59. data/app/services/malawi_hiv_program_reports/pepfar/tpt_status.rb +181 -0
  60. data/app/services/malawi_hiv_program_reports/pepfar/tx_ml.rb +181 -0
  61. data/app/services/malawi_hiv_program_reports/pepfar/tx_new.rb +202 -0
  62. data/app/services/malawi_hiv_program_reports/pepfar/tx_rtt.rb +288 -0
  63. data/app/services/malawi_hiv_program_reports/pepfar/tx_tb.rb +283 -0
  64. data/app/services/malawi_hiv_program_reports/pepfar/utils.rb +141 -0
  65. data/app/services/malawi_hiv_program_reports/pepfar/viral_load_coverage.rb +414 -0
  66. data/app/services/malawi_hiv_program_reports/pepfar/viral_load_coverage2.rb +433 -0
  67. data/app/services/malawi_hiv_program_reports/report_map.rb +56 -0
  68. data/app/services/malawi_hiv_program_reports/utils/README.md +8 -0
  69. data/app/services/malawi_hiv_program_reports/utils/common_sql_query_utils.rb +60 -0
  70. data/app/services/malawi_hiv_program_reports/utils/concurrency_utils.rb +53 -0
  71. data/app/services/malawi_hiv_program_reports/utils/docs/common_sql_query_utils.md +53 -0
  72. data/app/services/malawi_hiv_program_reports/utils/model_utils.rb +66 -0
  73. data/app/services/malawi_hiv_program_reports/utils/parameter_utils.rb +32 -0
  74. data/app/services/malawi_hiv_program_reports/utils/time_utils.rb +52 -0
  75. data/lib/malawi_hiv_program_reports/version.rb +1 -1
  76. metadata +74 -1
@@ -0,0 +1,208 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MalawiHivProgramReports
4
+ module Moh
5
+ # This class is used to add additional cohort disaggregated data
6
+ # rubocop:disable Metrics/ClassLength
7
+ class CohortDisaggregatedAdditions
8
+ COHORT_REGIMENS = %w[
9
+ 0P 2P 4PP 4PA 9PP 9PA 11PP 11PA 12PP 12PA 14PP 14PA 15PP 15PA 16P 17PP 17PA
10
+ 4A 5A 6A 7A 8A 9A 10A 11A 12A 13A 14A 15A 16A 17A
11
+ ].freeze
12
+
13
+ def initialize(start_date:, end_date:, gender:, age_group:)
14
+ @start_date = start_date
15
+ @end_date = end_date
16
+ @gender = gender
17
+ @age_group = age_group
18
+ end
19
+
20
+ def screened_for_tb
21
+ return screened_for_tb_female_client('FP') if @gender == 'pregnant'
22
+ return screened_for_tb_female_client('FNP') if @gender == 'fnp'
23
+ return screened_for_tb_female_client('FBf') if @gender == 'breastfeeding'
24
+
25
+ gender = @gender.first.upcase
26
+ results = ActiveRecord::Base.connection.select_all <<~SQL
27
+ SELECT
28
+ e.patient_id, disaggregated_age_group(e.birthdate, DATE('#{@end_date}')) age_group
29
+ FROM temp_earliest_start_date e
30
+ INNER JOIN temp_patient_outcomes USING(patient_id)
31
+ WHERE cum_outcome = 'On antiretrovirals' AND LEFT(gender,1) = '#{gender}'
32
+ GROUP BY e.patient_id HAVING age_group = '#{@age_group}';
33
+ SQL
34
+
35
+ patient_ids = []
36
+ (results || []).each do |r|
37
+ patient_ids << r['patient_id'].to_i
38
+ end
39
+
40
+ tb_screened(patient_ids)
41
+ end
42
+
43
+ def clients_given_ipt
44
+ return female_clients_given_ipt('FP') if @gender == 'pregnant'
45
+ return female_clients_given_ipt('FNP') if @gender == 'fnp'
46
+ return female_clients_given_ipt('FBf') if @gender == 'breastfeeding'
47
+
48
+ gender = @gender.first.upcase
49
+
50
+ patient_ids = []
51
+ results = ActiveRecord::Base.connection.select_all <<~SQL
52
+ SELECT
53
+ e.patient_id, disaggregated_age_group(e.birthdate, DATE('#{@end_date}')) age_group
54
+ FROM temp_earliest_start_date e
55
+ INNER JOIN temp_patient_outcomes USING(patient_id)
56
+ WHERE cum_outcome = 'On antiretrovirals' AND LEFT(gender,1) = '#{gender}'
57
+ GROUP BY e.patient_id HAVING age_group = '#{@age_group}';
58
+ SQL
59
+
60
+ (results || []).each do |row|
61
+ patient_ids << row['patient_id'].to_i
62
+ end
63
+
64
+ return [] if patient_ids.blank?
65
+
66
+ given_ipt(patient_ids)
67
+ end
68
+
69
+ def disaggregated_regimen_distribution
70
+ additional_sql = ''
71
+ additional_for_women_sql = ''
72
+ gender = @gender.first.upcase
73
+
74
+ if @age_group == 'All'
75
+ case @gender.upcase
76
+ when 'FP'
77
+ additional_for_women_sql = 'INNER JOIN temp_disaggregated t ON t.patient_id = e.patient_id'
78
+ additional_for_women_sql += " AND t.maternal_status = 'FP' "
79
+ when 'FBF'
80
+ additional_for_women_sql = 'INNER JOIN temp_disaggregated t ON t.patient_id = e.patient_id'
81
+ additional_for_women_sql += " AND t.maternal_status = 'Fbf' "
82
+ when 'FNP'
83
+ additional_for_women_sql = 'INNER JOIN temp_disaggregated t ON t.patient_id = e.patient_id'
84
+ additional_for_women_sql += " AND t.maternal_status = 'FNP' "
85
+ end
86
+ else
87
+ additional_sql = "HAVING age_group = '#{@age_group}'"
88
+ end
89
+
90
+ patients = ActiveRecord::Base.connection.select_all <<~SQL
91
+ SELECT
92
+ e.patient_id, disaggregated_age_group(e.birthdate, DATE("#{@end_date.to_date}")) age_group
93
+ FROM temp_earliest_start_date e
94
+ INNER JOIN temp_patient_outcomes o ON o.patient_id = e.patient_id
95
+ #{additional_for_women_sql}
96
+ WHERE LEFT(gender,1) = '#{gender}' AND o.cum_outcome = 'On antiretrovirals'
97
+ AND DATE(date_enrolled) <= '#{@end_date.to_date}'
98
+ GROUP BY e.patient_id #{additional_sql};
99
+ SQL
100
+
101
+ return {} if patients.blank?
102
+
103
+ patient_ids = patients.map { |p| p['patient_id'].to_i }
104
+ data = {}
105
+
106
+ patient_ids.each do |patient_id|
107
+ regimen_data = ActiveRecord::Base.connection.select_one <<~SQL
108
+ SELECT patient_current_regimen(#{patient_id}, DATE('#{@end_date.to_date}')) regimen;
109
+ SQL
110
+
111
+ regimen = (COHORT_REGIMENS.include? regimen_data['regimen']) ? regimen_data['regimen'] : 'N/A'
112
+ data[regimen] = [] if data[regimen].blank?
113
+ data[regimen] << patient_id
114
+ end
115
+
116
+ data
117
+ end
118
+
119
+ private
120
+
121
+ def given_ipt(patient_ids)
122
+ return [] if patient_ids.blank?
123
+
124
+ isoniazid_concept_id = ::ConceptName.find_by(name: 'Isoniazid').concept_id
125
+ isoniazid_rifapentine_concept_id = ::ConceptName.find_by(name: 'Isoniazid/Rifapentine').concept_id
126
+ pyridoxine_concept_id = ::ConceptName.find_by(name: 'Pyridoxine').concept_id
127
+
128
+ results = ActiveRecord::Base.connection.select_all(
129
+ "SELECT ods.patient_id FROM orders ods
130
+ INNER JOIN drug_order dos ON ods.order_id = dos.order_id AND ods.voided = 0
131
+ WHERE ods.concept_id IN (#{isoniazid_concept_id}, #{pyridoxine_concept_id}, #{isoniazid_rifapentine_concept_id})
132
+ AND dos.quantity IS NOT NULL
133
+ AND ods.patient_id in (#{patient_ids.join(',')})
134
+ AND ods.start_date BETWEEN '#{@start_date.to_date.strftime('%Y-%m-%d 00:00:00')}'
135
+ AND '#{@end_date.to_date.strftime('%Y-%m-%d 23:59:59')}'
136
+ AND DATE(ods.start_date) = (SELECT MAX(DATE(o.start_date)) FROM orders o
137
+ INNER JOIN drug_order d ON o.order_id = d.order_id AND o.voided = 0
138
+ WHERE o.concept_id IN (#{isoniazid_concept_id}, #{pyridoxine_concept_id}, #{isoniazid_rifapentine_concept_id})
139
+ AND o.patient_id = ods.patient_id
140
+ AND d.quantity IS NOT NULL
141
+ AND o.start_date BETWEEN '#{@start_date.to_date.strftime('%Y-%m-%d 00:00:00')}'
142
+ AND '#{@end_date.to_date.strftime('%Y-%m-%d 23:59:59')}')
143
+ GROUP BY ods.patient_id;"
144
+ )
145
+
146
+ results_patients = []
147
+
148
+ (results || []).each do |row|
149
+ results_patients << row['patient_id'].to_i
150
+ end
151
+
152
+ results_patients
153
+ end
154
+
155
+ def tb_screened(patient_ids)
156
+ return [] if patient_ids.blank?
157
+
158
+ results = ActiveRecord::Base.connection.select_all <<~SQL
159
+ SELECT e.*, tb_status FROM temp_earliest_start_date e
160
+ INNER JOIN temp_patient_tb_status s ON s.patient_id = e.patient_id
161
+ INNER JOIN temp_patient_outcomes o ON o.patient_id = e.patient_id
162
+ WHERE o.cum_outcome = 'On antiretrovirals' AND e.patient_id IN(#{patient_ids.join(',')})
163
+ AND DATE(e.date_enrolled) <= '#{@end_date.to_date}';
164
+ SQL
165
+
166
+ patient_ids = []
167
+ (results || []).each do |r|
168
+ patient_ids << r['patient_id'].to_i unless r['tb_status'].blank?
169
+ end
170
+
171
+ patient_ids
172
+ end
173
+
174
+ def screened_for_tb_female_client(group)
175
+ results = ActiveRecord::Base.connection.select_all <<~SQL
176
+ SELECT f.patient_id FROM temp_disaggregated f
177
+ INNER JOIN temp_patient_outcomes o ON o.patient_id = f.patient_id
178
+ WHERE maternal_status = "#{group}"
179
+ AND o.cum_outcome = 'On antiretrovirals' GROUP BY f.patient_id;
180
+ SQL
181
+
182
+ patient_ids = []
183
+ (results || []).each do |r|
184
+ patient_ids << r['patient_id'].to_i
185
+ end
186
+
187
+ tb_screened(patient_ids)
188
+ end
189
+
190
+ def female_clients_given_ipt(group)
191
+ results = ActiveRecord::Base.connection.select_all <<~SQL
192
+ SELECT f.patient_id FROM temp_disaggregated f
193
+ INNER JOIN temp_patient_outcomes o ON o.patient_id = f.patient_id
194
+ WHERE maternal_status = "#{group}"
195
+ AND o.cum_outcome = 'On antiretrovirals' GROUP BY f.patient_id;
196
+ SQL
197
+
198
+ patient_ids = []
199
+ (results || []).each do |r|
200
+ patient_ids << r['patient_id'].to_i
201
+ end
202
+
203
+ given_ipt(patient_ids)
204
+ end
205
+ end
206
+ # rubocop:enable Metrics/ClassLength
207
+ end
208
+ end