Class: QME::QualityReport

Inherits:
Object
  • Object
show all
Includes:
Mongoid::Attributes::Dynamic, Mongoid::Document, Mongoid::Timestamps
Defined in:
lib/qme/quality_report.rb

Overview

A class that allows you to create and obtain the results of running a quality measure against a set of patient records.

Constant Summary collapse

POPULATION =
'IPP'
DENOMINATOR =
'DENOM'
NUMERATOR =
'NUMER'
EXCLUSIONS =
'DENEX'
EXCEPTIONS =
'DENEXCEP'
MSRPOPL =
'MSRPOPL'
MSRPOPLEX =
'MSRPOPLEX'
OBSERVATION =
'OBSERV'
ANTINUMERATOR =
'antinumerator'
CONSIDERED =
'considered'
RACE =
'RACE'
ETHNICITY =
'ETHNICITY'
SEX =
'SEX'
POSTAL_CODE =
'POSTAL_CODE'
PAYER =
'PAYER'

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.find_or_create(measure_id, sub_id, parameter_values) ⇒ Object



95
96
97
98
99
100
101
# File 'lib/qme/quality_report.rb', line 95

def self.find_or_create(measure_id, sub_id, parameter_values)
  @parameter_values = parameter_values
  @parameter_values[:filters] = self.normalize_filters(@parameter_values[:filters])
  query = {measure_id: measure_id, sub_id: sub_id}
  query.merge! @parameter_values
  self.find_or_create_by(query)
end

.normalize_filters(filters) ⇒ Object

make sure all filter id arrays are sorted



174
175
176
# File 'lib/qme/quality_report.rb', line 174

def self.normalize_filters(filters)
  filters.each {|key, value| value.sort_by! {|v| (v.is_a? Hash) ? "#{v}" : v} if value.is_a? Array} unless filters.nil?
end

.queue_staged_rollups(measure_id, sub_id, effective_date) ⇒ Object



103
104
105
106
107
108
109
110
111
# File 'lib/qme/quality_report.rb', line 103

def self.queue_staged_rollups(measure_id,sub_id,effective_date)
 query = Mongoid.default_client["rollup_buffer"].find({measure_id: measure_id, sub_id: sub_id, effective_date: effective_date})
 query.each do |options|
    if QME::QualityReport.where("_id" => options["quality_report_id"]).count == 1
       QME::QualityReport.enque_job(options,:rollup)
    end
 end
 query.delete_many
end

.update_patient_results(id) ⇒ Object

Removes the cached results for the patient with the supplied id and recalculates as necessary



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
# File 'lib/qme/quality_report.rb', line 65

def self.update_patient_results(id)
  # TODO: need to wait for any outstanding calculations to complete and then prevent
  # any new ones from starting until we are done.

  # drop any cached measure result calculations for the modified patient
 QME::PatientCache.where('value.medical_record_id' => id).destroy()

  # get a list of cached measure results for a single patient
  sample_patient = QME::PatientCache.where({}).first
  if sample_patient
    cached_results = QME::PatientCache.where({'value.patient_id' => sample_patient['value']['patient_id']})

    # for each cached result (a combination of measure_id, sub_id, effective_date and test_id)
    cached_results.each do |measure|
      # recalculate patient_cache value for modified patient
      value = measure['value']
      map = QME::MapReduce::Executor.new(value['measure_id'], value['sub_id'],
        'effective_date' => value['effective_date'], 'test_id' => value['test_id'])
      map.map_record_into_measure_groups(id)
    end
  end

  # remove the query totals so they will be recalculated using the new results for
  # the modified patient
  self.destroy_all
end

Instance Method Details

#calculate(parameters, asynchronous = true) ⇒ Object

Kicks off a background job to calculate the measure

Returns:

  • a unique id for the measure calculation job



135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
# File 'lib/qme/quality_report.rb', line 135

def calculate(parameters, asynchronous=true)

  options = {'quality_report_id' => self.id}
  options.merge! parameters || {}

  if self.status["state"] == "completed" && !options["recalculate"]
    return self
  end

  self.status["state"] = "queued"
  if (asynchronous)
    options[:asynchronous] = true
    if patients_cached?
      QME::QualityReport.enque_job(options,:rollup)
    elsif calculation_queued_or_running?
      self.status["state"] = "stagged"
      self.save
      options.merge!( {measure_id: self.measure_id, sub_id: self.sub_id, effective_date: self.effective_date })
      Mongoid.default_client["rollup_buffer"].insert_one(options)
    else
      # queue the job for calculation
      QME::QualityReport.enque_job(options,:calculation)
    end
  else
    mcj = QME::MapReduce::MeasureCalculationJob.new(options)
    mcj.perform
  end
end

#calculated?true|false

Determines whether the quality report has been calculated for the given measure and parameters

Returns:

  • (true|false)


116
117
118
# File 'lib/qme/quality_report.rb', line 116

def calculated?
  self.status["state"] == "completed"
end

#calculation_queued_or_running?Boolean

queued up by another quality report or if it is currently running

Returns:

  • (Boolean)


129
130
131
# File 'lib/qme/quality_report.rb', line 129

def calculation_queued_or_running?
  !QME::QualityReport.where({measure_id: self.measure_id,sub_id:self.sub_id, effective_date: self.effective_date, test_id: self.test_id }).nin("status.state" =>["unknown","stagged"]).first.nil?
end

#measureObject



169
170
171
# File 'lib/qme/quality_report.rb', line 169

def measure
  QME::QualityMeasure.where({"hqmf_id"=>self.measure_id, "sub_id" => self.sub_id}).first
end

#patient_cache_matcherObject



187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
# File 'lib/qme/quality_report.rb', line 187

def patient_cache_matcher
  match = {'value.measure_id' => self.measure_id,
           'value.sub_id'           => self.sub_id,
           'value.effective_date'   => self.effective_date,
           'value.test_id'          => test_id,
           'value.manual_exclusion' => {'$in' => [nil, false]}}

  if(filters)
    if (filters['races'] && filters['races'].size > 0)
      match['value.race.code'] = {'$in' => filters['races']}
    end
    if (filters['ethnicities'] && filters['ethnicities'].size > 0)
      match['value.ethnicity.code'] = {'$in' => filters['ethnicities']}
    end
    if (filters['genders'] && filters['genders'].size > 0)
      match['value.gender'] = {'$in' => filters['genders']}
    end
    if (filters['providers'] && filters['providers'].size > 0)
      providers = filters['providers'].map { |pv| BSON::ObjectId.from_string(pv) }
      match['value.provider_performances.provider_id'] = {'$in' => providers}
    end
    if (filters['languages'] && filters['languages'].size > 0)
      match["value.languages"] = {'$in' => filters['languages']}
    end
  end
  match
end

#patient_result(patient_id = nil) ⇒ Object



178
179
180
181
182
183
184
# File 'lib/qme/quality_report.rb', line 178

def patient_result(patient_id = nil)
  query = patient_cache_matcher
  if patient_id
    query['value.medical_record_id'] = patient_id
  end
   QME::PatientCache.where(query).first()
end

#patient_resultsObject



164
165
166
167
# File 'lib/qme/quality_report.rb', line 164

def patient_results
 ex = QME::MapReduce::Executor.new(self.measure_id,self.sub_id, self.attributes)
 QME::PatientCache.where(patient_cache_matcher)
end

#patients_cached?Boolean

Determines whether the patient mapping for the quality report has been completed

Returns:

  • (Boolean)


122
123
124
# File 'lib/qme/quality_report.rb', line 122

def patients_cached?
  !QME::QualityReport.where({measure_id: self.measure_id,sub_id:self.sub_id, effective_date: self.effective_date, test_id: self.test_id, "status.state" => "completed" }).first.nil?
end