malawi_hiv_program_reports 1.0.1 → 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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,219 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'ostruct'
|
4
|
+
|
5
|
+
module MalawiHivProgramReports
|
6
|
+
module Moh
|
7
|
+
# This class is used to add additional cohort disaggregated data
|
8
|
+
# rubocop:disable Metrics/ClassLength
|
9
|
+
class CohortStruct
|
10
|
+
FIELD_DESCRIPTIONS = {
|
11
|
+
# Table contains various fields of the Cohort report and their descriptions.
|
12
|
+
# A fields description is simply "Indicator: Human Readable Name",
|
13
|
+
# or "Human Readable Name". The former is for fields with an indicator
|
14
|
+
# label and the latter is for fields without.
|
15
|
+
# Examples:
|
16
|
+
# ...,
|
17
|
+
# six_a: "KS: Kaposis Sarcoma",
|
18
|
+
# regimen_2p: "Regimen 2P",
|
19
|
+
# ...
|
20
|
+
total_other_patients: 'All others (not circled)',
|
21
|
+
patients_with_7_plus_doses_missed_at_their_last_visit: 'Adherence: 4+ Doses',
|
22
|
+
unknown_age: 'Unknown age',
|
23
|
+
cum_unknown_age: 'Unknown Age (Cumulative)',
|
24
|
+
quarterly_unknown_age: 'Unknown Age (Quarterly)',
|
25
|
+
died_total: 'Died: Died Total',
|
26
|
+
died_within_the_1st_month_of_art_initiation: 'M1: Died within the 1st month after ART initiation',
|
27
|
+
died_within_the_2nd_month_of_art_initiation: 'M2: Died within the 2nd month of art initiation',
|
28
|
+
died_within_the_3rd_month_of_art_initiation: 'M3: Died within the 3rd month after ART initiation',
|
29
|
+
died_after_the_3rd_month_of_art_initiation: 'M4+: Died within the 3rd month after ART initiation',
|
30
|
+
no_tb: 'Nev/>2 Years: Never TB or TB over 2 years ago',
|
31
|
+
cum_no_tb: 'Nev/>2 Years: Never TB or TB over 2 years ago (Cumulative)',
|
32
|
+
quarterly_no_tb: 'Nev/>2 Years: Never TB or TB over 2 years ago (Quarterly)',
|
33
|
+
who_stage_two: 'CD4: CD4 below threshold',
|
34
|
+
cum_who_stage_two: 'CD4: CD4 below threshold (Cumulative)',
|
35
|
+
quarterly_who_stage_two: 'CD4: CD4 below threshold (Quarterly)',
|
36
|
+
asymptomatic: 'Asy: Asymptomatic / mild',
|
37
|
+
cum_asymptomatic: 'Asy: Asymptomatic / mild (Cumulative)',
|
38
|
+
quarterly_asymptomatic: 'Asy: Asymptomatic / mild (Quarterly)',
|
39
|
+
pregnant_women: 'Preg: Pregnant women',
|
40
|
+
cum_pregnant_women: 'Preg: Pregnant Women (Cumulative)',
|
41
|
+
quarterly_pregnant_women: 'Preg: Pregnant Women (Quarterly)',
|
42
|
+
defaulted: 'Def: Defaulted (more than 2 months overdue after expected to have run out of ARVs',
|
43
|
+
tb_within_the_last_two_years: 'Last 2 Years: TB within the last 2 years',
|
44
|
+
cum_tb_within_the_last_two_years: 'Last 2 Years: TB within the last 2 years (Cumulative)',
|
45
|
+
quarterly_tb_within_the_last_two_years: 'Last 2 Years: TB within the last 2 years (Quarterly)',
|
46
|
+
total_patients_without_side_effects: 'Side Effects (as of the last visit before end of quarter)',
|
47
|
+
current_episode_of_tb: 'Curr: Current episode of TB',
|
48
|
+
cum_current_episode_of_tb: 'Curr: Current episode of TB (Cumulative)',
|
49
|
+
quarterly_current_episode_of_tb: 'Curr: Current episode of TB (Quarterly)',
|
50
|
+
re_initiated_on_art: 'Re: Patients re-initiated on ART',
|
51
|
+
cum_re_initiated_on_art: 'Re: Patients re-initiated on ART (Cumulative)',
|
52
|
+
quarterly_re_initiated_on_art: 'Re: Patients re-initiated on ART (Quarterly)',
|
53
|
+
zero_p: 'Regimen 0P',
|
54
|
+
zero_a: 'Regimen 0 A',
|
55
|
+
two_p: 'Regimen 2P',
|
56
|
+
two_a: 'Regimen 2 A',
|
57
|
+
four_pp: ' Regimen 4PP',
|
58
|
+
four_pa: ' Regimen 4PA',
|
59
|
+
four_a: 'Regimen 4 A',
|
60
|
+
five_a: 'Regimen 5 A',
|
61
|
+
six_a: 'Regimen 6 A',
|
62
|
+
seven_a: 'Regimen 7 A',
|
63
|
+
eight_a: 'Regimen 8 A',
|
64
|
+
nine_pp: 'Regimen 9PP',
|
65
|
+
nine_pa: 'Regimen 9PA',
|
66
|
+
nine_a: 'Regimen 9 A',
|
67
|
+
ten_a: 'Regimen 10 A',
|
68
|
+
eleven_pp: 'Regimen 11PP',
|
69
|
+
eleven_pa: 'Regimen 11PA',
|
70
|
+
eleven_a: 'Regimen 11 A',
|
71
|
+
twelve_pp: 'Regimen 12PP',
|
72
|
+
twelve_pa: 'Regimen 12PA',
|
73
|
+
twelve_a: 'Regimen 12 A',
|
74
|
+
thirteen_a: 'Regimen 13 A',
|
75
|
+
fourteen_pp: 'Regimen 14PP',
|
76
|
+
fourteen_pa: 'Regimen 14PA',
|
77
|
+
fourteen_a: 'Regimen 14 A',
|
78
|
+
fifteen_pp: 'Regimen 15PP',
|
79
|
+
fifteen_pa: 'Regimen 15PA',
|
80
|
+
fifteen_a: 'Regimen 15 A',
|
81
|
+
sixteen_p: 'Regimen 16P',
|
82
|
+
sixteen_a: 'Regimen 16 A',
|
83
|
+
seventeen_pa: 'Regimen 17PA',
|
84
|
+
seventeen_pp: 'Regimen 17PP',
|
85
|
+
seventeen_a: 'Regimen 17 A',
|
86
|
+
total_patients_with_side_effects: 'Any side effects',
|
87
|
+
total_patients_on_family_planning: 'PIFP: Apprx. % of women who received Depo at ART in the last quarter',
|
88
|
+
total_pregnant_women: 'Pregnant/BreastFeeding as of the last visit before end of quarter',
|
89
|
+
transfered_out: 'TO: Transferred Out',
|
90
|
+
children_12_59_months: 'U5: Children 12 - 59 months',
|
91
|
+
cum_children_12_59_months: 'U5: Children 12 - 59 months (Cumulative)',
|
92
|
+
quarterly_children_12_59_months: 'U5: Children 12 - 59 months (Quarterly)',
|
93
|
+
tb_not_suspected: 'Current TB status any form of TB',
|
94
|
+
tb_confirmed_on_tb_treatment: 'TB confirmed, on TB Treatment',
|
95
|
+
tb_confirmed_currently_not_yet_on_tb_treatment: 'TB confirmed, not on TB Treatment',
|
96
|
+
breastfeeding_mothers: 'BF: Breastfeeding mothers',
|
97
|
+
cum_breastfeeding_mothers: 'BF: Breastfeeding mothers (Cumulative)',
|
98
|
+
quarterly_breastfeeding_mothers: 'BF: Breastfeeding mothers (Quarterly)',
|
99
|
+
patients_with_0_6_doses_missed_at_their_last_visit: 'Adnerence: as of the last visit before end of quarter',
|
100
|
+
total_patients_on_arvs_and_ipt: 'IPT: Apprx. % of patients retained in <b>ART</b> who are currently on IPT',
|
101
|
+
total_breastfeeding_women: 'Total Breastfeeding Women',
|
102
|
+
total_alive_and_on_art: ' Total alive and on ART',
|
103
|
+
kaposis_sarcoma: "KS: Kaposi's Sarcoma",
|
104
|
+
cum_kaposis_sarcoma: "KS: Kaposi's Sarcoma (Cumulative)",
|
105
|
+
quarterly_kaposis_sarcoma: "KS: Kaposi's Sarcoma (Quarterly)",
|
106
|
+
unknown_outcome: 'Patient status is unknown',
|
107
|
+
unknown_regimen: "Specify above regimens counted as 'Other' Other (paed. / adult)",
|
108
|
+
total_patients_with_screened_bp: 'BP screen: Apprx. % of adult ART patients with BP recorded at least once this year',
|
109
|
+
cum_total_registered: 'Total Registered (Cummulative)',
|
110
|
+
quarterly_total_registered: 'Total Registered (Quarterly)',
|
111
|
+
transfer_in: 'TI: Patients transferred in on ART',
|
112
|
+
cum_transfer_in: 'TI: Patients transferred in on ART (Cumulative)',
|
113
|
+
quarterly_transfer_in: 'TI: Patients transferred in on ART (Quarterly)',
|
114
|
+
confirmed_hiv_infection_in_infants_pcr: 'PCR: Infants < 12 months PCR+',
|
115
|
+
cum_confirmed_hiv_infection_in_infants_pcr: 'PCR: Infants < 12 months PCR+ (Cumulative)',
|
116
|
+
quarterly_confirmed_hiv_infection_in_infants_pcr: 'PCR: Infants < 12 months PCR+ (Quarterly)',
|
117
|
+
who_stage_four: '4: WHO stage 4',
|
118
|
+
cum_who_stage_four: '4: WHO stage 4 (Cumulative)',
|
119
|
+
quarterly_who_stage_four: '4: WHO stage 4 (Quarterly)',
|
120
|
+
non_pregnant_females: 'FNP: Non-pregnant females all ages',
|
121
|
+
cum_non_pregnant_females: 'FNP: Non-pregnant females all ages (Cumulative)',
|
122
|
+
quarterly_non_pregnant_females: 'FNP: Non-pregnant females all ages (Quarterly)',
|
123
|
+
unknown_tb_status: 'Unknown (not circled)',
|
124
|
+
total_patients_on_arvs_and_cpt: 'CPT: Apprx. % of patients retained in <b>ART</b> who are currently on CPT',
|
125
|
+
tb_suspected: 'TB Suspected',
|
126
|
+
unknown_side_effects: 'Unkown (not circled)',
|
127
|
+
total_registered: 'Total Registered',
|
128
|
+
pregnant_females_all_ages: 'Female pregnant_females all ages',
|
129
|
+
cum_pregnant_females_all_ages: 'Female pregnant patients all ages (Cumulative)',
|
130
|
+
quarterly_pregnant_females_all_ages: 'Cumulative female pregnant patients (Quarterly)',
|
131
|
+
patients_with_unknown_adhrence: 'Unknown (not circled)',
|
132
|
+
who_stage_three: '3: WHO stage 3',
|
133
|
+
cum_who_stage_three: '3: WHO stage 3 (Cumulative)',
|
134
|
+
quarterly_who_stage_three: '3: WHO stage 3 (Quarterly)',
|
135
|
+
unknown_other_reason_outside_guidelines: 'Unk: Unknown / reason outside guidelines',
|
136
|
+
cum_unknown_other_reason_outside_guidelines: 'Unk: Unknown / reason outside guidelines (Cumulative)',
|
137
|
+
quarterly_unknown_other_reason_outside_guidelines: 'Unk: Unknown / reason outside guidelines (Quarterly)',
|
138
|
+
initiated_on_art_first_time: 'FT: Patients initiated on ART first time',
|
139
|
+
cum_initiated_on_art_first_time: 'FT: Patients initiated on ART first time (Cummulative)',
|
140
|
+
quarterly_initiated_on_art_first_time: 'FT: Patients initiated on ART first time (Quarterly)',
|
141
|
+
presumed_severe_hiv_disease_in_infants: 'PSHD: Pres. Sev. HIV disease age < 12 months',
|
142
|
+
cum_presumed_severe_hiv_disease_in_infants: 'PSHD: Pres. Sev. HIV disease age < 12 months (Cumulative)',
|
143
|
+
quarterly_presumed_severe_hiv_disease_in_infants: 'PSHD: Pres. Sev. HIV disease age < 12 months (Quarterly)',
|
144
|
+
all_males: 'M: Males all ages',
|
145
|
+
cum_all_males: 'M: Males all ages (Cumulative)',
|
146
|
+
quarterly_all_males: 'M: Males all ages (Quarterly)',
|
147
|
+
stopped_art: 'Stop: Stopped taking ARVs (clinician or patient own decision, last known alive)',
|
148
|
+
children_below_24_months_at_art_initiation: 'A: Children below 24 months at ART initiation',
|
149
|
+
cum_children_below_24_months_at_art_initiation: 'A: Children below 24 months at ART initiation (Cumulative)',
|
150
|
+
quarterly_children_below_24_months_at_art_initiation: 'A: Children below 24 m at ART initiation (Quarterly)',
|
151
|
+
children_24_months_14_years_at_art_initiation: 'B: Children 24 months - 14 years at ART initiation',
|
152
|
+
cum_children_24_months_14_years_at_art_initiation: 'B: Children 24 months - 14 years at ART initiation (Cumulative)',
|
153
|
+
quarterly_children_24_months_14_years_at_art_initiation: 'B: Children 24 months - 14 years at ART initiation (Quarterly)',
|
154
|
+
adults_at_art_initiation: 'C: Adults 15 years or older at ART initiation',
|
155
|
+
cum_adults_at_art_initiation: 'C: Adults 15 years or older at ART initiation (Cumulative)',
|
156
|
+
quarterly_adults_at_art_initiation: 'C: Adults 15 years or older at ART initiation (Quarterly)',
|
157
|
+
males_initiated_on_art_first_time: 'Newly initiated male patients',
|
158
|
+
cum_males_initiated_on_art_first_time: 'Newly initiated male patients (Cummulative)',
|
159
|
+
initial_pregnant_females_all_ages: 'Newly initiated pregnant females',
|
160
|
+
cum_initial_pregnant_females_all_ages: 'Newly initiated pregnant females (Cummulative)',
|
161
|
+
initial_non_pregnant_females_all_ages: 'Newly initiated non-pregnant females',
|
162
|
+
cum_initial_non_pregnant_females_all_ages: 'Newly initiated non-pregnant females (Cummulative)',
|
163
|
+
unknown_gender: 'All clients registered but has not gender specified',
|
164
|
+
cum_unknown_gender: 'All clients registered but has not gender specified (Cummulative)',
|
165
|
+
newly_initiated_on_3hp: 'All patients who started 3HP in current reporting period',
|
166
|
+
newly_initiated_on_ipt: 'All patients who started IPT in current reporting period'
|
167
|
+
}.freeze
|
168
|
+
|
169
|
+
def initialize
|
170
|
+
@values = ActiveSupport::HashWithIndifferentAccess.new
|
171
|
+
end
|
172
|
+
|
173
|
+
def method_missing(name, *args, &)
|
174
|
+
name_prefix, name_suffix = split_missing_method_name(name)
|
175
|
+
|
176
|
+
return super(name, *args, &) unless FIELD_DESCRIPTIONS.include?(name_prefix)
|
177
|
+
|
178
|
+
field = value(name_prefix)
|
179
|
+
field.contents = args[0] if name_suffix == '='
|
180
|
+
field.contents
|
181
|
+
|
182
|
+
field.contents
|
183
|
+
end
|
184
|
+
|
185
|
+
def respond_to_missing?(name)
|
186
|
+
field_name, = split_missing_method_name(name)
|
187
|
+
FIELD_DESCRIPTIONS.include?(field_name)
|
188
|
+
end
|
189
|
+
|
190
|
+
def values
|
191
|
+
@values.values
|
192
|
+
end
|
193
|
+
|
194
|
+
private
|
195
|
+
|
196
|
+
# Returns a ReportValue object for the given name
|
197
|
+
def value(name)
|
198
|
+
description = FIELD_DESCRIPTIONS[name]
|
199
|
+
iname_parts = description.split(':', 2)
|
200
|
+
iname_parts.insert(0, nil) unless iname_parts.size == 2
|
201
|
+
short_iname, long_iname = iname_parts
|
202
|
+
|
203
|
+
@values[name] ||= OpenStruct.new(
|
204
|
+
name:,
|
205
|
+
indicator_name: long_iname.strip,
|
206
|
+
indicator_short_name: short_iname ? short_iname.strip : short_iname,
|
207
|
+
description:,
|
208
|
+
contents: nil
|
209
|
+
)
|
210
|
+
end
|
211
|
+
|
212
|
+
def split_missing_method_name(name)
|
213
|
+
match = name.to_s.match(/^([_A-Z0-9]+)(=)?$/i)
|
214
|
+
[match[1].to_sym, match[2]]
|
215
|
+
end
|
216
|
+
end
|
217
|
+
# rubocop:enable Metrics/ClassLength
|
218
|
+
end
|
219
|
+
end
|
@@ -0,0 +1,203 @@
|
|
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 CohortSurvivalAnalysis
|
8
|
+
def initialize(name:, type:, start_date:, end_date:, regenerate:, occupation:)
|
9
|
+
@name = name
|
10
|
+
@type = type
|
11
|
+
@start_date = start_date
|
12
|
+
@end_date = end_date
|
13
|
+
@regenerate = regenerate
|
14
|
+
@occupation = occupation
|
15
|
+
end
|
16
|
+
|
17
|
+
def survival_analysis(quarter, age_group)
|
18
|
+
art_service = CohortDisaggregated.new(name: 'survival_analysis',
|
19
|
+
type: 'survival_analysis', start_date: Date.today,
|
20
|
+
end_date: Date.today, rebuild: @regenerate)
|
21
|
+
|
22
|
+
start_date, end_date = art_service.generate_start_date_and_end_date(quarter)
|
23
|
+
CohortBuilder.new.init_temporary_tables(start_date, @end_date, @occupation) if @regenerate
|
24
|
+
art_service = CohortDisaggregated.new(name: 'survival_analysis',
|
25
|
+
type: 'survival_analysis', start_date: @start_date.to_date,
|
26
|
+
end_date: @end_date.to_date, rebuild: @regenerate)
|
27
|
+
|
28
|
+
qtr = quarter.split[0]
|
29
|
+
results = {}
|
30
|
+
years = 1
|
31
|
+
|
32
|
+
years_to_backto = ActiveRecord::Base.connection.select_one <<~SQL
|
33
|
+
SELECT
|
34
|
+
TIMESTAMPDIFF(YEAR, DATE(MIN(encounter_datetime)), DATE('#{end_date}')) years
|
35
|
+
FROM encounter e WHERE program_id = 1 AND voided = 0;
|
36
|
+
SQL
|
37
|
+
|
38
|
+
clinic_start_years = begin
|
39
|
+
years_to_backto['years'].to_i
|
40
|
+
rescue StandardError
|
41
|
+
nil
|
42
|
+
end
|
43
|
+
clinic_start_years = 10 if clinic_start_years.blank?
|
44
|
+
|
45
|
+
while years < clinic_start_years
|
46
|
+
yr = (quarter.split[1].to_i - years)
|
47
|
+
set_qtr = "#{qtr} #{yr}"
|
48
|
+
qstart_date, qend_date = art_service.generate_start_date_and_end_date(set_qtr)
|
49
|
+
results[set_qtr] = {}
|
50
|
+
|
51
|
+
case age_group
|
52
|
+
when 'General'
|
53
|
+
additional_sql = ' GROUP BY e.patient_id'
|
54
|
+
when 'Children'
|
55
|
+
additional_sql = ' GROUP BY e.patient_id'
|
56
|
+
additional_sql += ' HAVING patient_age < 15'
|
57
|
+
when 'Women'
|
58
|
+
option_Bplus_women_ids = pregnant_and_breastfeeding_women(qstart_date, qend_date)
|
59
|
+
|
60
|
+
option_Bplus_women_ids = [0] if option_Bplus_women_ids.blank?
|
61
|
+
|
62
|
+
additional_sql = " AND e.patient_id IN (#{option_Bplus_women_ids.join(', ')})"
|
63
|
+
additional_sql += ' GROUP BY e.patient_id'
|
64
|
+
additional_sql += ' HAVING patient_age >= 15'
|
65
|
+
additional_sql += ' AND gender = "F"'
|
66
|
+
end
|
67
|
+
|
68
|
+
begin
|
69
|
+
data = ActiveRecord::Base.connection.select_all <<~SQL
|
70
|
+
SELECT
|
71
|
+
cum_outcome, timestampdiff(month, DATE('#{qend_date}'), DATE('#{end_date}')) qinterval,
|
72
|
+
timestampdiff(year, DATE(e.birthdate), DATE('#{end_date}')) AS patient_age,
|
73
|
+
e.gender
|
74
|
+
FROM temp_earliest_start_date e
|
75
|
+
INNER JOIN temp_patient_outcomes o ON o.patient_id = e.patient_id
|
76
|
+
WHERE date_enrolled BETWEEN '#{qstart_date.strftime('%Y-%m-%d')}'
|
77
|
+
AND '#{qend_date.strftime('%Y-%m-%d')}'
|
78
|
+
#{additional_sql};
|
79
|
+
SQL
|
80
|
+
rescue StandardError
|
81
|
+
return results
|
82
|
+
end
|
83
|
+
|
84
|
+
(data || []).each do |r|
|
85
|
+
outcome = r['cum_outcome']
|
86
|
+
outcome = (outcome.blank? ? 'Unknown' : outcome)
|
87
|
+
|
88
|
+
if results[set_qtr][outcome].blank?
|
89
|
+
results[set_qtr][outcome] = {}
|
90
|
+
results[set_qtr][outcome][r['qinterval']] = 0
|
91
|
+
end
|
92
|
+
results[set_qtr][outcome][r['qinterval']] += 1
|
93
|
+
end
|
94
|
+
|
95
|
+
years += 1
|
96
|
+
end
|
97
|
+
|
98
|
+
append_last_six_months(quarter, results, end_date) if age_group == 'Women'
|
99
|
+
|
100
|
+
results
|
101
|
+
end
|
102
|
+
|
103
|
+
def pregnant_and_breastfeeding_women(start_date, end_date)
|
104
|
+
patient_ids = []
|
105
|
+
|
106
|
+
patients = ActiveRecord::Base.connection.select_all <<~SQL
|
107
|
+
SELECT
|
108
|
+
e.*, patient_reason_for_starting_art_text(e.patient_id) reason
|
109
|
+
FROM temp_earliest_start_date e
|
110
|
+
WHERE date_enrolled BETWEEN '#{start_date.to_date}' AND '#{end_date.to_date}'
|
111
|
+
AND gender IN('F','Female') GROUP BY e.patient_id
|
112
|
+
HAVING reason LIKE '%pregnant%' OR reason LIKE '%breast%';
|
113
|
+
SQL
|
114
|
+
|
115
|
+
(patients || []).each do |aRow|
|
116
|
+
patient_ids << aRow['patient_id'].to_i
|
117
|
+
end
|
118
|
+
|
119
|
+
concept_ids = []
|
120
|
+
::ConceptName.where(name: 'Breastfeeding').select do |c|
|
121
|
+
concept_ids << c.concept_id
|
122
|
+
end
|
123
|
+
concept_ids << ::ConceptName.find_by_name('Patient pregnant').concept_id
|
124
|
+
concept_ids << ::ConceptName.find_by_name('Is patient pregnant?').concept_id
|
125
|
+
concept_ids << ::ConceptName.find_by_name('Is patient breast feeding?').concept_id
|
126
|
+
yes_concept_id = ::ConceptName.find_by_name('Yes').concept_id
|
127
|
+
|
128
|
+
patients = ActiveRecord::Base.connection.select_all <<~SQL
|
129
|
+
SELECT
|
130
|
+
e.*, patient_reason_for_starting_art_text(e.patient_id) reason
|
131
|
+
FROM temp_earliest_start_date e
|
132
|
+
INNER JOIN obs ON obs.person_id = e.patient_id
|
133
|
+
WHERE date_enrolled BETWEEN '#{start_date.to_date}' AND '#{end_date.to_date}'
|
134
|
+
AND gender IN('F','Female') AND obs.voided = 0
|
135
|
+
AND DATE(obs_datetime) = DATE(earliest_start_date)
|
136
|
+
AND obs.concept_id IN(#{concept_ids.join(',')})
|
137
|
+
AND value_coded = #{yes_concept_id} GROUP BY e.patient_id
|
138
|
+
HAVING reason LIKE '%Lymphocyte count below threshold with who stage%'
|
139
|
+
ORDER BY obs_datetime DESC;
|
140
|
+
SQL
|
141
|
+
|
142
|
+
pregnant_and_breastfeeding_clients = []
|
143
|
+
|
144
|
+
(patients || []).each do |aRow|
|
145
|
+
pregnant_and_breastfeeding_clients << aRow['patient_id'].to_i
|
146
|
+
end
|
147
|
+
|
148
|
+
(patient_ids + pregnant_and_breastfeeding_clients).uniq
|
149
|
+
end
|
150
|
+
|
151
|
+
def append_last_six_months(quarter, results, end_date)
|
152
|
+
art_service = CohortDisaggregated.new(name: 'survival_analysis',
|
153
|
+
type: 'survival_analysis', start_date: @start_date.to_date,
|
154
|
+
end_date: @end_date.to_date, rebuild: @regenerate)
|
155
|
+
|
156
|
+
qstart_date, qend_date = art_service.generate_start_date_and_end_date(quarter)
|
157
|
+
qstart_date -= 6.month
|
158
|
+
qend_date -= 6.month
|
159
|
+
# set_qtr = "Q#{quarter.split(' ')[0][1..1].to_i - 2} #{qend_date.year}"
|
160
|
+
set_qtr = (quarter[1..1].to_i - 2)
|
161
|
+
|
162
|
+
set_qtr = (set_qtr.zero? ? 4 : set_qtr)
|
163
|
+
set_qtr = (set_qtr == -1 ? 3 : set_qtr)
|
164
|
+
set_qtr = (set_qtr == -2 ? 2 : set_qtr)
|
165
|
+
set_qtr = "Q#{set_qtr} #{qend_date.year}"
|
166
|
+
|
167
|
+
option_Bplus_women_ids = pregnant_and_breastfeeding_women(qstart_date, qend_date)
|
168
|
+
option_Bplus_women_ids = [0] if option_Bplus_women_ids.blank?
|
169
|
+
|
170
|
+
data = ActiveRecord::Base.connection.select_all <<~SQL
|
171
|
+
SELECT
|
172
|
+
cum_outcome, timestampdiff(month, DATE('#{qend_date}'), DATE('#{end_date}')) qinterval,
|
173
|
+
timestampdiff(year, DATE(e.birthdate), DATE('#{end_date}')) AS patient_age,
|
174
|
+
e.gender
|
175
|
+
FROM temp_earliest_start_date e
|
176
|
+
INNER JOIN temp_patient_outcomes o ON o.patient_id = e.patient_id
|
177
|
+
WHERE date_enrolled BETWEEN '#{qstart_date.strftime('%Y-%m-%d')}'
|
178
|
+
AND '#{qend_date.strftime('%Y-%m-%d')}' AND gender = 'F' AND e.patient_id IN (#{option_Bplus_women_ids.join(', ')});
|
179
|
+
SQL
|
180
|
+
|
181
|
+
(data || []).each do |r|
|
182
|
+
outcome = r['cum_outcome']
|
183
|
+
outcome = (outcome.blank? ? 'Unknown' : outcome)
|
184
|
+
|
185
|
+
if results[set_qtr].blank?
|
186
|
+
results[set_qtr] = {}
|
187
|
+
results[set_qtr][outcome] = {}
|
188
|
+
results[set_qtr][outcome][r['qinterval']] = 0
|
189
|
+
elsif results[set_qtr][outcome].blank?
|
190
|
+
results[set_qtr][outcome] = {}
|
191
|
+
results[set_qtr][outcome][r['qinterval']] = 0
|
192
|
+
end
|
193
|
+
|
194
|
+
puts "######### #{r['qinterval']}"
|
195
|
+
results[set_qtr][outcome][r['qinterval']] += 1
|
196
|
+
end
|
197
|
+
|
198
|
+
results
|
199
|
+
end
|
200
|
+
end
|
201
|
+
# rubocop:enable Metrics/ClassLength
|
202
|
+
end
|
203
|
+
end
|
@@ -0,0 +1,223 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module MalawiHivProgramReports
|
4
|
+
module Moh
|
5
|
+
# This class generates the MOH TPT report
|
6
|
+
# rubocop:disable Metrics/ClassLength
|
7
|
+
class MohTpt
|
8
|
+
include MalawiHivProgramReports::Utils::CommonSqlQueryUtils
|
9
|
+
attr_reader :start_date, :end_date, :start_of_month, :end_of_month, :raw_end_date, :raw_start_date
|
10
|
+
|
11
|
+
def initialize(start_date:, end_date:, **kwargs)
|
12
|
+
@raw_end_date = end_date.to_date
|
13
|
+
@raw_start_date = start_date.to_date
|
14
|
+
@start_date = start_date - 9.months
|
15
|
+
@end_date = @start_date + 3.months
|
16
|
+
@start_of_month = @start_date.beginning_of_month
|
17
|
+
@end_of_month = @end_date.end_of_month
|
18
|
+
@occupation = kwargs[:occupation]
|
19
|
+
end
|
20
|
+
|
21
|
+
def data
|
22
|
+
report = init_report
|
23
|
+
drop_tables
|
24
|
+
initiated_on_art
|
25
|
+
initiated_on_tpt
|
26
|
+
create_indexes
|
27
|
+
process_initiated_on_art report, fetch_initiated_on_art
|
28
|
+
process_initiated_tpt report, fetch_initiated_on_tpt
|
29
|
+
response = []
|
30
|
+
report.each do |key, value|
|
31
|
+
response << { age_group: key, gender: 'F', **value['F'] }
|
32
|
+
response << { age_group: key, gender: 'M', **value['M'] }
|
33
|
+
end
|
34
|
+
response
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
GENDERS = %w[F M].freeze
|
40
|
+
AGE_GROUPS = ['<1 year', '1-4 years', '5-9 years', '10-14 years', '15-19 years',
|
41
|
+
'20-24 years', '25-29 years', '30-34 years', '35-39 years', '40-44 years',
|
42
|
+
'45-49 years', '50-54 years', '55-59 years', '60-64 years', '65-69 years',
|
43
|
+
'70-74 years', '75-79 years', '80-84 years', '85-89 years',
|
44
|
+
'90 plus years'].freeze
|
45
|
+
|
46
|
+
def init_report
|
47
|
+
AGE_GROUPS.each_with_object({}) do |age_group, report|
|
48
|
+
report[age_group] = GENDERS.each_with_object({}) do |gender, tpt_report|
|
49
|
+
tpt_report[gender] = {
|
50
|
+
initiated_art: [], started_tpt: [], not_completed_tpt: [],
|
51
|
+
completed_tpt: [], died: [], pregnant: [],
|
52
|
+
defaulted: [], stopped: [],
|
53
|
+
transfer_out: [], confirmed_tb: [],
|
54
|
+
breast_feeding: [], skin_rash: [],
|
55
|
+
nausea: [], peripheral_neuropathy: [],
|
56
|
+
dizziness: [], yellow_eyes: []
|
57
|
+
}
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def process_initiated_on_art(report, patients)
|
63
|
+
patients.each do |patient|
|
64
|
+
report[patient['age_group']][patient['gender']][:initiated_art] << patient['patient_id']
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def process_initiated_tpt(report, patients)
|
69
|
+
TptOutcome.new(start_date:, end_date: raw_end_date)
|
70
|
+
.moh_report(report, patients, start_date, end_date)
|
71
|
+
end
|
72
|
+
|
73
|
+
def fetch_initiated_on_art
|
74
|
+
ActiveRecord::Base.connection.select_all <<~SQL
|
75
|
+
SELECT patient_id, age_group, gender FROM temp_initiated_on_art
|
76
|
+
WHERE art_start_date >= DATE('#{start_of_month}')
|
77
|
+
SQL
|
78
|
+
end
|
79
|
+
|
80
|
+
def fetch_initiated_on_tpt
|
81
|
+
result = ActiveRecord::Base.connection.select_all <<~SQL
|
82
|
+
SELECT * FROM temp_initiated_on_tpt
|
83
|
+
WHERE start_date >= DATE('#{start_of_month}')
|
84
|
+
SQL
|
85
|
+
# convert to array of hashes
|
86
|
+
result.to_a
|
87
|
+
end
|
88
|
+
|
89
|
+
def initiated_on_art
|
90
|
+
ActiveRecord::Base.connection.execute <<~SQL
|
91
|
+
CREATE TABLE temp_initiated_on_art
|
92
|
+
SELECT pp.patient_id, coalesce(o.value_datetime, min(art_order.start_date)) art_start_date, p.gender, disaggregated_age_group(p.birthdate, DATE('#{raw_end_date}')) age_group
|
93
|
+
FROM patient_program pp
|
94
|
+
INNER JOIN person p ON p.person_id = pp.patient_id AND p.voided = 0
|
95
|
+
INNER JOIN patient_state ps ON ps.patient_program_id = pp.patient_program_id AND ps.voided = 0 AND ps.state = 7 -- ON ART
|
96
|
+
INNER JOIN orders art_order ON art_order.patient_id = pp.patient_id
|
97
|
+
AND art_order.start_date >= DATE('#{start_of_month}')
|
98
|
+
AND art_order.start_date < DATE('#{end_of_month}') + INTERVAL 1 DAY
|
99
|
+
AND art_order.voided = 0
|
100
|
+
AND art_order.order_type_id = 1 -- Drug order
|
101
|
+
AND art_order.concept_id IN (#{arv_concepts})
|
102
|
+
INNER JOIN drug_order do ON do.order_id = art_order.order_id AND do.quantity > 0
|
103
|
+
LEFT JOIN encounter e ON e.patient_id = pp.patient_id
|
104
|
+
AND e.encounter_type = 9 -- HIV CLINIC REGISTRATION
|
105
|
+
AND e.voided = 0
|
106
|
+
AND e.encounter_datetime < DATE('#{end_of_month}') + INTERVAL 1 DAY
|
107
|
+
AND e.program_id = 1 -- HIV PROGRAM
|
108
|
+
LEFT JOIN obs o ON o.person_id = pp.patient_id
|
109
|
+
AND o.concept_id = 2516 -- ART start date
|
110
|
+
AND o.encounter_id = e.encounter_id
|
111
|
+
AND o.voided = 0
|
112
|
+
LEFT JOIN (#{current_occupation_query}) a ON a.person_id = pp.patient_id
|
113
|
+
WHERE pp.patient_id NOT IN (
|
114
|
+
SELECT o.patient_id
|
115
|
+
FROM orders o
|
116
|
+
INNER JOIN drug_order do ON do.order_id = o.order_id AND do.quantity > 0
|
117
|
+
WHERE o.order_type_id = 1 -- Drug order
|
118
|
+
AND o.voided = 0
|
119
|
+
AND o.concept_id IN (#{arv_concepts})
|
120
|
+
AND o.start_date < DATE('#{start_of_month}')
|
121
|
+
GROUP BY o.patient_id
|
122
|
+
)
|
123
|
+
AND pp.program_id = 1 #{%w[Military Civilian].include?(@occupation) ? 'AND' : ''} #{occupation_filter(occupation: @occupation, field_name: 'value', table_name: 'a', include_clause: false)}
|
124
|
+
GROUP BY pp.patient_id
|
125
|
+
SQL
|
126
|
+
end
|
127
|
+
|
128
|
+
def initiated_on_tpt
|
129
|
+
ActiveRecord::Base.connection.execute <<~SQL
|
130
|
+
CREATE TABLE temp_initiated_on_tpt
|
131
|
+
SELECT
|
132
|
+
pp.patient_id,
|
133
|
+
coalesce(tpt_transfer_in_obs.value_datetime, min(tpt_order.start_date)) start_date,
|
134
|
+
p.gender, disaggregated_age_group(p.birthdate, DATE('#{raw_end_date}')) age_group,
|
135
|
+
patient_outcome(p.person_id, DATE('#{@raw_end_date}')) AS outcome,
|
136
|
+
DATE(COALESCE(art_start_date_obs.value_datetime, MIN(art_order.start_date))) AS earliest_start_date,
|
137
|
+
GROUP_CONCAT(DISTINCT tpt_order.concept_id SEPARATOR ',') AS drug_concepts,
|
138
|
+
CASE
|
139
|
+
WHEN count(DISTINCT tpt_order.concept_id) > 1 THEN '3HP'
|
140
|
+
WHEN tpt_order.concept_id = 10565 THEN '3HP'
|
141
|
+
ELSE '6H'
|
142
|
+
END AS tpt_type
|
143
|
+
FROM patient_program pp
|
144
|
+
INNER JOIN person p ON p.person_id = pp.patient_id AND p.voided = 0
|
145
|
+
INNER JOIN patient_state ps ON ps.patient_program_id = pp.patient_program_id AND ps.voided = 0 AND ps.state = 7 -- ON ART
|
146
|
+
INNER JOIN orders tpt_order ON tpt_order.patient_id = pp.patient_id
|
147
|
+
AND tpt_order.start_date >= DATE('#{start_of_month}')
|
148
|
+
AND tpt_order.start_date < DATE('#{end_of_month}') + INTERVAL 1 DAY
|
149
|
+
AND tpt_order.voided = 0
|
150
|
+
AND tpt_order.order_type_id = 1 -- Drug order
|
151
|
+
AND tpt_order.concept_id IN (#{tpt_concepts})
|
152
|
+
INNER JOIN drug_order do ON do.order_id = tpt_order.order_id AND do.quantity > 0
|
153
|
+
LEFT JOIN encounter AS clinic_registration_encounter
|
154
|
+
ON clinic_registration_encounter.encounter_type = (
|
155
|
+
SELECT encounter_type_id FROM encounter_type WHERE name = 'HIV CLINIC REGISTRATION' LIMIT 1
|
156
|
+
)
|
157
|
+
AND clinic_registration_encounter.patient_id = pp.patient_id
|
158
|
+
AND clinic_registration_encounter.program_id = pp.program_id
|
159
|
+
AND clinic_registration_encounter.encounter_datetime < DATE('#{@end_date}') + INTERVAL 1 DAY
|
160
|
+
AND clinic_registration_encounter.voided = 0
|
161
|
+
INNER JOIN orders AS art_order
|
162
|
+
ON art_order.patient_id = pp.patient_id
|
163
|
+
/* AND art_order.encounter_id = prescription_encounter.encounter_id */
|
164
|
+
AND art_order.concept_id IN (SELECT concept_id FROM concept_set WHERE concept_set = 1085)
|
165
|
+
AND art_order.start_date < DATE('#{@end_of_month}') + INTERVAL 1 DAY
|
166
|
+
AND art_order.order_type_id IN (SELECT order_type_id FROM order_type WHERE name = 'Drug order')
|
167
|
+
AND art_order.start_date >= DATE('1901-01-01')
|
168
|
+
AND art_order.voided = 0
|
169
|
+
LEFT JOIN obs AS art_start_date_obs
|
170
|
+
ON art_start_date_obs.concept_id = 2516
|
171
|
+
AND art_start_date_obs.person_id = pp.patient_id
|
172
|
+
AND art_start_date_obs.voided = 0
|
173
|
+
AND art_start_date_obs.obs_datetime < (DATE('#{@end_of_month}') + INTERVAL 1 DAY)
|
174
|
+
AND art_start_date_obs.encounter_id = clinic_registration_encounter.encounter_id
|
175
|
+
LEFT JOIN obs tpt_transfer_in_obs ON tpt_transfer_in_obs.person_id = pp.patient_id
|
176
|
+
AND tpt_transfer_in_obs.concept_id = #{::ConceptName.find_by_name('TPT Drugs Received').concept_id}
|
177
|
+
AND tpt_transfer_in_obs.voided = 0
|
178
|
+
AND tpt_transfer_in_obs.value_drug IN (#{tpt_concepts})
|
179
|
+
AND tpt_transfer_in_obs.obs_datetime < DATE('#{end_of_month}') + INTERVAL 1 DAY
|
180
|
+
LEFT JOIN (#{current_occupation_query}) a ON a.person_id = pp.patient_id
|
181
|
+
WHERE pp.patient_id NOT IN (
|
182
|
+
SELECT o.patient_id
|
183
|
+
FROM orders o
|
184
|
+
INNER JOIN drug_order do ON do.order_id = o.order_id AND do.quantity > 0
|
185
|
+
WHERE o.order_type_id = 1 -- Drug order
|
186
|
+
AND o.voided = 0
|
187
|
+
AND o.concept_id IN (#{tpt_concepts})
|
188
|
+
AND o.start_date < DATE('#{start_of_month}')
|
189
|
+
GROUP BY o.patient_id
|
190
|
+
)
|
191
|
+
AND pp.program_id = 1 #{%w[Military Civilian].include?(@occupation) ? 'AND' : ''} #{occupation_filter(occupation: @occupation, field_name: 'value', table_name: 'a', include_clause: false)}
|
192
|
+
GROUP BY pp.patient_id
|
193
|
+
SQL
|
194
|
+
end
|
195
|
+
|
196
|
+
def drop_tables
|
197
|
+
execute_query 'DROP TABLE IF EXISTS temp_initiated_on_art'
|
198
|
+
execute_query 'DROP TABLE IF EXISTS temp_initiated_on_tpt'
|
199
|
+
end
|
200
|
+
|
201
|
+
def create_indexes
|
202
|
+
execute_query 'CREATE INDEX idx_temp_initiated_on_art ON temp_initiated_on_art(patient_id)'
|
203
|
+
execute_query 'CREATE INDEX idx_temp_initiated_on_tpt ON temp_initiated_on_tpt(patient_id)'
|
204
|
+
end
|
205
|
+
|
206
|
+
def execute_query(query)
|
207
|
+
ActiveRecord::Base.connection.execute(query)
|
208
|
+
end
|
209
|
+
|
210
|
+
def arv_concepts
|
211
|
+
@arv_concepts ||= ::ConceptSet.where(concept_set: ::ConceptName.where(name: 'Antiretroviral drugs')
|
212
|
+
.select(:concept_id))
|
213
|
+
.collect(&:concept_id).join(',')
|
214
|
+
end
|
215
|
+
|
216
|
+
def tpt_concepts
|
217
|
+
@tpt_concepts ||= ::ConceptName.where(name: ['Rifapentine', 'Isoniazid', 'Isoniazid/Rifapentine'])
|
218
|
+
.collect(&:concept_id).join(',')
|
219
|
+
end
|
220
|
+
end
|
221
|
+
# rubocop:enable Metrics/ClassLength
|
222
|
+
end
|
223
|
+
end
|