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,494 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
##
|
|
4
|
+
# Family planning, action to take
|
|
5
|
+
# It should pull data for 6 month back e.g when the report is generated for the month of June,
|
|
6
|
+
# the report must pick clients who started TPT in the month of December
|
|
7
|
+
# it must be drillable
|
|
8
|
+
module MalawiHivProgramReports
|
|
9
|
+
module Clinic
|
|
10
|
+
class TptOutcome
|
|
11
|
+
include MalawiHivProgramReports::Utils::CommonSqlQueryUtils
|
|
12
|
+
include MalawiHivProgramReports::Utils::ModelUtils
|
|
13
|
+
include MalawiHivProgramReports::Pepfar::Utils
|
|
14
|
+
|
|
15
|
+
def initialize(start_date:, end_date:, **kwargs)
|
|
16
|
+
@start_date = start_date.to_date
|
|
17
|
+
@end_date = end_date.to_date
|
|
18
|
+
@tb_prev = Pepfar::TbPrev3.new(start_date: @start_date, end_date: @end_date)
|
|
19
|
+
@occupation = kwargs[:occupation]
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def find_report
|
|
23
|
+
report = init_report
|
|
24
|
+
@param = 'tpt_type'
|
|
25
|
+
load_patients_into_report report, process_tpt_clients
|
|
26
|
+
response = []
|
|
27
|
+
report.each do |key, value|
|
|
28
|
+
response << { age_group: key, tpt_type: '3HP', **value['3HP'] }
|
|
29
|
+
response << { age_group: key, tpt_type: '6H', **value['6H'] }
|
|
30
|
+
end
|
|
31
|
+
response
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def moh_report(report, clients, start_date, end_date)
|
|
35
|
+
@first_day_of_month = start_date.to_date
|
|
36
|
+
@last_day_of_month = end_date.to_date
|
|
37
|
+
tpt_clients = process_tpt_clients(clients)
|
|
38
|
+
@param = 'gender'
|
|
39
|
+
load_moh_patients_into_report report, tpt_clients
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
private
|
|
43
|
+
|
|
44
|
+
TPT_TYPES = %w[3HP 6H].freeze
|
|
45
|
+
|
|
46
|
+
def init_report
|
|
47
|
+
pepfar_age_groups.each_with_object({}) do |age_group, report|
|
|
48
|
+
next if age_group == 'Unknown'
|
|
49
|
+
|
|
50
|
+
report[age_group] = TPT_TYPES.each_with_object({}) do |tpt_type, tpt_report|
|
|
51
|
+
tpt_report[tpt_type] = {
|
|
52
|
+
started_tpt_new: [],
|
|
53
|
+
started_tpt_prev: [],
|
|
54
|
+
completed_tpt_new: [],
|
|
55
|
+
completed_tpt_prev: [],
|
|
56
|
+
not_completed_tpt: [],
|
|
57
|
+
died: [],
|
|
58
|
+
stopped: [],
|
|
59
|
+
defaulted: [],
|
|
60
|
+
transfer_out: [],
|
|
61
|
+
confirmed_tb: [],
|
|
62
|
+
pregnant: [],
|
|
63
|
+
breast_feeding: [],
|
|
64
|
+
skin_rash: [],
|
|
65
|
+
peripheral_neuropathy: [],
|
|
66
|
+
yellow_eyes: [],
|
|
67
|
+
nausea: [],
|
|
68
|
+
dizziness: []
|
|
69
|
+
}
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def patient_breast_feeding?(patient_id, last_tpt)
|
|
75
|
+
::Observation.where(person_id: patient_id, concept_id: breast_feeding_concept_id,
|
|
76
|
+
value_coded: yes_concept_id)
|
|
77
|
+
.where('DATE(obs_datetime) > DATE(?) AND DATE(obs_datetime) < DATE(?) + INTERVAL 1 DAY', last_tpt&.to_date, @end_date.to_date)
|
|
78
|
+
.exists?
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def patient_skin_rash?(patient_id, last_tpt)
|
|
82
|
+
::Observation.where(person_id: patient_id, concept_id: drug_induced_concept_id,
|
|
83
|
+
value_coded: skin_rash_concept_id)
|
|
84
|
+
.where('DATE(obs_datetime) > DATE(?) AND DATE(obs_datetime) < DATE(?) + INTERVAL 1 DAY', last_tpt&.to_date, @end_date.to_date)
|
|
85
|
+
.where("value_drug IN (#{tpt_actual_drugs})")
|
|
86
|
+
.exists?
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def patient_peripheral_neuropathy?(patient_id, last_tpt)
|
|
90
|
+
::Observation.where(person_id: patient_id, concept_id: drug_induced_concept_id,
|
|
91
|
+
value_coded: peripheral_neuropathy_concept_id)
|
|
92
|
+
.where('DATE(obs_datetime) > DATE(?) AND DATE(obs_datetime) < DATE(?) + INTERVAL 1 DAY', last_tpt&.to_date, @end_date.to_date)
|
|
93
|
+
.where("value_drug IN (#{tpt_actual_drugs})")
|
|
94
|
+
.exists?
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def patient_pregnant?(patient_id, last_tpt)
|
|
98
|
+
::Observation.where(person_id: patient_id, concept_id: pregnant_concept_id,
|
|
99
|
+
value_coded: yes_concept_id)
|
|
100
|
+
.where('DATE(obs_datetime) > DATE(?) AND DATE(obs_datetime) < DATE(?) + INTERVAL 1 DAY', last_tpt&.to_date, @end_date.to_date)
|
|
101
|
+
.exists?
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def patient_on_tb_treatment?(patient_id, last_tpt)
|
|
105
|
+
::Observation.where(person_id: patient_id, concept_id: tb_treatment_concept_id,
|
|
106
|
+
value_coded: yes_concept_id)
|
|
107
|
+
.where('DATE(obs_datetime) > DATE(?) AND DATE(obs_datetime) < DATE(?) + INTERVAL 1 DAY', last_tpt&.to_date, @end_date.to_date)
|
|
108
|
+
.exists?
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def patient_yellow_eyes?(patient_id, last_tpt)
|
|
112
|
+
::Observation.where(person_id: patient_id, concept_id: drug_induced_concept_id,
|
|
113
|
+
value_coded: yellow_eyes_concept_id)
|
|
114
|
+
.where('DATE(obs_datetime) > DATE(?) AND DATE(obs_datetime) < DATE(?) + INTERVAL 1 DAY', last_tpt&.to_date, @end_date.to_date)
|
|
115
|
+
.where("value_drug IN (#{tpt_actual_drugs})")
|
|
116
|
+
.exists?
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def patient_nausea?(patient_id, last_tpt)
|
|
120
|
+
::Observation.where(person_id: patient_id, concept_id: drug_induced_concept_id,
|
|
121
|
+
value_coded: nausea_concept_id)
|
|
122
|
+
.where('DATE(obs_datetime) > DATE(?) AND DATE(obs_datetime) < DATE(?) + INTERVAL 1 DAY', last_tpt&.to_date, @end_date.to_date)
|
|
123
|
+
.where("value_drug IN (#{tpt_actual_drugs})")
|
|
124
|
+
.exists?
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def patient_dizziness?(patient_id, last_tpt)
|
|
128
|
+
::Observation.where(person_id: patient_id, concept_id: drug_induced_concept_id,
|
|
129
|
+
value_coded: dizziness_concept_id)
|
|
130
|
+
.where('DATE(obs_datetime) > DATE(?) AND DATE(obs_datetime) < DATE(?) + INTERVAL 1 DAY', last_tpt&.to_date, @end_date.to_date)
|
|
131
|
+
.where("value_drug IN (#{tpt_actual_drugs})")
|
|
132
|
+
.exists?
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def pregnant_concept_id
|
|
136
|
+
@pregnant_concept_id ||= concept_name_to_id('Is patient pregnant?')
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def tb_treatment_concept_id
|
|
140
|
+
@tb_treatment_concept_id ||= concept_name_to_id('TB treatment')
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def yes_concept_id
|
|
144
|
+
@yes_concept_id ||= concept_name_to_id('Yes')
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def breast_feeding_concept_id
|
|
148
|
+
@breast_feeding_concept_id ||= concept_name_to_id('Breast feeding?')
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def skin_rash_concept_id
|
|
152
|
+
@skin_rash_concept_id ||= concept_name_to_id('Skin rash')
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
def peripheral_neuropathy_concept_id
|
|
156
|
+
@peripheral_neuropathy_concept_id ||= concept_name_to_id('Peripheral neuropathy')
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def yellow_eyes_concept_id
|
|
160
|
+
@yellow_eyes_concept_id ||= concept_name_to_id('Yellow eyes')
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def nausea_concept_id
|
|
164
|
+
@nausea_concept_id ||= concept_name_to_id('Nausea')
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def dizziness_concept_id
|
|
168
|
+
@dizziness_concept_id ||= concept_name_to_id('Dizziness')
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def drug_induced_concept_id
|
|
172
|
+
@drug_induced_concept_id ||= concept_name_to_id('Drug Induced')
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def tpt_clients
|
|
176
|
+
ActiveRecord::Base.connection.select_all <<~SQL
|
|
177
|
+
SELECT
|
|
178
|
+
pp.patient_id,
|
|
179
|
+
patient_outcome(p.person_id, DATE('#{@end_date}')) AS outcome,
|
|
180
|
+
p.gender,
|
|
181
|
+
p.birthdate,
|
|
182
|
+
disaggregated_age_group(p.birthdate, DATE('#{@end_date}')) AS age_group,
|
|
183
|
+
DATE(COALESCE(art_start_date_obs.value_datetime, MIN(art_order.start_date))) AS earliest_start_date,
|
|
184
|
+
GROUP_CONCAT(DISTINCT o.concept_id SEPARATOR ',') AS drug_concepts,
|
|
185
|
+
CASE
|
|
186
|
+
WHEN count(DISTINCT o.concept_id) > 1 THEN '3HP'
|
|
187
|
+
WHEN o.concept_id = 10565 THEN '3HP'
|
|
188
|
+
ELSE '6H'
|
|
189
|
+
END AS tpt_type
|
|
190
|
+
FROM patient_program pp
|
|
191
|
+
INNER JOIN patient_state ps ON ps.patient_program_id = pp.patient_program_id AND ps.voided = 0 AND ps.state = 7
|
|
192
|
+
INNER JOIN person p ON p.person_id = pp.patient_id AND p.voided = 0
|
|
193
|
+
INNER JOIN encounter e ON e.patient_id = pp.patient_id
|
|
194
|
+
AND e.encounter_type = 25 /* Treatment */
|
|
195
|
+
AND e.voided = 0
|
|
196
|
+
AND e.program_id = 1 /* HIV PROGRAM */
|
|
197
|
+
INNER JOIN orders o ON o.encounter_id = e.encounter_id
|
|
198
|
+
AND o.order_type_id = #{::OrderType.find_by_name('Drug order').id}
|
|
199
|
+
AND o.voided = 0
|
|
200
|
+
AND o.concept_id IN (#{tpt_drugs.to_sql})
|
|
201
|
+
INNER JOIN drug_order dor ON dor.order_id = o.order_id AND dor.quantity > 0
|
|
202
|
+
INNER JOIN (
|
|
203
|
+
SELECT e.patient_id
|
|
204
|
+
FROM encounter e
|
|
205
|
+
INNER JOIN orders o ON o.encounter_id = e.encounter_id
|
|
206
|
+
AND o.voided = 0
|
|
207
|
+
AND o.order_type_id = #{::OrderType.find_by_name('Drug order').id}
|
|
208
|
+
AND o.concept_id IN (#{tpt_drugs.to_sql})
|
|
209
|
+
AND DATE(o.start_date) BETWEEN #{first_day_of_month} AND DATE(#{last_day_of_month})
|
|
210
|
+
INNER JOIN drug_order dor ON dor.order_id = o.order_id AND dor.quantity > 0
|
|
211
|
+
WHERE e.encounter_type = 25 /* Treatment */
|
|
212
|
+
AND e.voided = 0
|
|
213
|
+
AND e.program_id = 1 /* HIV PROGRAM */
|
|
214
|
+
AND DATE(e.encounter_datetime) BETWEEN #{first_day_of_month} AND DATE(#{last_day_of_month})
|
|
215
|
+
GROUP BY e.patient_id
|
|
216
|
+
) clients_on_tpt ON clients_on_tpt.patient_id = e.patient_id
|
|
217
|
+
LEFT JOIN encounter AS clinic_registration_encounter
|
|
218
|
+
ON clinic_registration_encounter.encounter_type = (
|
|
219
|
+
SELECT encounter_type_id FROM encounter_type WHERE name = 'HIV CLINIC REGISTRATION' LIMIT 1
|
|
220
|
+
)
|
|
221
|
+
AND clinic_registration_encounter.patient_id = pp.patient_id
|
|
222
|
+
AND clinic_registration_encounter.program_id = pp.program_id
|
|
223
|
+
AND clinic_registration_encounter.encounter_datetime < DATE('#{@end_date}') + INTERVAL 1 DAY
|
|
224
|
+
AND clinic_registration_encounter.voided = 0
|
|
225
|
+
INNER JOIN orders AS art_order
|
|
226
|
+
ON art_order.patient_id = pp.patient_id
|
|
227
|
+
/* AND art_order.encounter_id = prescription_encounter.encounter_id */
|
|
228
|
+
AND art_order.concept_id IN (SELECT concept_id FROM concept_set WHERE concept_set = 1085)
|
|
229
|
+
AND art_order.start_date < DATE('#{@end_date}') + INTERVAL 1 DAY
|
|
230
|
+
AND art_order.order_type_id IN (SELECT order_type_id FROM order_type WHERE name = 'Drug order')
|
|
231
|
+
AND art_order.start_date >= DATE('1901-01-01')
|
|
232
|
+
AND art_order.voided = 0
|
|
233
|
+
LEFT JOIN obs AS art_start_date_obs
|
|
234
|
+
ON art_start_date_obs.concept_id = 2516
|
|
235
|
+
AND art_start_date_obs.person_id = pp.patient_id
|
|
236
|
+
AND art_start_date_obs.voided = 0
|
|
237
|
+
AND art_start_date_obs.obs_datetime < (DATE('#{@end_date}') + INTERVAL 1 DAY)
|
|
238
|
+
AND art_start_date_obs.encounter_id = clinic_registration_encounter.encounter_id
|
|
239
|
+
LEFT JOIN (#{current_occupation_query}) AS a ON a.person_id = pp.patient_id
|
|
240
|
+
WHERE pp.program_id = 1 /* HIV PROGRAM */
|
|
241
|
+
AND pp.patient_id NOT IN (
|
|
242
|
+
/* External consultations */
|
|
243
|
+
SELECT DISTINCT registration_encounter.patient_id
|
|
244
|
+
FROM patient_program
|
|
245
|
+
INNER JOIN program ON program.name = 'HIV PROGRAM'
|
|
246
|
+
INNER JOIN encounter AS registration_encounter
|
|
247
|
+
ON registration_encounter.patient_id = patient_program.patient_id
|
|
248
|
+
AND registration_encounter.program_id = patient_program.program_id
|
|
249
|
+
AND registration_encounter.encounter_datetime < DATE('#{@end_date}') + INTERVAL 1 DAY
|
|
250
|
+
AND registration_encounter.voided = 0
|
|
251
|
+
INNER JOIN (
|
|
252
|
+
SELECT MAX(encounter.encounter_datetime) AS encounter_datetime, encounter.patient_id
|
|
253
|
+
FROM encounter
|
|
254
|
+
INNER JOIN encounter_type
|
|
255
|
+
ON encounter_type.encounter_type_id = encounter.encounter_type
|
|
256
|
+
AND encounter_type.name = 'Registration'
|
|
257
|
+
INNER JOIN program
|
|
258
|
+
ON program.program_id = encounter.program_id
|
|
259
|
+
AND program.name = 'HIV PROGRAM'
|
|
260
|
+
WHERE encounter.encounter_datetime < DATE('#{@end_date}') AND encounter.voided = 0
|
|
261
|
+
GROUP BY encounter.patient_id
|
|
262
|
+
) AS max_registration_encounter
|
|
263
|
+
ON max_registration_encounter.patient_id = registration_encounter.patient_id
|
|
264
|
+
AND max_registration_encounter.encounter_datetime = registration_encounter.encounter_datetime
|
|
265
|
+
INNER JOIN obs AS patient_type_obs
|
|
266
|
+
ON patient_type_obs.encounter_id = registration_encounter.encounter_id
|
|
267
|
+
AND patient_type_obs.concept_id IN (SELECT concept_id FROM concept_name WHERE name = 'Type of patient' AND voided = 0)
|
|
268
|
+
AND patient_type_obs.value_coded IN (SELECT concept_id FROM concept_name WHERE name IN ('Drug refill', 'External consultation') AND voided = 0)
|
|
269
|
+
AND patient_type_obs.voided = 0
|
|
270
|
+
WHERE patient_program.voided = 0
|
|
271
|
+
)
|
|
272
|
+
AND pp.voided = 0 #{%w[Military Civilian].include?(@occupation) ? 'AND' : ''} #{occupation_filter(occupation: @occupation, field_name: 'value', table_name: 'a', include_clause: false)}
|
|
273
|
+
AND DATE(o.start_date)<= DATE('#{@end_date}')
|
|
274
|
+
GROUP BY pp.patient_id
|
|
275
|
+
SQL
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
def process_tpt_clients(patients = nil)
|
|
279
|
+
clients = []
|
|
280
|
+
(patients || tpt_clients || []).each do |client|
|
|
281
|
+
result = @tb_prev.fetch_individual_report(client['patient_id'])
|
|
282
|
+
next if result.blank?
|
|
283
|
+
next if result['tpt_initiation_date'].to_date < first_day_of_month.to_date
|
|
284
|
+
|
|
285
|
+
client['start_date'] = result['tpt_initiation_date']
|
|
286
|
+
client['last_dispense_date'] = result['last_dispensed_date']
|
|
287
|
+
client['total_pills_taken'] = result['total_pills_taken']
|
|
288
|
+
client['total_days_on_medication'] = result['total_days_on_medication']
|
|
289
|
+
client['tpt_type'] = @tb_prev.patient_on_3hp?(result) ? '3HP' : '6H'
|
|
290
|
+
client['drug_concepts'] = result['drug_concepts']
|
|
291
|
+
|
|
292
|
+
clients << client
|
|
293
|
+
end
|
|
294
|
+
clients
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
# def tpt_clients
|
|
298
|
+
# ActiveRecord::Base.connection.select_all <<~SQL
|
|
299
|
+
# SELECT
|
|
300
|
+
# p.person_id AS patient_id,
|
|
301
|
+
# DATE(min(o.start_date)) AS start_date,
|
|
302
|
+
# DATE(max(o.start_date)) AS last_dispense_date,
|
|
303
|
+
# patient_outcome(p.person_id, DATE('#{@end_date}')) AS outcome,
|
|
304
|
+
# SUM(d.quantity) AS total_pills_taken,
|
|
305
|
+
# SUM(DATEDIFF(o.auto_expire_date, o.start_date)) AS total_days_on_medication,
|
|
306
|
+
# p.gender,
|
|
307
|
+
# p.birthdate,
|
|
308
|
+
# disaggregated_age_group(p.birthdate, DATE('#{@end_date}')) AS age_group,
|
|
309
|
+
# GROUP_CONCAT(DISTINCT o.concept_id SEPARATOR ',') AS drug_concepts,
|
|
310
|
+
# CASE
|
|
311
|
+
# WHEN count(DISTINCT o.concept_id) > 1 THEN '3HP'
|
|
312
|
+
# WHEN o.concept_id = 10565 THEN '3HP'
|
|
313
|
+
# ELSE '6H'
|
|
314
|
+
# END AS tpt_type
|
|
315
|
+
# FROM person p
|
|
316
|
+
# INNER JOIN encounter e
|
|
317
|
+
# ON e.patient_id = p.person_id
|
|
318
|
+
# AND e.encounter_type = #{::EncounterType.find_by_name('Treatment').id}
|
|
319
|
+
# AND e.voided = 0
|
|
320
|
+
# AND e.program_id = #{::Program.find_by_name('HIV PROGRAM').id}
|
|
321
|
+
# AND e.encounter_datetime >= DATE('#{@start_date}') - INTERVAL 6 MONTH
|
|
322
|
+
# AND e.encounter_datetime <= DATE('#{@start_date}')
|
|
323
|
+
# INNER JOIN orders o
|
|
324
|
+
# ON o.encounter_id = e.encounter_id
|
|
325
|
+
# AND o.concept_id IN (#{tpt_drugs.to_sql})
|
|
326
|
+
# AND o.start_date >= DATE('#{@start_date}') - INTERVAL 6 MONTH
|
|
327
|
+
# AND o.start_date <= DATE('#{@end_date}')
|
|
328
|
+
# AND o.voided = 0
|
|
329
|
+
# AND o.order_type_id = #{::OrderType.find_by_name('Drug order').id}
|
|
330
|
+
# INNER JOIN drug_order d ON d.order_id = o.order_id AND d.quantity > 0
|
|
331
|
+
# WHERE p.voided = 0
|
|
332
|
+
# AND p.person_id NOT IN (
|
|
333
|
+
# SELECT p.person_id
|
|
334
|
+
# FROM person p
|
|
335
|
+
# INNER JOIN encounter e
|
|
336
|
+
# ON e.patient_id = p.person_id
|
|
337
|
+
# AND e.encounter_type = #{::EncounterType.find_by_name('Treatment').id}
|
|
338
|
+
# AND e.voided = 0
|
|
339
|
+
# AND e.program_id = #{::Program.find_by_name('HIV PROGRAM').id}
|
|
340
|
+
# INNER JOIN orders o
|
|
341
|
+
# ON o.patient_id = e.patient_id
|
|
342
|
+
# AND o.concept_id IN (#{tpt_drugs.to_sql})
|
|
343
|
+
# AND o.voided = 0
|
|
344
|
+
# AND o.order_type_id = #{::OrderType.find_by_name('Drug order').id}
|
|
345
|
+
# INNER JOIN drug_order d ON d.order_id = o.order_id AND d.quantity > 0
|
|
346
|
+
# WHERE p.voided = 0
|
|
347
|
+
# AND e.encounter_datetime < '#{@start_date - 6.months}'
|
|
348
|
+
# AND e.encounter_datetime >= '#{@start_date - 15.months}'
|
|
349
|
+
# )
|
|
350
|
+
# AND p.person_id NOT IN (
|
|
351
|
+
# /* External consultations */
|
|
352
|
+
# SELECT DISTINCT registration_encounter.patient_id
|
|
353
|
+
# FROM patient_program
|
|
354
|
+
# INNER JOIN program ON program.name = 'HIV PROGRAM'
|
|
355
|
+
# INNER JOIN encounter AS registration_encounter
|
|
356
|
+
# ON registration_encounter.patient_id = patient_program.patient_id
|
|
357
|
+
# AND registration_encounter.program_id = patient_program.program_id
|
|
358
|
+
# AND registration_encounter.encounter_datetime < DATE('#{@end_date}') + INTERVAL 1 DAY
|
|
359
|
+
# AND registration_encounter.voided = 0
|
|
360
|
+
# INNER JOIN (
|
|
361
|
+
# SELECT MAX(encounter.encounter_datetime) AS encounter_datetime, encounter.patient_id
|
|
362
|
+
# FROM encounter
|
|
363
|
+
# INNER JOIN encounter_type
|
|
364
|
+
# ON encounter_type.encounter_type_id = encounter.encounter_type
|
|
365
|
+
# AND encounter_type.name = 'Registration'
|
|
366
|
+
# INNER JOIN program
|
|
367
|
+
# ON program.program_id = encounter.program_id
|
|
368
|
+
# AND program.name = 'HIV PROGRAM'
|
|
369
|
+
# WHERE encounter.encounter_datetime < DATE('#{@end_date}') AND encounter.voided = 0
|
|
370
|
+
# GROUP BY encounter.patient_id
|
|
371
|
+
# ) AS max_registration_encounter
|
|
372
|
+
# ON max_registration_encounter.patient_id = registration_encounter.patient_id
|
|
373
|
+
# AND max_registration_encounter.encounter_datetime = registration_encounter.encounter_datetime
|
|
374
|
+
# INNER JOIN obs AS patient_type_obs
|
|
375
|
+
# ON patient_type_obs.encounter_id = registration_encounter.encounter_id
|
|
376
|
+
# AND patient_type_obs.concept_id IN (SELECT concept_id FROM concept_name WHERE name = 'Type of patient' AND voided = 0)
|
|
377
|
+
# AND patient_type_obs.value_coded IN (SELECT concept_id FROM concept_name WHERE name IN ('Drug refill', 'External consultation') AND voided = 0)
|
|
378
|
+
# AND patient_type_obs.voided = 0
|
|
379
|
+
# WHERE patient_program.voided = 0
|
|
380
|
+
# )
|
|
381
|
+
# GROUP BY p.person_id
|
|
382
|
+
# SQL
|
|
383
|
+
# end
|
|
384
|
+
|
|
385
|
+
def load_patients_into_report(report, patients)
|
|
386
|
+
patients.each do |patient|
|
|
387
|
+
new_on_art = patient_new_on_art?(patient)
|
|
388
|
+
common_reponse(patient)
|
|
389
|
+
if new_on_art
|
|
390
|
+
report[patient['age_group']][patient[@param]][:started_tpt_new] << @common_response
|
|
391
|
+
else
|
|
392
|
+
report[patient['age_group']][patient[@param]][:started_tpt_prev] << @common_response
|
|
393
|
+
end
|
|
394
|
+
|
|
395
|
+
if patient_completed_tpt?(patient, patient['tpt_type'])
|
|
396
|
+
report[patient['age_group']][patient[@param]][:completed_tpt_new] << @common_response if new_on_art
|
|
397
|
+
report[patient['age_group']][patient[@param]][:completed_tpt_prev] << @common_response unless new_on_art
|
|
398
|
+
else
|
|
399
|
+
report[patient['age_group']][patient[@param]][:not_completed_tpt] << @common_response
|
|
400
|
+
process_outcomes report, patient
|
|
401
|
+
end
|
|
402
|
+
end
|
|
403
|
+
end
|
|
404
|
+
|
|
405
|
+
def load_moh_patients_into_report(report, patients)
|
|
406
|
+
patients.each do |patient|
|
|
407
|
+
common_reponse(patient)
|
|
408
|
+
report[patient['age_group']][patient[@param]][:started_tpt] << @common_response
|
|
409
|
+
if patient_completed_tpt?(patient, patient['tpt_type'])
|
|
410
|
+
report[patient['age_group']][patient[@param]][:completed_tpt] << @common_response
|
|
411
|
+
else
|
|
412
|
+
report[patient['age_group']][patient[@param]][:not_completed_tpt] << @common_response
|
|
413
|
+
process_outcomes report, patient
|
|
414
|
+
end
|
|
415
|
+
end
|
|
416
|
+
end
|
|
417
|
+
|
|
418
|
+
def process_outcomes(report, patient)
|
|
419
|
+
process_patient_conditions report, patient
|
|
420
|
+
return if @condition
|
|
421
|
+
|
|
422
|
+
case patient['outcome']
|
|
423
|
+
when 'Patient died'
|
|
424
|
+
report[patient['age_group']][patient[@param]][:died] << @common_response
|
|
425
|
+
when 'Patient transferred out'
|
|
426
|
+
report[patient['age_group']][patient[@param]][:transfer_out] << @common_response
|
|
427
|
+
when 'Treatment stopped'
|
|
428
|
+
report[patient['age_group']][patient[@param]][:stopped] << @common_response
|
|
429
|
+
when 'Defaulted'
|
|
430
|
+
report[patient['age_group']][patient[@param]][:defaulted] << @common_response
|
|
431
|
+
else
|
|
432
|
+
process_patient_conditions report, patient
|
|
433
|
+
end
|
|
434
|
+
end
|
|
435
|
+
|
|
436
|
+
def process_patient_conditions(report, patient)
|
|
437
|
+
if patient_on_tb_treatment?(patient['patient_id'], patient['last_dispense_date'])
|
|
438
|
+
report[patient['age_group']][patient[@param]][:confirmed_tb] << @common_response
|
|
439
|
+
elsif patient['gender'] == 'F' && patient_pregnant?(patient['patient_id'], patient['last_dispense_date'])
|
|
440
|
+
report[patient['age_group']][patient[@param]][:pregnant] << @common_response
|
|
441
|
+
@condition = true
|
|
442
|
+
return
|
|
443
|
+
elsif patient['gender'] == 'F' && patient_breast_feeding?(patient['patient_id'], patient['last_dispense_date'])
|
|
444
|
+
report[patient['age_group']][patient[@param]][:breast_feeding] << @common_response
|
|
445
|
+
@condition = true
|
|
446
|
+
return
|
|
447
|
+
end
|
|
448
|
+
|
|
449
|
+
process_malawi_art_conditions report, patient
|
|
450
|
+
end
|
|
451
|
+
|
|
452
|
+
def process_malawi_art_conditions(report, patient)
|
|
453
|
+
%i[skin_rash nausea peripheral_neuropathy dizziness yellow_eyes].each do |condition|
|
|
454
|
+
method_name = :"patient_#{condition}?"
|
|
455
|
+
next unless send(method_name, patient['patient_id'], patient['last_dispense_date'])
|
|
456
|
+
|
|
457
|
+
report[patient['age_group']][patient[@param]][condition] << @common_response
|
|
458
|
+
@condition = true
|
|
459
|
+
end
|
|
460
|
+
end
|
|
461
|
+
|
|
462
|
+
def patient_new_on_art?(patient)
|
|
463
|
+
init_date = patient['earliest_start_date'].to_date
|
|
464
|
+
start_date = patient['start_date'].to_date
|
|
465
|
+
|
|
466
|
+
init_date + 6.months > start_date
|
|
467
|
+
end
|
|
468
|
+
|
|
469
|
+
def common_reponse(patient)
|
|
470
|
+
@common_response = if @param == 'tpt_type'
|
|
471
|
+
{ patient_id: patient['patient_id'], gender: patient['gender'] }
|
|
472
|
+
else
|
|
473
|
+
patient['patient_id']
|
|
474
|
+
end
|
|
475
|
+
end
|
|
476
|
+
|
|
477
|
+
def tpt_drugs
|
|
478
|
+
::ConceptName.where(name: ['INH', 'Isoniazid/Rifapentine', 'Rifapentine']).select(:concept_id)
|
|
479
|
+
end
|
|
480
|
+
|
|
481
|
+
def tpt_actual_drugs
|
|
482
|
+
@tpt_actual_drugs ||= ::Drug.where(concept_id: tpt_drugs.map(&:concept_id)).select(:drug_id).to_sql
|
|
483
|
+
end
|
|
484
|
+
|
|
485
|
+
def first_day_of_month
|
|
486
|
+
@first_day_of_month ||= ActiveRecord::Base.connection.quote((@start_date - 6.month).beginning_of_month)
|
|
487
|
+
end
|
|
488
|
+
|
|
489
|
+
def last_day_of_month
|
|
490
|
+
@last_day_of_month ||= ActiveRecord::Base.connection.quote((@start_date - 6.month).end_of_month)
|
|
491
|
+
end
|
|
492
|
+
end
|
|
493
|
+
end
|
|
494
|
+
end
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# This is MOH client returned to care report
|
|
4
|
+
module MalawiHivProgramReports
|
|
5
|
+
module Clinic
|
|
6
|
+
class TxRtt
|
|
7
|
+
include MalawiHivProgramReports::Utils::CommonSqlQueryUtils
|
|
8
|
+
|
|
9
|
+
def initialize(start_date:, end_date:, **kwargs)
|
|
10
|
+
@start_date = ActiveRecord::Base.connection.quote(start_date)
|
|
11
|
+
@end_date = ActiveRecord::Base.connection.quote(end_date)
|
|
12
|
+
@occupation = kwargs[:occupation]
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def find_report
|
|
16
|
+
tx_rtt.each_with_object({}) do |patient, report|
|
|
17
|
+
age_group = report[patient['age_group']] || { 'M' => [], 'F' => [], 'Unknown' => [] }
|
|
18
|
+
age_group[patient['gender']&.first&.upcase || 'Unknown'] << { patient_id: patient['patient_id'],
|
|
19
|
+
months: patient['months'] }
|
|
20
|
+
|
|
21
|
+
report[patient['age_group']] = age_group
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
|
|
27
|
+
def tx_rtt
|
|
28
|
+
ActiveRecord::Base.connection.select_all <<~SQL
|
|
29
|
+
SELECT patient_program.patient_id,
|
|
30
|
+
disaggregated_age_group(person.birthdate, #{@end_date}) AS age_group,
|
|
31
|
+
person.gender,
|
|
32
|
+
IF(
|
|
33
|
+
patient_state_at_start_of_quarter.state = 6, 'Treatment stopped',
|
|
34
|
+
IF(
|
|
35
|
+
patient_state_at_start_of_quarter.state = 12, 'Defaulted',
|
|
36
|
+
patient_outcome(patient_program.patient_id, (DATE(#{@start_date}) - INTERVAL 1 DAY) )
|
|
37
|
+
)
|
|
38
|
+
) AS initial_outcome,
|
|
39
|
+
IF(
|
|
40
|
+
patient_state_at_start_of_quarter.state = 6,
|
|
41
|
+
patient_state_at_start_of_quarter.start_date,
|
|
42
|
+
IF(
|
|
43
|
+
patient_state_at_start_of_quarter.state = 12,
|
|
44
|
+
patient_state_at_start_of_quarter.start_date,
|
|
45
|
+
current_defaulter_date(patient_program.patient_id, (DATE(#{@start_date}) - INTERVAL 1 DAY) ))) AS initial_outcome_date,
|
|
46
|
+
IF(
|
|
47
|
+
patients_with_orders_at_end_of_quarter.patient_id IS NOT NULL, 'On antiretrovirals',
|
|
48
|
+
IF(
|
|
49
|
+
current_defaulter(patient_program.patient_id, #{@end_date}) = 0,
|
|
50
|
+
'On antiretrovirals','Defaulted'
|
|
51
|
+
)
|
|
52
|
+
) AS final_outcome,
|
|
53
|
+
TIMESTAMPDIFF(MONTH, IF(
|
|
54
|
+
patient_state_at_start_of_quarter.state = 6,
|
|
55
|
+
patient_state_at_start_of_quarter.start_date,
|
|
56
|
+
IF(
|
|
57
|
+
patient_state_at_start_of_quarter.state = 12,
|
|
58
|
+
patient_state_at_start_of_quarter.start_date,
|
|
59
|
+
current_defaulter_date(
|
|
60
|
+
patient_program.patient_id,
|
|
61
|
+
(DATE(#{@start_date}) - INTERVAL 1 DAY)
|
|
62
|
+
)
|
|
63
|
+
)
|
|
64
|
+
), patients_who_received_art_in_quarter.start_date) AS months
|
|
65
|
+
FROM patient_program
|
|
66
|
+
INNER JOIN person ON person.person_id = patient_program.patient_id
|
|
67
|
+
/* Select patients that were on treatment before start of reporting period */
|
|
68
|
+
INNER JOIN patient_state AS patient_ever_on_treatment
|
|
69
|
+
ON patient_ever_on_treatment.patient_program_id = patient_program.patient_program_id
|
|
70
|
+
AND patient_ever_on_treatment.state = 7
|
|
71
|
+
AND patient_ever_on_treatment.start_date < DATE(#{@start_date})
|
|
72
|
+
AND patient_ever_on_treatment.voided = 0
|
|
73
|
+
/* Get patient's state at the start of the quarter. */
|
|
74
|
+
INNER JOIN (
|
|
75
|
+
SELECT patient_program_id, MAX(patient_state.date_created) AS date_created
|
|
76
|
+
FROM patient_state
|
|
77
|
+
INNER JOIN patient_program USING (patient_program_id)
|
|
78
|
+
WHERE patient_state.voided = 0
|
|
79
|
+
AND patient_program.voided = 0
|
|
80
|
+
AND patient_program.program_id = 1
|
|
81
|
+
AND patient_state.start_date < DATE(#{@start_date}) + INTERVAL 1 DAY
|
|
82
|
+
GROUP BY patient_program_id
|
|
83
|
+
) AS date_of_last_patient_state_before_quarter
|
|
84
|
+
ON date_of_last_patient_state_before_quarter.patient_program_id = patient_program.patient_program_id
|
|
85
|
+
LEFT JOIN patient_state AS patient_state_at_start_of_quarter
|
|
86
|
+
ON patient_state_at_start_of_quarter.patient_program_id = date_of_last_patient_state_before_quarter.patient_program_id
|
|
87
|
+
AND patient_state_at_start_of_quarter.date_created = date_of_last_patient_state_before_quarter.date_created
|
|
88
|
+
AND patient_state_at_start_of_quarter.state IN (6, 12) /* 2: TO, 6: Tx Stopped, 12: Defaulted */
|
|
89
|
+
/* Select patients who received ART within the reporting period. */
|
|
90
|
+
INNER JOIN (
|
|
91
|
+
SELECT DISTINCT encounter.patient_id, orders.start_date
|
|
92
|
+
FROM encounter
|
|
93
|
+
INNER JOIN orders
|
|
94
|
+
ON orders.encounter_id = encounter.encounter_id
|
|
95
|
+
AND DATE(orders.start_date) BETWEEN DATE(#{@start_date}) AND DATE(#{@end_date})
|
|
96
|
+
AND orders.voided = 0
|
|
97
|
+
INNER JOIN drug_order
|
|
98
|
+
ON drug_order.order_id = orders.order_id
|
|
99
|
+
AND drug_order.quantity > 0
|
|
100
|
+
AND drug_order.drug_inventory_id IN (SELECT DISTINCT drug_id FROM arv_drug)
|
|
101
|
+
WHERE encounter.voided = 0
|
|
102
|
+
AND encounter.program_id = 1
|
|
103
|
+
AND DATE(encounter.encounter_datetime) BETWEEN DATE(#{@start_date}) AND DATE(#{@end_date})
|
|
104
|
+
) AS patients_who_received_art_in_quarter
|
|
105
|
+
ON patients_who_received_art_in_quarter.patient_id = patient_program.patient_id
|
|
106
|
+
/* Ensure that patients are on ART at the end of the quarter */
|
|
107
|
+
INNER JOIN (
|
|
108
|
+
SELECT patient_program_id, MAX(patient_state.date_created) AS date_created
|
|
109
|
+
FROM patient_state
|
|
110
|
+
INNER JOIN patient_program USING (patient_program_id)
|
|
111
|
+
WHERE patient_state.voided = 0
|
|
112
|
+
AND patient_program.voided = 0
|
|
113
|
+
AND patient_program.program_id = 1
|
|
114
|
+
AND patient_state.start_date < DATE(#{@end_date}) + INTERVAL 1 DAY
|
|
115
|
+
GROUP BY patient_program_id
|
|
116
|
+
) AS date_of_last_patient_state_in_quarter
|
|
117
|
+
ON date_of_last_patient_state_in_quarter.patient_program_id = patient_program.patient_program_id
|
|
118
|
+
|
|
119
|
+
/*Not sure why Walter had this section in but I believe its not neccessary*/
|
|
120
|
+
/*INNER JOIN patient_state AS patient_state_at_end_of_quarter
|
|
121
|
+
ON patient_state_at_end_of_quarter.patient_program_id = patient_program.patient_program_id
|
|
122
|
+
AND patient_state_at_end_of_quarter.date_created = date_of_last_patient_state_before_quarter.date_created
|
|
123
|
+
AND patient_state_at_end_of_quarter.state = 7*/
|
|
124
|
+
|
|
125
|
+
/* Select patient who had orders in the last 30 days of the reporting period.
|
|
126
|
+
This is to be used as a quick filter for patients who are definitely
|
|
127
|
+
'On ART' by the end of the reporting period. The rest will be filtered by
|
|
128
|
+
the current_defaulter function. */
|
|
129
|
+
LEFT JOIN (
|
|
130
|
+
SELECT DISTINCT encounter.patient_id
|
|
131
|
+
FROM encounter
|
|
132
|
+
INNER JOIN orders
|
|
133
|
+
ON orders.encounter_id = encounter.encounter_id
|
|
134
|
+
AND orders.voided = 0
|
|
135
|
+
AND DATE(orders.start_date) BETWEEN DATE(#{@start_date}) AND DATE(#{@end_date})
|
|
136
|
+
AND orders.auto_expire_date >= (DATE(#{@end_date}) - INTERVAL 60 DAY)
|
|
137
|
+
INNER JOIN drug_order
|
|
138
|
+
ON drug_order.order_id = orders.order_id
|
|
139
|
+
AND drug_order.quantity > 0
|
|
140
|
+
AND drug_order.drug_inventory_id IN (SELECT DISTINCT drug_id FROM arv_drug)
|
|
141
|
+
WHERE encounter.program_id = 1
|
|
142
|
+
AND DATE(encounter.encounter_datetime) BETWEEN DATE(#{@start_date}) AND DATE(#{@end_date})
|
|
143
|
+
AND encounter.voided = 0
|
|
144
|
+
) AS patients_with_orders_at_end_of_quarter
|
|
145
|
+
ON patients_with_orders_at_end_of_quarter.patient_id = patient_program.patient_id
|
|
146
|
+
LEFT JOIN (#{current_occupation_query}) AS a ON a.person_id = patient_program.patient_id
|
|
147
|
+
WHERE patient_program.program_id = 1
|
|
148
|
+
/* Ensure that the patients retrieved, did not receive ART within 28 days
|
|
149
|
+
before the start of the reporting period */
|
|
150
|
+
AND patient_program.patient_id NOT IN (
|
|
151
|
+
SELECT DISTINCT orders.patient_id
|
|
152
|
+
FROM orders
|
|
153
|
+
INNER JOIN drug_order USING (order_id)
|
|
154
|
+
INNER JOIN arv_drug ON arv_drug.drug_id = drug_inventory_id
|
|
155
|
+
INNER JOIN patient_program
|
|
156
|
+
ON patient_program.patient_id = orders.patient_id
|
|
157
|
+
AND patient_program.program_id = 1
|
|
158
|
+
WHERE ((DATE(orders.start_date) BETWEEN (DATE(#{@start_date}) - INTERVAL 60 DAY) AND DATE(#{@start_date}))
|
|
159
|
+
OR (DATE(orders.auto_expire_date )BETWEEN (DATE(#{@start_date}) - INTERVAL 60 DAY) AND DATE(#{@start_date})))
|
|
160
|
+
AND orders.voided = 0
|
|
161
|
+
) #{%w[Military Civilian].include?(@occupation) ? 'AND' : ''} #{occupation_filter(occupation: @occupation, field_name: 'value', table_name: 'a', include_clause: false)}
|
|
162
|
+
GROUP BY patient_program.patient_id
|
|
163
|
+
HAVING initial_outcome IN ('Defaulted', 'Treatment stopped')
|
|
164
|
+
AND final_outcome = 'On antiretrovirals';
|
|
165
|
+
SQL
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
end
|