Module: MalawiHivProgramReports::Pepfar::Utils

Overview

Common utilities for Pepfar reports

Constant Summary collapse

COHORT_REGIMENS =
%w[
  0P 2P 4PP 4PA 9PP 9PA 11PP 11PA 12PP 12PA 14PP 14PA 15PP 15PA 16P 17PP 17PA
  4A 5A 6A 7A 8A 9A 10A 11A 12A 13A 14A 15A 16A 17A
].freeze
FULL_6H_COURSE_PILLS =
146
FULL_3HP_COURSE_DAYS =
12.days

Instance Method Summary collapse

Instance Method Details

#drug_refills_and_external_consultation_listObject

this just gives all clients who are truly external or drug refill rubocop:disable Metrics/MethodLength rubocop:disable Metrics/AbcSize



93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'app/services/malawi_hiv_program_reports/pepfar/utils.rb', line 93

def drug_refills_and_external_consultation_list
  to_remove = [0]

  type_of_patient_concept = ::ConceptName.find_by_name('Type of patient').concept_id
  new_patient_concept = ::ConceptName.find_by_name('New patient').concept_id
  drug_refill_concept = ::ConceptName.find_by_name('Drug refill').concept_id
  external_concept = ::ConceptName.find_by_name('External consultation').concept_id
  hiv_clinic_registration_id = ::EncounterType.find_by_name('HIV CLINIC REGISTRATION').encounter_type_id

  res = ActiveRecord::Base.connection.select_all <<~SQL
    SELECT p.person_id patient_id
    FROM person #{current_partition} p
    INNER JOIN patient_program #{current_partition} pp ON pp.patient_id = p.person_id AND pp.program_id = #{::Program.find_by_name('HIV PROGRAM').id} AND pp.voided = 0
    INNER JOIN patient_state #{current_partition} ps ON ps.patient_program_id = pp.patient_program_id AND ps.state = 7 AND ps.start_date IS NOT NULL
    LEFT JOIN encounter #{current_partition} as hiv_registration ON hiv_registration.patient_id = p.person_id AND hiv_registration.encounter_datetime < DATE(#{ActiveRecord::Base.connection.quote(end_date)}) AND hiv_registration.encounter_type = #{hiv_clinic_registration_id} AND hiv_registration.voided = 0
    LEFT JOIN (
      SELECT * FROM obs #{current_partition} WHERE concept_id = #{type_of_patient_concept} AND voided = 0 AND value_coded = #{new_patient_concept} AND obs_datetime < #{interval_manager(date: end_date, value: 1, interval: 'DAY', operator: '+')}
    ) AS new_patient ON p.person_id = new_patient.person_id
    LEFT JOIN (
      SELECT * FROM obs #{current_partition} WHERE concept_id = #{type_of_patient_concept} AND voided = 0 AND value_coded = #{drug_refill_concept} AND obs_datetime < #{interval_manager(date: end_date, value: 1, interval: 'DAY', operator: '+')}
      ) AS refill ON p.person_id = refill.person_id
    LEFT JOIN (
      SELECT * FROM obs #{current_partition} WHERE concept_id = #{type_of_patient_concept} AND voided = 0 AND value_coded = #{external_concept} AND obs_datetime < #{interval_manager(date: end_date, value: 1, interval: 'DAY', operator: '+')}
      ) AS external ON p.person_id = external.person_id
    WHERE (refill.value_coded IS NOT NULL OR external.value_coded IS NOT NULL)
    AND NOT (hiv_registration.encounter_id IS NOT NULL OR new_patient.value_coded IS NOT NULL)
    GROUP BY p.person_id
    ORDER BY hiv_registration.encounter_datetime DESC, refill.obs_datetime DESC, external.obs_datetime DESC
  SQL
  res.each do |record|
    to_remove << record['patient_id'].to_i
  end
  to_remove.join(',')
end

#isoniazid_rifapentine_conceptObject



134
135
136
# File 'app/services/malawi_hiv_program_reports/pepfar/utils.rb', line 134

def isoniazid_rifapentine_concept
  @isoniazid_rifapentine_concept ||= ::ConceptName.find_by!(name: 'Isoniazid/Rifapentine')
end

#patient_completed_tpt?(patient, tpt) ⇒ Boolean

Returns whether a patient completed their course of TPT

Returns:

  • (Boolean)


77
78
79
80
81
82
83
84
85
86
87
88
# File 'app/services/malawi_hiv_program_reports/pepfar/utils.rb', line 77

def patient_completed_tpt?(patient, tpt)
  if tpt == '3HP'
    # return true if patient['total_days_on_medication'].to_i >= 83 # 3 months
    return true if patient['months_on_tpt'].to_i >= 3

    divider = patient['drug_concepts'].split(',').length > 1 ? 14.0 : 7.0
    days_on_medication = (patient['total_days_on_medication'] / divider).round
    days_on_medication.days >= FULL_3HP_COURSE_DAYS
  else
    patient['total_days_on_medication'].to_i >= FULL_6H_COURSE_PILLS
  end
end

#patient_on_3hp?(patient) ⇒ Boolean

Returns:

  • (Boolean)


138
139
140
141
# File 'app/services/malawi_hiv_program_reports/pepfar/utils.rb', line 138

def patient_on_3hp?(patient)
  drug_concepts = patient['drug_concepts'].split(',').collect(&:to_i)
  drug_concepts.intersect?([rifapentine_concept.concept_id, isoniazid_rifapentine_concept&.concept_id])
end

#patient_on_tb_treatment?(patient_id) ⇒ Boolean

Returns:

  • (Boolean)


143
144
145
146
147
148
# File 'app/services/malawi_hiv_program_reports/pepfar/utils.rb', line 143

def patient_on_tb_treatment?(patient_id)
  ::Observation.where(person_id: patient_id, concept_id: ::ConceptName.find_by_name('TB status').concept_id,
                      value_coded: ::ConceptName.find_by_name('Confirmed TB on treatment').concept_id)
               .where("obs_datetime < #{interval_manager(date: end_date, value: 1, interval: 'DAY',
                                                         operator: '+')}").exists?
end

#pepfar_age_groupsObject

An array of all groups as required by Pepfar.



10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# File 'app/services/malawi_hiv_program_reports/pepfar/utils.rb', line 10

def pepfar_age_groups
  @pepfar_age_groups ||= [
    'Unknown',
    '<1 year',
    '1-4 years', '5-9 years',
    '10-14 years', '15-19 years',
    '20-24 years',
    '25-29 years', '30-34 years',
    '35-39 years', '40-44 years',
    '45-49 years', '50-54 years',
    '55-59 years', '60-64 years',
    '65-69 years', '70-74 years',
    '75-79 years', '80-84 years',
    '85-89 years',
    '90 plus years'
  ].freeze
end

#pepfar_patient_drilldown_information(patients, current_date) ⇒ Object

Returns the drilldown information for all specified patients (ie patient_ids)

Information returned for a patient is as follows:

* patient_id
* arv_number or filing_number
* age_group
* birthdate
* gender

Raises:

  • (::ArgumentError)


42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'app/services/malawi_hiv_program_reports/pepfar/utils.rb', line 42

def pepfar_patient_drilldown_information(patients, current_date)
  raise ::ArgumentError, "current_date can't be nil" unless current_date

  ::Person.joins("LEFT JOIN patient_identifier #{current_partition} ON patient_identifier.patient_id = person.person_id
                    AND patient_identifier.voided = 0
                    AND patient_identifier.identifier_type IN (#{pepfar_patient_identifier_type.to_sql})")
          .where(person_id: patients)
          .select("person.person_id AS patient_id,
                   person.gender,
                   person.birthdate,
                   disaggregated_age_group(person.birthdate, DATE(#{ActiveRecord::Base.connection.quote(current_date)})) AS age_group,
                   patient_identifier.identifier AS arv_number")
end

#pepfar_patient_identifier_typeObject

Returns the preferred Pepfar identifier type.

In some clinics like Lighthouse Filing numbers are used exclusively and in other sites, ARV Numbers are used.



61
62
63
64
65
# File 'app/services/malawi_hiv_program_reports/pepfar/utils.rb', line 61

def pepfar_patient_identifier_type
  name = GlobalProperty.find_by(property: 'use.filing.numbers')&.property_value
  name = name.present? && name == 'true' ? 'Filing number' : 'ARV Number'
  ::PatientIdentifierType.where(name:).select(:patient_identifier_type_id)
end

#rifapentine_conceptObject

rubocop:enable Metrics/MethodLength rubocop:enable Metrics/AbcSize



130
131
132
# File 'app/services/malawi_hiv_program_reports/pepfar/utils.rb', line 130

def rifapentine_concept
  @rifapentine_concept ||= ::ConceptName.find_by!(name: 'Rifapentine')
end