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