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.
- checksums.yaml +4 -4
- data/app/services/malawi_hiv_program_reports/README.md +16 -0
- data/app/services/malawi_hiv_program_reports/adapters/moh/custom.rb +199 -0
- data/app/services/malawi_hiv_program_reports/archiving_candidates.rb +130 -0
- data/app/services/malawi_hiv_program_reports/arv_refill_periods.rb +311 -0
- data/app/services/malawi_hiv_program_reports/clinic/README.md +5 -0
- data/app/services/malawi_hiv_program_reports/clinic/appointments_report.rb +317 -0
- data/app/services/malawi_hiv_program_reports/clinic/discrepancy_report.rb +42 -0
- data/app/services/malawi_hiv_program_reports/clinic/docs/hypertension_report.md +31 -0
- data/app/services/malawi_hiv_program_reports/clinic/drug_dispensations.rb +48 -0
- data/app/services/malawi_hiv_program_reports/clinic/external_consultation_clients.rb +69 -0
- data/app/services/malawi_hiv_program_reports/clinic/hypertension_report.rb +223 -0
- data/app/services/malawi_hiv_program_reports/clinic/ipt_coverage.rb +112 -0
- data/app/services/malawi_hiv_program_reports/clinic/ipt_report.rb +69 -0
- data/app/services/malawi_hiv_program_reports/clinic/lims_results.rb +55 -0
- data/app/services/malawi_hiv_program_reports/clinic/outcome_list.rb +127 -0
- data/app/services/malawi_hiv_program_reports/clinic/patients_alive_and_on_treatment.rb +57 -0
- data/app/services/malawi_hiv_program_reports/clinic/patients_due_for_viral_load.rb +39 -0
- data/app/services/malawi_hiv_program_reports/clinic/patients_on_antiretrovirals.rb +44 -0
- data/app/services/malawi_hiv_program_reports/clinic/patients_on_dtg.rb +36 -0
- data/app/services/malawi_hiv_program_reports/clinic/patients_on_treatment.rb +42 -0
- data/app/services/malawi_hiv_program_reports/clinic/patients_with_outdated_demographics.rb +173 -0
- data/app/services/malawi_hiv_program_reports/clinic/pregnant_patients.rb +91 -0
- data/app/services/malawi_hiv_program_reports/clinic/regimen_dispensation_data.rb +282 -0
- data/app/services/malawi_hiv_program_reports/clinic/regimen_switch.rb +456 -0
- data/app/services/malawi_hiv_program_reports/clinic/regimens_and_formulations.rb +182 -0
- data/app/services/malawi_hiv_program_reports/clinic/regimens_by_weight_and_gender.rb +108 -0
- data/app/services/malawi_hiv_program_reports/clinic/retention.rb +246 -0
- data/app/services/malawi_hiv_program_reports/clinic/stock_card_report.rb +65 -0
- data/app/services/malawi_hiv_program_reports/clinic/tpt_outcome.rb +494 -0
- data/app/services/malawi_hiv_program_reports/clinic/tx_rtt.rb +169 -0
- data/app/services/malawi_hiv_program_reports/clinic/viral_load.rb +292 -0
- data/app/services/malawi_hiv_program_reports/clinic/viral_load_disaggregated.rb +97 -0
- data/app/services/malawi_hiv_program_reports/clinic/viral_load_results.rb +175 -0
- data/app/services/malawi_hiv_program_reports/clinic/visits_report.rb +113 -0
- data/app/services/malawi_hiv_program_reports/clinic/vl_collection.rb +48 -0
- data/app/services/malawi_hiv_program_reports/cohort/outcomes.rb +338 -0
- data/app/services/malawi_hiv_program_reports/cohort/regimens.rb +69 -0
- data/app/services/malawi_hiv_program_reports/cohort/side_effects.rb +141 -0
- data/app/services/malawi_hiv_program_reports/cohort/tpt.rb +172 -0
- data/app/services/malawi_hiv_program_reports/moh/cohort.rb +278 -0
- data/app/services/malawi_hiv_program_reports/moh/cohort_builder.rb +2340 -0
- data/app/services/malawi_hiv_program_reports/moh/cohort_disaggregated.rb +608 -0
- data/app/services/malawi_hiv_program_reports/moh/cohort_disaggregated_additions.rb +208 -0
- data/app/services/malawi_hiv_program_reports/moh/cohort_disaggregated_builder.rb +526 -0
- data/app/services/malawi_hiv_program_reports/moh/cohort_struct.rb +219 -0
- data/app/services/malawi_hiv_program_reports/moh/cohort_survival_analysis.rb +203 -0
- data/app/services/malawi_hiv_program_reports/moh/moh_tpt.rb +223 -0
- data/app/services/malawi_hiv_program_reports/moh/tpt_newly_initiated.rb +235 -0
- data/app/services/malawi_hiv_program_reports/pepfar/defaulter_list.rb +25 -0
- data/app/services/malawi_hiv_program_reports/pepfar/maternal_status.rb +29 -0
- data/app/services/malawi_hiv_program_reports/pepfar/patient_start_vl.rb +45 -0
- data/app/services/malawi_hiv_program_reports/pepfar/regimen_switch.rb +479 -0
- data/app/services/malawi_hiv_program_reports/pepfar/sc_arvdisp.rb +174 -0
- data/app/services/malawi_hiv_program_reports/pepfar/sc_curr.rb +98 -0
- data/app/services/malawi_hiv_program_reports/pepfar/tb_prev.rb +163 -0
- data/app/services/malawi_hiv_program_reports/pepfar/tb_prev2.rb +222 -0
- data/app/services/malawi_hiv_program_reports/pepfar/tb_prev3.rb +421 -0
- data/app/services/malawi_hiv_program_reports/pepfar/tpt_status.rb +181 -0
- data/app/services/malawi_hiv_program_reports/pepfar/tx_ml.rb +181 -0
- data/app/services/malawi_hiv_program_reports/pepfar/tx_new.rb +202 -0
- data/app/services/malawi_hiv_program_reports/pepfar/tx_rtt.rb +288 -0
- data/app/services/malawi_hiv_program_reports/pepfar/tx_tb.rb +283 -0
- data/app/services/malawi_hiv_program_reports/pepfar/utils.rb +141 -0
- data/app/services/malawi_hiv_program_reports/pepfar/viral_load_coverage.rb +414 -0
- data/app/services/malawi_hiv_program_reports/pepfar/viral_load_coverage2.rb +433 -0
- data/app/services/malawi_hiv_program_reports/report_map.rb +56 -0
- data/app/services/malawi_hiv_program_reports/utils/README.md +8 -0
- data/app/services/malawi_hiv_program_reports/utils/common_sql_query_utils.rb +60 -0
- data/app/services/malawi_hiv_program_reports/utils/concurrency_utils.rb +53 -0
- data/app/services/malawi_hiv_program_reports/utils/docs/common_sql_query_utils.md +53 -0
- data/app/services/malawi_hiv_program_reports/utils/model_utils.rb +66 -0
- data/app/services/malawi_hiv_program_reports/utils/parameter_utils.rb +32 -0
- data/app/services/malawi_hiv_program_reports/utils/time_utils.rb +52 -0
- data/lib/malawi_hiv_program_reports/version.rb +1 -1
- metadata +74 -1
|
@@ -0,0 +1,526 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module MalawiHivProgramReports
|
|
4
|
+
module Moh
|
|
5
|
+
# This class is used to add additional cohort disaggregated data
|
|
6
|
+
class CohortDisaggregatedBuilder < CohortBuilder
|
|
7
|
+
def initialize(outcomes_definition: 'moh', **kwargs)
|
|
8
|
+
unless %w[moh pepfar].include?(outcomes_definition.downcase)
|
|
9
|
+
raise ::ArgumentError, "Invalid outcomes_definition `#{outcomes_definition}` expected moh or pepfar"
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
@location = kwargs[:location]
|
|
13
|
+
@adapter = ActiveRecord::Base.connection.adapter_name.downcase
|
|
14
|
+
@outcomes_definition = outcomes_definition
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def build(_cohort_struct, start_date, end_date)
|
|
18
|
+
build_disaggregated_report(cohort(nil, start_date, end_date), start_date, end_date)
|
|
19
|
+
rescue StandardError => e
|
|
20
|
+
Rails.logger.error "Error Message #{e.message}"
|
|
21
|
+
raise e
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def cohort(_cohort_struct, start_date, end_date)
|
|
25
|
+
time_started = Time.now.strftime('%Y-%m-%d %H:%M:%S')
|
|
26
|
+
|
|
27
|
+
@cohort_struct = cohort_struct = CohortStruct.new
|
|
28
|
+
|
|
29
|
+
#=end
|
|
30
|
+
# Get earliest date enrolled
|
|
31
|
+
@cohort_cum_start_date = cum_start_date = get_cum_start_date
|
|
32
|
+
|
|
33
|
+
# Total registered
|
|
34
|
+
cohort_struct.total_registered = total_registered(start_date, end_date)
|
|
35
|
+
cohort_struct.cum_total_registered = total_registered(cum_start_date, end_date)
|
|
36
|
+
|
|
37
|
+
# Patients initiated on ART first time
|
|
38
|
+
cohort_struct.initiated_on_art_first_time = initiated_on_art_first_time(start_date, end_date)
|
|
39
|
+
cohort_struct.cum_initiated_on_art_first_time = initiated_on_art_first_time(cum_start_date, end_date)
|
|
40
|
+
|
|
41
|
+
# Patients re-initiated on ART
|
|
42
|
+
cohort_struct.re_initiated_on_art = re_initiated_on_art(start_date, end_date)
|
|
43
|
+
cohort_struct.cum_re_initiated_on_art = re_initiated_on_art(cum_start_date, end_date)
|
|
44
|
+
|
|
45
|
+
# Patients transferred in on ART
|
|
46
|
+
cohort_struct.transfer_in = transfer_in(start_date, end_date, cohort_struct.re_initiated_on_art)
|
|
47
|
+
cohort_struct.cum_transfer_in = transfer_in(cum_start_date, end_date, cohort_struct.cum_re_initiated_on_art)
|
|
48
|
+
|
|
49
|
+
# All males
|
|
50
|
+
cohort_struct.all_males = males(start_date, end_date)
|
|
51
|
+
cohort_struct.cum_all_males = males(cum_start_date, end_date)
|
|
52
|
+
|
|
53
|
+
# Unknown age
|
|
54
|
+
cohort_struct.unknown_age = unknown_age(start_date, end_date)
|
|
55
|
+
cohort_struct.cum_unknown_age = unknown_age(cum_start_date, end_date)
|
|
56
|
+
|
|
57
|
+
# No TB
|
|
58
|
+
# total_registered - (current_episode - tb_within_the_last_two_years)
|
|
59
|
+
cohort_struct.no_tb = no_tb(cohort_struct.total_registered, cohort_struct.tb_within_the_last_two_years,
|
|
60
|
+
cohort_struct.current_episode_of_tb)
|
|
61
|
+
cohort_struct.cum_no_tb = cum_no_tb(cohort_struct.cum_total_registered,
|
|
62
|
+
cohort_struct.cum_tb_within_the_last_two_years, cohort_struct.cum_current_episode_of_tb)
|
|
63
|
+
|
|
64
|
+
# Total Alive and On ART
|
|
65
|
+
# Unique PatientProgram entries at the current location for those patients with at least one state
|
|
66
|
+
# ON ARVs and earliest start date of the 'ON ARVs' state less than or equal to end date of quarter
|
|
67
|
+
# and latest state is ON ARVs (Excluding defaulters)
|
|
68
|
+
cohort_struct.total_alive_and_on_art = get_outcome('On antiretrovirals')
|
|
69
|
+
|
|
70
|
+
# Pregnant women
|
|
71
|
+
#
|
|
72
|
+
# Unique PatientProgram entries at the current location for those patients with at least one state ON ARVs
|
|
73
|
+
# and earliest start date of the 'ON ARVs' state within the quarter
|
|
74
|
+
# and having a REASON FOR ELIGIBILITY observation with an answer as PATIENT PREGNANT
|
|
75
|
+
cohort_struct.total_pregnant_women = total_pregnant_women(cohort_struct.total_alive_and_on_art, cum_start_date,
|
|
76
|
+
end_date)
|
|
77
|
+
|
|
78
|
+
# Breastfeeding mothers
|
|
79
|
+
#
|
|
80
|
+
# Unique PatientProgram entries at the current location for those patients with at least one state
|
|
81
|
+
# ON ARVs and earliest start date of the 'ON ARVs' state within the quarter
|
|
82
|
+
# and having a REASON FOR ELIGIBILITY observation with an answer as BREASTFEEDING
|
|
83
|
+
cohort_struct.total_breastfeeding_women = total_breastfeeding_women(cohort_struct.total_alive_and_on_art, cohort_struct.total_pregnant_women,
|
|
84
|
+
cum_start_date, end_date)
|
|
85
|
+
|
|
86
|
+
# Non-pregnant females (all ages)
|
|
87
|
+
|
|
88
|
+
# Unique PatientProgram entries at the current location for those patients with at least one state ON ARVs
|
|
89
|
+
# and earliest start date of the 'ON ARVs' state within the quarter and having gender of
|
|
90
|
+
# related PERSON entry as F for female and no entries of 'IS PATIENT PREGNANT?' observation answered 'YES'
|
|
91
|
+
# in related HIV CLINIC CONSULTATION encounters not within 28 days from earliest registration date
|
|
92
|
+
pregnant_females = []
|
|
93
|
+
(cohort_struct.total_pregnant_women || []).each do |patient|
|
|
94
|
+
pregnant_females << patient['person_id'].to_i
|
|
95
|
+
end
|
|
96
|
+
cohort_struct.non_pregnant_females = non_pregnant_females(start_date, end_date, pregnant_females)
|
|
97
|
+
cohort_struct.cum_non_pregnant_females = non_pregnant_females(cum_start_date, end_date, pregnant_females)
|
|
98
|
+
end_time = Time.now.strftime('%Y-%m-%d %H:%M:%S')
|
|
99
|
+
|
|
100
|
+
puts "Started at: #{time_started}. Finished at: #{end_time}. Total time in minutes: #{((end_time.to_time - time_started.to_time) / 60).round(2)} minutes."
|
|
101
|
+
Rails.logger.info "Started at: #{time_started}. Finished at: #{end_time}. Total time in minutes: #{((end_time.to_time - time_started.to_time) / 60).round(2)} minutes."
|
|
102
|
+
cohort_struct
|
|
103
|
+
rescue StandardError => e
|
|
104
|
+
Rails.logger.error "Error Message #{e}"
|
|
105
|
+
raise e
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def build_disaggregated_report(cohort, start_date, end_date)
|
|
109
|
+
@age_groups = ['0-5 months', '6-11 months', '12-23 months', '2-4 years',
|
|
110
|
+
'5-9 years', '10-14 years', '15-17 years', '18-19 years',
|
|
111
|
+
'20-24 years', '25-29 years', '30-34 years', '35-39 years',
|
|
112
|
+
'40-44 years', '45-49 years', '50+ years', 'All']
|
|
113
|
+
|
|
114
|
+
report = {}
|
|
115
|
+
counter = 1
|
|
116
|
+
|
|
117
|
+
%w[Male Female].each do |gender|
|
|
118
|
+
@age_groups.each do |ag|
|
|
119
|
+
next if /all/i.match?(ag)
|
|
120
|
+
|
|
121
|
+
report[counter] = {} if report[counter].blank?
|
|
122
|
+
report[counter][gender] = {} if report[counter][gender].blank?
|
|
123
|
+
report[counter][gender][ag] = get_data(cohort, start_date, end_date, gender, ag)
|
|
124
|
+
counter += 1
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
%w[M FP FNP FBf].each do |gender|
|
|
129
|
+
@age_groups.each do |ag|
|
|
130
|
+
next unless /all/i.match?(ag)
|
|
131
|
+
|
|
132
|
+
report[counter] = {} if report[counter].blank?
|
|
133
|
+
report[counter][gender] = {} if report[counter][gender].blank?
|
|
134
|
+
report[counter][gender][ag] = get_data(cohort, start_date, end_date, gender, ag)
|
|
135
|
+
counter += 1
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
report
|
|
140
|
+
rescue StandardError => e
|
|
141
|
+
Rails.logger.error "Error Message #{e}"
|
|
142
|
+
raise e
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def get_data(cohort, start_date, end_date, gender, age_group)
|
|
146
|
+
@cohort = cohort
|
|
147
|
+
|
|
148
|
+
if %w[Male Female].include?(gender)
|
|
149
|
+
case age_group
|
|
150
|
+
when '50+ years'
|
|
151
|
+
yrs_months = 'year'
|
|
152
|
+
age_to = 1000
|
|
153
|
+
age_from = 50
|
|
154
|
+
when /years/i
|
|
155
|
+
age_from, age_to = age_group.sub(' years', '').split('-')
|
|
156
|
+
yrs_months = 'year'
|
|
157
|
+
when /months/i
|
|
158
|
+
age_from, age_to = age_group.sub(' months', '').split('-')
|
|
159
|
+
yrs_months = 'month'
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
g = gender.first
|
|
163
|
+
|
|
164
|
+
started_on_art = get_started_on_art(yrs_months, age_from, age_to, g, start_date, end_date)
|
|
165
|
+
alive_on_art = get_alive_on_art(yrs_months, age_from, age_to, g, @cohort_cum_start_date, end_date)
|
|
166
|
+
started_on_ipt = get_started_on_ipt(yrs_months, age_from, age_to, g, @cohort_cum_start_date, end_date)
|
|
167
|
+
screened_for_tb = get_screened_for_tb(yrs_months, age_from, age_to, g, @cohort_cum_start_date, end_date)
|
|
168
|
+
|
|
169
|
+
return [started_on_art&.length || 0,
|
|
170
|
+
alive_on_art&.length || 0,
|
|
171
|
+
started_on_ipt&.length || 0,
|
|
172
|
+
screened_for_tb&.length || 0]
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
if gender == 'M'
|
|
176
|
+
age_from = 0
|
|
177
|
+
age_to = 1000
|
|
178
|
+
yrs_months = 'year'
|
|
179
|
+
started_on_art = get_started_on_art(yrs_months, age_from, age_to, gender, start_date, end_date)
|
|
180
|
+
alive_on_art = get_alive_on_art(yrs_months, age_from, age_to, gender, @cohort_cum_start_date, end_date)
|
|
181
|
+
started_on_ipt = get_started_on_ipt(yrs_months, age_from, age_to, gender, @cohort_cum_start_date, end_date)
|
|
182
|
+
screened_for_tb = get_screened_for_tb(yrs_months, age_from, age_to, gender, @cohort_cum_start_date, end_date)
|
|
183
|
+
|
|
184
|
+
return [started_on_art&.length || 0,
|
|
185
|
+
alive_on_art&.length || 0,
|
|
186
|
+
started_on_ipt&.length || 0,
|
|
187
|
+
screened_for_tb&.length || 0]
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
if gender == 'FP'
|
|
191
|
+
a, b, c, d = get_fp(start_date, end_date)
|
|
192
|
+
return [a.length, b.length, c.length, d.length]
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
if gender == 'FNP'
|
|
196
|
+
fnp_a, fnp_b, fnp_c, fnp_d = get_fnp(start_date, end_date)
|
|
197
|
+
return [fnp_a.length, fnp_b.length, fnp_c.length, fnp_d.length]
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
if gender == 'FBf'
|
|
201
|
+
a, b, c, d = get_fbf(start_date, end_date)
|
|
202
|
+
return [a.length, b.length, c.length, d.length]
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
[0, 0, 0, 0]
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
def get_fnp(start_date, end_date)
|
|
209
|
+
age_from = 0
|
|
210
|
+
age_to = 1000
|
|
211
|
+
yrs_months = 'year'
|
|
212
|
+
gender = 'F'
|
|
213
|
+
|
|
214
|
+
females_pregnant = []
|
|
215
|
+
cum_females_pregnant = []
|
|
216
|
+
breast_feeding_women = []
|
|
217
|
+
cum_breast_feeding_women = []
|
|
218
|
+
|
|
219
|
+
started_on_art = []
|
|
220
|
+
alive_on_art = []
|
|
221
|
+
started_on_ipt = []
|
|
222
|
+
screened_for_tb = []
|
|
223
|
+
|
|
224
|
+
###############################################################
|
|
225
|
+
(@cohort.total_breastfeeding_women || []).each do |p|
|
|
226
|
+
date_enrolled_str = ActiveRecord::Base.connection.select_one(
|
|
227
|
+
"SELECT date_enrolled FROM temp_earliest_start_date e
|
|
228
|
+
WHERE patient_id = #{p['person_id']} #{site_manager(operator: 'AND', column: 'e.site_id',
|
|
229
|
+
location: @location)}"
|
|
230
|
+
)
|
|
231
|
+
|
|
232
|
+
date_enrolled = date_enrolled_str['date_enrolled'].to_date
|
|
233
|
+
if (date_enrolled >= start_date.to_date) && (end_date.to_date <= end_date.to_date)
|
|
234
|
+
breast_feeding_women << p['person_id'].to_i
|
|
235
|
+
breast_feeding_women = breast_feeding_women.uniq
|
|
236
|
+
else
|
|
237
|
+
cum_breast_feeding_women << p['person_id'].to_i
|
|
238
|
+
cum_breast_feeding_women = cum_breast_feeding_women.uniq
|
|
239
|
+
end
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
cum_pregnant_women = @cohort.total_pregnant_women
|
|
243
|
+
(cum_pregnant_women || []).each do |p|
|
|
244
|
+
next if breast_feeding_women.include?(p['person_id'].to_i)
|
|
245
|
+
|
|
246
|
+
date_enrolled_str = ActiveRecord::Base.connection.select_one(
|
|
247
|
+
"SELECT date_enrolled FROM temp_earliest_start_date e
|
|
248
|
+
WHERE patient_id = #{p['person_id'].to_i} #{site_manager(operator: 'AND', column: 'e.site_id',
|
|
249
|
+
location: @location)}"
|
|
250
|
+
)
|
|
251
|
+
|
|
252
|
+
date_enrolled = date_enrolled_str['date_enrolled'].to_date
|
|
253
|
+
if (date_enrolled >= start_date.to_date) && (end_date.to_date <= end_date.to_date)
|
|
254
|
+
females_pregnant << p['person_id'].to_i
|
|
255
|
+
females_pregnant = females_pregnant.uniq
|
|
256
|
+
else
|
|
257
|
+
cum_females_pregnant << p['person_id'].to_i
|
|
258
|
+
cum_females_pregnant = cum_females_pregnant.uniq
|
|
259
|
+
end
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
cum_females_pregnant = (cum_females_pregnant + females_pregnant)&.uniq || []
|
|
263
|
+
cum_breast_feeding_women += breast_feeding_women
|
|
264
|
+
#####################################################################
|
|
265
|
+
|
|
266
|
+
(get_started_on_art(yrs_months, age_from, age_to, gender, start_date, end_date) || []).each do |fnp|
|
|
267
|
+
next if females_pregnant.include?(fnp['patient_id'].to_i)
|
|
268
|
+
next if breast_feeding_women.include?(fnp['patient_id'].to_i)
|
|
269
|
+
|
|
270
|
+
started_on_art << { patient_id: fnp['patient_id'].to_i, date_enrolled: fnp['date_enrolled'].to_date }
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
(get_alive_on_art(yrs_months, age_from, age_to, gender, @cohort_cum_start_date, end_date) || []).each do |fnp|
|
|
274
|
+
next if cum_females_pregnant.include?(fnp['patient_id'].to_i)
|
|
275
|
+
next if cum_breast_feeding_women.include?(fnp['patient_id'].to_i)
|
|
276
|
+
|
|
277
|
+
alive_on_art << { patient_id: fnp['patient_id'].to_i }
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
(get_started_on_ipt(yrs_months, age_from, age_to, gender, @cohort_cum_start_date, end_date) || []).each do |fnp|
|
|
281
|
+
next if cum_females_pregnant.include?(fnp['patient_id'].to_i)
|
|
282
|
+
next if cum_breast_feeding_women.include?(fnp['patient_id'].to_i)
|
|
283
|
+
|
|
284
|
+
started_on_ipt << { patient_id: fnp['patient_id'].to_i }
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
(get_screened_for_tb(yrs_months, age_from, age_to, gender, @cohort_cum_start_date,
|
|
288
|
+
end_date) || []).each do |fnp|
|
|
289
|
+
next if cum_females_pregnant.include?(fnp['patient_id'].to_i)
|
|
290
|
+
next if cum_breast_feeding_women.include?(fnp['patient_id'].to_i)
|
|
291
|
+
|
|
292
|
+
screened_for_tb << { patient_id: fnp['patient_id'].to_i }
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
[started_on_art, alive_on_art, started_on_ipt, screened_for_tb]
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
def get_screened_for_tb(yrs_months, age_from, age_to, gender, start_date, end_date)
|
|
299
|
+
alive_on_art_patient_ids = []
|
|
300
|
+
start_date = @cohort_cum_start_date
|
|
301
|
+
|
|
302
|
+
(@cohort.total_alive_and_on_art || []).each do |data|
|
|
303
|
+
alive_on_art_patient_ids << data['patient_id'].to_i
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
return [] if alive_on_art_patient_ids.blank?
|
|
307
|
+
|
|
308
|
+
tb_treatment = concept_name('TB treatment').concept_id
|
|
309
|
+
tb_status_id = concept_name('TB status').concept_id
|
|
310
|
+
clinical_consultation = encounter_type('HIV CLINIC CONSULTATION').id
|
|
311
|
+
|
|
312
|
+
ActiveRecord::Base.connection.select_all <<~SQL
|
|
313
|
+
SELECT t1.patient_id
|
|
314
|
+
FROM obs t3
|
|
315
|
+
INNER JOIN temp_earliest_start_date t1 ON t1.patient_id = t3.person_id #{site_manager(operator: 'AND', column: 't1.site_id', location: @location)} AND t1.patient_id IN(#{alive_on_art_patient_ids.join(',')})
|
|
316
|
+
WHERE t3.concept_id IN(#{tb_treatment},#{tb_status_id}) AND t3.voided = 0
|
|
317
|
+
AND t3.obs_datetime BETWEEN '#{start_date.to_date.strftime('%Y-%m-%d 00:00:00')}' AND '#{end_date.to_date.strftime('%Y-%m-%d 23:59:59')}'
|
|
318
|
+
AND gender = '#{gender.first}' AND t1.date_enrolled BETWEEN '#{start_date.to_date}' AND '#{end_date.to_date}' #{site_manager(operator: 'AND', column: 't3.site_id', location: @location)}
|
|
319
|
+
AND #{timestampdiff_manager(date1: 'birthdate', date2: "DATE('#{end_date.to_date}')", interval: yrs_months)} BETWEEN #{age_from} AND #{age_to}
|
|
320
|
+
AND t3.obs_datetime = (
|
|
321
|
+
SELECT MAX(obs_datetime)
|
|
322
|
+
FROM obs t4
|
|
323
|
+
INNER JOIN encounter e ON e.encounter_id = t4.encounter_id AND e.encounter_type = #{clinical_consultation} AND e.voided = 0 #{site_manager(operator: 'AND', column: 'e.site_id', location: @location)}
|
|
324
|
+
WHERE t3.person_id = t4.person_id
|
|
325
|
+
AND t4.voided = 0 #{site_manager(operator: 'AND', column: 't4.site_id', location: @location)}
|
|
326
|
+
AND t4.obs_datetime BETWEEN '#{start_date.to_date.strftime('%Y-%m-%d 00:00:00')}' AND '#{end_date.to_date.strftime('%Y-%m-%d 23:59:59')}'
|
|
327
|
+
)
|
|
328
|
+
GROUP BY t3.person_id
|
|
329
|
+
SQL
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
def get_started_on_ipt(yrs_months, age_from, age_to, gender, _start_date, end_date)
|
|
333
|
+
data = ActiveRecord::Base.connection.select_all <<~SQL
|
|
334
|
+
SELECT patient_id
|
|
335
|
+
FROM temp_earliest_start_date
|
|
336
|
+
WHERE gender = '#{gender}' AND earliest_start_date <= '#{end_date.to_date}'
|
|
337
|
+
AND #{timestampdiff_manager(date1: 'birthdate', date2: "DATE('#{end_date.to_date}')", interval: yrs_months)}
|
|
338
|
+
BETWEEN #{age_from} AND #{age_to} #{site_manager(operator: 'AND', column: 'site_id', location: @location)}
|
|
339
|
+
SQL
|
|
340
|
+
|
|
341
|
+
return [] if data.blank?
|
|
342
|
+
|
|
343
|
+
patient_ids = []
|
|
344
|
+
|
|
345
|
+
data.each do |d|
|
|
346
|
+
patient_ids << d['patient_id'].to_i
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
amount_dispensed = concept_name('Amount dispensed').concept_id
|
|
350
|
+
ipt_drug_ids = ::Drug.where(concept_id: concept_name('Isoniazid').concept_id).map(&:drug_id)
|
|
351
|
+
|
|
352
|
+
ActiveRecord::Base.connection.select_all <<~SQL
|
|
353
|
+
SELECT obs.person_id patient_id
|
|
354
|
+
FROM obs
|
|
355
|
+
WHERE concept_id = #{amount_dispensed} AND obs.voided = 0 #{site_manager(operator: 'AND', column: 'obs.site_id', location: @location)}
|
|
356
|
+
AND obs.obs_datetime <= '#{end_date.to_date.strftime('%Y-%m-%d 23:59:59')}'
|
|
357
|
+
AND value_drug IN(#{ipt_drug_ids.join(',')}) AND obs.person_id IN(#{patient_ids.join(',')})
|
|
358
|
+
SQL
|
|
359
|
+
end
|
|
360
|
+
|
|
361
|
+
def get_alive_on_art(yrs_months, age_from, age_to, gender, _start_date, end_date)
|
|
362
|
+
alive_on_art_patient_ids = []
|
|
363
|
+
|
|
364
|
+
(@cohort.total_alive_and_on_art || []).each do |data|
|
|
365
|
+
alive_on_art_patient_ids << data['patient_id'].to_i
|
|
366
|
+
end
|
|
367
|
+
|
|
368
|
+
return [] if alive_on_art_patient_ids.blank?
|
|
369
|
+
|
|
370
|
+
ActiveRecord::Base.connection.select_all <<~SQL
|
|
371
|
+
SELECT patient_id
|
|
372
|
+
FROM temp_earliest_start_date
|
|
373
|
+
WHERE gender = '#{gender}' AND date_enrolled <= '#{end_date.to_date}' AND
|
|
374
|
+
patient_id IN(#{alive_on_art_patient_ids.join(',')})
|
|
375
|
+
AND #{timestampdiff_manager(date1: 'birthdate', date2: "DATE('#{end_date.to_date}')", interval: yrs_months)}
|
|
376
|
+
BETWEEN #{age_from} AND #{age_to} #{site_manager(operator: 'AND', column: 'site_id', location: @location)}
|
|
377
|
+
SQL
|
|
378
|
+
end
|
|
379
|
+
|
|
380
|
+
def get_started_on_art(yrs_months, age_from, age_to, gender, start_date, end_date)
|
|
381
|
+
ActiveRecord::Base.connection.select_all <<~SQL
|
|
382
|
+
SELECT patient_id, date_enrolled
|
|
383
|
+
FROM temp_earliest_start_date
|
|
384
|
+
WHERE gender = '#{gender}' AND date_enrolled BETWEEN
|
|
385
|
+
'#{start_date.to_date}' AND '#{end_date.to_date}' AND
|
|
386
|
+
(DATE(date_enrolled) = DATE(earliest_start_date))
|
|
387
|
+
AND #{timestampdiff_manager(date1: 'birthdate', date2: 'DATE(earliest_start_date)', interval: yrs_months)}
|
|
388
|
+
BETWEEN #{age_from} AND #{age_to} #{site_manager(operator: 'AND', column: 'site_id', location: @location)}
|
|
389
|
+
SQL
|
|
390
|
+
end
|
|
391
|
+
|
|
392
|
+
def get_fp(start_date, end_date)
|
|
393
|
+
age_from = 0
|
|
394
|
+
age_to = 1000
|
|
395
|
+
yrs_months = 'year'
|
|
396
|
+
gender = 'F'
|
|
397
|
+
cum_pregnant_women = @cohort.total_pregnant_women
|
|
398
|
+
|
|
399
|
+
return [[], [], [], []] if cum_pregnant_women.blank?
|
|
400
|
+
|
|
401
|
+
pregnant_women_patient_ids = []
|
|
402
|
+
|
|
403
|
+
cum_pregnant_women.each do |p|
|
|
404
|
+
date_enrolled_str = ActiveRecord::Base.connection.select_one <<~SQL
|
|
405
|
+
SELECT date_enrolled FROM temp_earliest_start_date e
|
|
406
|
+
WHERE patient_id = #{p['person_id'].to_i} #{site_manager(operator: 'AND', column: 'e.site_id', location: @location)}
|
|
407
|
+
SQL
|
|
408
|
+
|
|
409
|
+
date_enrolled = date_enrolled_str['date_enrolled'].to_date
|
|
410
|
+
if (date_enrolled >= @cohort_cum_start_date.to_date) && (end_date.to_date <= end_date.to_date)
|
|
411
|
+
pregnant_women_patient_ids << p['person_id'].to_i
|
|
412
|
+
end
|
|
413
|
+
end
|
|
414
|
+
|
|
415
|
+
started_on_art = []
|
|
416
|
+
alive_on_art = []
|
|
417
|
+
started_on_ipt = []
|
|
418
|
+
screened_for_tb = []
|
|
419
|
+
|
|
420
|
+
(get_started_on_art(yrs_months, age_from, age_to, gender, start_date, end_date) || []).each do |p|
|
|
421
|
+
next unless pregnant_women_patient_ids.include?(p['patient_id'].to_i)
|
|
422
|
+
|
|
423
|
+
started_on_art << p
|
|
424
|
+
end
|
|
425
|
+
|
|
426
|
+
(get_alive_on_art(yrs_months, age_from, age_to, gender, @cohort_cum_start_date, end_date) || []).each do |p|
|
|
427
|
+
next unless pregnant_women_patient_ids.include?(p['patient_id'].to_i)
|
|
428
|
+
|
|
429
|
+
alive_on_art << { patient_id: p['patient_id'].to_i }
|
|
430
|
+
end
|
|
431
|
+
|
|
432
|
+
(get_started_on_ipt(yrs_months, age_from, age_to, gender, @cohort_cum_start_date, end_date) || []).each do |p|
|
|
433
|
+
next unless pregnant_women_patient_ids.include?(p['patient_id'].to_i)
|
|
434
|
+
|
|
435
|
+
started_on_ipt << { patient_id: p['patient_id'].to_i }
|
|
436
|
+
end
|
|
437
|
+
|
|
438
|
+
(get_screened_for_tb(yrs_months, age_from, age_to, gender, @cohort_cum_start_date, end_date) || []).each do |p|
|
|
439
|
+
next unless pregnant_women_patient_ids.include?(p['patient_id'].to_i)
|
|
440
|
+
|
|
441
|
+
screened_for_tb << { patient_id: p['patient_id'].to_i }
|
|
442
|
+
end
|
|
443
|
+
|
|
444
|
+
[started_on_art, alive_on_art,
|
|
445
|
+
started_on_ipt, screened_for_tb]
|
|
446
|
+
end
|
|
447
|
+
|
|
448
|
+
def get_fbf(start_date, end_date)
|
|
449
|
+
age_from = 0
|
|
450
|
+
age_to = 1000
|
|
451
|
+
yrs_months = 'year'
|
|
452
|
+
gender = 'F'
|
|
453
|
+
cum_breastfeeding_mothers = @cohort.total_breastfeeding_women
|
|
454
|
+
|
|
455
|
+
return [[], [], [], []] if cum_breastfeeding_mothers.blank?
|
|
456
|
+
|
|
457
|
+
fbf_women_patient_ids = []
|
|
458
|
+
|
|
459
|
+
started_on_art = []
|
|
460
|
+
alive_on_art = []
|
|
461
|
+
started_on_ipt = []
|
|
462
|
+
screened_for_tb = []
|
|
463
|
+
|
|
464
|
+
#########################################################################
|
|
465
|
+
cum_pregnant_women = @cohort.total_pregnant_women
|
|
466
|
+
pregnant_women_patient_ids = []
|
|
467
|
+
|
|
468
|
+
cum_pregnant_women.each do |p|
|
|
469
|
+
date_enrolled_str = ActiveRecord::Base.connection.select_one(
|
|
470
|
+
"SELECT date_enrolled FROM temp_earliest_start_date e
|
|
471
|
+
WHERE patient_id = #{p['person_id'].to_i} #{site_manager(operator: 'AND', column: 'e.site_id',
|
|
472
|
+
location: @location)}"
|
|
473
|
+
)
|
|
474
|
+
|
|
475
|
+
date_enrolled = date_enrolled_str['date_enrolled'].to_date
|
|
476
|
+
if (date_enrolled >= @cohort_cum_start_date.to_date) && (end_date.to_date <= end_date.to_date)
|
|
477
|
+
pregnant_women_patient_ids << p['person_id'].to_i
|
|
478
|
+
end
|
|
479
|
+
end
|
|
480
|
+
#########################################################################
|
|
481
|
+
|
|
482
|
+
cum_breastfeeding_mothers.each do |w|
|
|
483
|
+
next if pregnant_women_patient_ids.include?(w['person_id'].to_i)
|
|
484
|
+
|
|
485
|
+
date_enrolled_str = ActiveRecord::Base.connection.select_one(
|
|
486
|
+
"SELECT date_enrolled FROM temp_earliest_start_date e
|
|
487
|
+
WHERE patient_id = #{w['person_id'].to_i} #{site_manager(operator: 'AND', column: 'e.site_id',
|
|
488
|
+
location: @location)}"
|
|
489
|
+
)
|
|
490
|
+
|
|
491
|
+
date_enrolled = date_enrolled_str['date_enrolled'].to_date
|
|
492
|
+
if (date_enrolled >= @cohort_cum_start_date.to_date) && (end_date.to_date <= end_date.to_date)
|
|
493
|
+
fbf_women_patient_ids << w['person_id'].to_i
|
|
494
|
+
end
|
|
495
|
+
end
|
|
496
|
+
|
|
497
|
+
(get_started_on_art(yrs_months, age_from, age_to, gender, start_date, end_date) || []).each do |fbf|
|
|
498
|
+
next unless fbf_women_patient_ids.include?(fbf['patient_id'].to_i)
|
|
499
|
+
|
|
500
|
+
started_on_art << { patient_id: fbf['patient_id'].to_i, date_enrolled: fbf['date_enrolled'].to_date }
|
|
501
|
+
end
|
|
502
|
+
|
|
503
|
+
(get_alive_on_art(yrs_months, age_from, age_to, gender, @cohort_cum_start_date, end_date) || []).each do |fbf|
|
|
504
|
+
next unless fbf_women_patient_ids.include?(fbf['patient_id'].to_i)
|
|
505
|
+
|
|
506
|
+
alive_on_art << { patient_id: fbf['patient_id'].to_i }
|
|
507
|
+
end
|
|
508
|
+
|
|
509
|
+
(get_started_on_ipt(yrs_months, age_from, age_to, gender, @cohort_cum_start_date, end_date) || []).each do |fbf|
|
|
510
|
+
next unless fbf_women_patient_ids.include?(fbf['patient_id'].to_i)
|
|
511
|
+
|
|
512
|
+
started_on_ipt << { patient_id: fbf['patient_id'].to_i }
|
|
513
|
+
end
|
|
514
|
+
|
|
515
|
+
(get_screened_for_tb(yrs_months, age_from, age_to, gender, @cohort_cum_start_date,
|
|
516
|
+
end_date) || []).each do |fbf|
|
|
517
|
+
next unless fbf_women_patient_ids.include?(fbf['patient_id'].to_i)
|
|
518
|
+
|
|
519
|
+
screened_for_tb << { patient_id: fbf['patient_id'].to_i }
|
|
520
|
+
end
|
|
521
|
+
|
|
522
|
+
[started_on_art, alive_on_art, started_on_ipt, screened_for_tb]
|
|
523
|
+
end
|
|
524
|
+
end
|
|
525
|
+
end
|
|
526
|
+
end
|