Class: MalawiHivProgramReports::Moh::ArtCohort

Inherits:
Object
  • Object
show all
Includes:
Adapters::Moh::Custom, Utils::ConcurrencyUtils, Utils::ModelUtils
Defined in:
app/services/malawi_hiv_program_reports/moh/art_cohort.rb

Overview

Cohort report builder class.

This class only provides one public method (start_build_report) besides the constructor. This method must be called to build report and save it to database. rubocop:disable Metrics/ClassLength

Constant Summary collapse

LOCK_FILE =
'art_service/reports/cohort.lock'

Constants included from Utils::ConcurrencyUtils

Utils::ConcurrencyUtils::LOCK_FILES_DIR_PATH

Instance Method Summary collapse

Methods included from Adapters::Moh::Custom

#cast_manager, #current_partition, #exe_create_drill_down_table, #exe_temp_cohort_members_table, #exe_temp_order_details_table, #exe_temp_other_patient_types, #exe_temp_register_start_date_table, #exe_tmp_patient_table, #function_manager, #group_by_columns, #in_manager, #interval_manager, #min_filt, #site_manager, #timestampdiff_manager

Methods included from Utils::ModelUtils

#concept, #concept_id_to_name, #concept_name, #concept_name_to_id, #drug, #encounter_type, #global_property, #order_type, #patient_identifier_type, #program, #report_type, #user_property

Methods included from Utils::ConcurrencyUtils

#with_lock

Constructor Details

#initialize(name:, type:, start_date:, end_date:, **kwargs) ⇒ ArtCohort

Returns a new instance of ArtCohort.



18
19
20
21
22
23
24
25
26
27
28
# File 'app/services/malawi_hiv_program_reports/moh/art_cohort.rb', line 18

def initialize(name:, type:, start_date:, end_date:, **kwargs)
  @name = name
  @start_date = start_date
  @end_date = end_date
  @type = type
  @occupation = kwargs[:occupation]
  @location = kwargs[:location]
  @cohort_builder = CohortBuilder.new(outcomes_definition: 'moh', **kwargs)
  @cohort_struct = CohortStruct.new
  @location_name = @location && Location.find(@location).name
end

Instance Method Details

#build_reportObject



30
31
32
33
34
35
36
37
38
39
# File 'app/services/malawi_hiv_program_reports/moh/art_cohort.rb', line 30

def build_report
  with_lock(LOCK_FILE, blocking: false) do
    init_drill_down_table
    @cohort_builder.build(@cohort_struct, @start_date, @end_date, @occupation)
    clear_drill_down
    save_report
  end
rescue ::FailedToAcquireLock => e
  Rails.logger.warn("ART#Cohort report is locked by another process: #{e}")
end

#cohort_report_drill_down(id) ⇒ Object



120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'app/services/malawi_hiv_program_reports/moh/art_cohort.rb', line 120

def cohort_report_drill_down(id)
  id = ActiveRecord::Base.connection.quote(id)

  patients = ActiveRecord::Base.connection.select_all <<~SQL
    SELECT i.identifier arv_number, p.birthdate,
           p.gender, n.given_name, n.family_name, p.person_id patient_id,
           outcomes.cum_outcome AS outcome
    FROM person p
    INNER JOIN cohort_drill_down c ON c.patient_id = p.person_id
    INNER JOIN temp_patient_outcomes AS outcomes
      ON outcomes.patient_id = c.patient_id
    LEFT JOIN patient_identifier i ON i.patient_id = p.person_id
    AND i.voided = 0 AND i.identifier_type = 4
    LEFT JOIN person_name n ON n.person_id = p.person_id AND n.voided = 0
    WHERE c.reporting_report_design_resource_id = #{id}
    GROUP BY p.person_id ORDER BY p.person_id, p.date_created;
  SQL

  patients.map do |person|
    {
      person_id: person['patient_id'],
      given_name: person['given_name'],
      family_name: person['family_name'],
      birthdate: person['birthdate'],
      gender: person['gender'],
      arv_number: person['arv_number'],
      outcome: person['outcome']
    }
  end
end

#defaulter_list(pepfar) ⇒ Object



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
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
# File 'app/services/malawi_hiv_program_reports/moh/art_cohort.rb', line 48

def defaulter_list(pepfar)
  report_type = (pepfar ? 'pepfar' : 'moh')
  defaulter_date_sql = pepfar ? 'current_pepfar_defaulter_date' : 'current_defaulter_date'
  CohortBuilder.new(outcomes_definition: report_type, location: @location)
               .init_temporary_tables(@start_date, @end_date, @occupation)

  data = ActiveRecord::Base.connection.select_all <<~SQL
    SELECT
      e.patient_id, i.identifier arv_number, e.birthdate,
      e.gender, n.given_name, n.family_name,
      art_reason.name art_reason, a.value cell_number, landmark.value landmark,
      s.state_province district, s.county_district ta,
      s.city_village village, TIMESTAMPDIFF(year, DATE(e.birthdate), DATE('#{@end_date}')) age,
      #{defaulter_date_sql}(e.patient_id, TIMESTAMP('#{@end_date.to_date.strftime('%Y-%m-%d 23:59:59')}')) AS defaulter_date,
      appointment.appointment_date AS appointment_date
    FROM temp_earliest_start_date e
    INNER JOIN temp_patient_outcomes o ON e.patient_id = o.patient_id
    INNER JOIN (
      SELECT e.patient_id, MAX(o.value_datetime) appointment_date
      FROM encounter e
      INNER JOIN obs o ON o.encounter_id = e.encounter_id AND o.voided = 0 AND o.concept_id = 5096 -- appointment date
      WHERE e.encounter_type = 7 -- appointment encounter type
      AND e.program_id = 1 -- HIV PROGRAM
      AND e.patient_id IN (SELECT patient_id FROM temp_patient_outcomes WHERE cum_outcome = 'Defaulted')
      AND e.encounter_datetime < DATE('#{@end_date}') + INTERVAL 1 DAY
      GROUP BY e.patient_id
    ) appointment ON appointment.patient_id = e.patient_id
    LEFT JOIN patient_identifier i ON i.patient_id = e.patient_id
    AND i.voided = 0 AND i.identifier_type = 4
    INNER JOIN person_name n ON n.person_id = e.patient_id AND n.voided = 0
    LEFT JOIN person_attribute a ON a.person_id = e.patient_id
    AND a.voided = 0 AND a.person_attribute_type_id = 12
    LEFT JOIN person_attribute landmark ON landmark.person_id = e.patient_id AND landmark.voided = 0 AND landmark.person_attribute_type_id = 19
    LEFT JOIN person_address s ON s.person_id = e.patient_id AND s.voided = 0
    LEFT JOIN concept_name art_reason ON art_reason.concept_id = e.reason_for_starting_art AND art_reason.voided = 0
    WHERE o.cum_outcome = 'Defaulted' GROUP BY e.patient_id
    ORDER BY e.patient_id, n.date_created DESC;
  SQL

  patients = []

  (data || []).each do |person|
    defaulter_date = person['defaulter_date']&.to_date || 'N/A'

    unless defaulter_date == 'N/A'
      next if defaulter_date < @start_date.to_date
      next if defaulter_date > @end_date.to_date
    end

    patients << {
      person_id: person['patient_id'],
      given_name: person['given_name'],
      family_name: person['family_name'],
      birthdate: person['birthdate'],
      gender: person['gender'],
      arv_number: person['arv_number'],
      outcome: 'Defaulted',
      defaulter_date:,
      appointment_date: person['appointment_date'].to_date.strftime('%Y-%m-%d'),
      art_reason: person['art_reason'],
      cell_number: person['cell_number'],
      district: person['district'],
      ta: person['ta'],
      village: person['village'],
      current_age: person['age'],
      landmark: person['landmark']
    }
  end

  patients
end

#find_reportObject



41
42
43
44
45
46
# File 'app/services/malawi_hiv_program_reports/moh/art_cohort.rb', line 41

def find_report
  ::Report.where(type: @type, name: "#{@name}#{"-#{@occupation}"}#{"-#{@location_name}"}",
                 start_date: @start_date, end_date: @end_date)
          .order(date_created: :desc)
          .first
end