quality-measure-engine 1.1.5 → 2.0.0
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.
- data/.gitignore +12 -0
- data/.travis.yml +16 -0
- data/Gemfile +5 -21
- data/Gemfile.lock +126 -0
- data/LICENSE.txt +13 -0
- data/README.md +23 -44
- data/Rakefile +6 -29
- data/lib/qme/bundle/bundle.rb +34 -0
- data/lib/qme/bundle/importer.rb +69 -0
- data/lib/qme/database_access.rb +7 -11
- data/lib/qme/map/map_reduce_builder.rb +4 -1
- data/lib/qme/map/map_reduce_executor.rb +55 -43
- data/lib/qme/map/measure_calculation_job.rb +24 -23
- data/lib/qme/quality_measure.rb +5 -5
- data/lib/qme/quality_report.rb +37 -19
- data/lib/qme/railtie.rb +7 -0
- data/lib/qme/tasks/bundle.rake +14 -0
- data/lib/qme/version.rb +3 -0
- data/lib/quality-measure-engine.rb +13 -25
- data/quality-measure-engine.gemspec +28 -0
- data/test/fixtures/bundles/just_measure_0002.zip +0 -0
- data/test/fixtures/delayed_backend_mongoid_jobs/queued_job.json +9 -0
- data/test/fixtures/measures/measure_metadata.json +52 -0
- data/test/fixtures/records/barry_berry.json +471 -0
- data/test/fixtures/records/billy_jones_ipp.json +78 -0
- data/test/fixtures/records/jane_jones_numerator.json +120 -0
- data/test/fixtures/records/jill_jones_denominator.json +78 -0
- data/test/simplecov_setup.rb +18 -0
- data/test/test_helper.rb +26 -0
- data/test/unit/qme/map/map_reduce_builder_test.rb +38 -0
- data/test/unit/qme/map/map_reduce_executor_test.rb +56 -0
- data/test/unit/qme/map/measure_calculation_job_test.rb +22 -0
- data/test/unit/qme/quality_measure_test.rb +14 -0
- data/{spec/qme/quality_report_spec.rb → test/unit/qme/quality_report_test.rb} +32 -20
- metadata +91 -115
- data/VERSION +0 -1
- data/js/map_reduce_utils.js +0 -173
- data/js/underscore_min.js +0 -25
- data/lib/qme/ext/record.rb +0 -43
- data/lib/qme/importer/entry.rb +0 -126
- data/lib/qme/importer/generic_importer.rb +0 -117
- data/lib/qme/importer/measure_properties_generator.rb +0 -39
- data/lib/qme/importer/property_matcher.rb +0 -110
- data/lib/qme/measure/database_loader.rb +0 -83
- data/lib/qme/measure/measure_loader.rb +0 -174
- data/lib/qme/measure/properties_builder.rb +0 -184
- data/lib/qme/measure/properties_converter.rb +0 -27
- data/lib/qme/randomizer/patient_randomization_job.rb +0 -47
- data/lib/qme/randomizer/patient_randomizer.rb +0 -250
- data/lib/qme/randomizer/random_patient_creator.rb +0 -47
- data/lib/qme_test.rb +0 -13
- data/lib/tasks/fixtures.rake +0 -91
- data/lib/tasks/measure.rake +0 -110
- data/lib/tasks/mongo.rake +0 -68
- data/lib/tasks/patient_random.rake +0 -45
- data/spec/qme/bundle_spec.rb +0 -37
- data/spec/qme/importer/generic_importer_spec.rb +0 -73
- data/spec/qme/importer/measure_properties_generator_spec.rb +0 -15
- data/spec/qme/importer/property_matcher_spec.rb +0 -174
- data/spec/qme/map/map_reduce_builder_spec.rb +0 -38
- data/spec/qme/map/measures_spec.rb +0 -38
- data/spec/qme/map/patient_mapper_spec.rb +0 -11
- data/spec/qme/measure_loader_spec.rb +0 -12
- data/spec/qme/properties_builder_spec.rb +0 -61
- data/spec/spec_helper.rb +0 -120
- data/spec/validate_measures_spec.rb +0 -21
@@ -85,12 +85,15 @@ module QME
|
|
85
85
|
"function (key, value) {
|
86
86
|
var patient = value;
|
87
87
|
patient.measure_id = \"#{@measure_def['id']}\";\n"
|
88
|
-
if @params['test_id'] && @params['test_id'].class==BSON::ObjectId
|
88
|
+
if @params['test_id'] && @params['test_id'].class==Moped::BSON::ObjectId
|
89
89
|
reduce += " patient.test_id = new ObjectId(\"#{@params['test_id']}\");\n"
|
90
90
|
end
|
91
91
|
if @measure_def['sub_id']
|
92
92
|
reduce += " patient.sub_id = \"#{@measure_def['sub_id']}\";\n"
|
93
93
|
end
|
94
|
+
if @measure_def['nqf_id']
|
95
|
+
reduce += " patient.nqf_id = \"#{@measure_def['nqf_id']}\";\n"
|
96
|
+
end
|
94
97
|
|
95
98
|
reduce += "patient.effective_date = #{@params['effective_date']};
|
96
99
|
if (patient.provider_performances) {
|
@@ -16,7 +16,8 @@ module QME
|
|
16
16
|
@measure_id = measure_id
|
17
17
|
@sub_id = sub_id
|
18
18
|
@parameter_values = parameter_values
|
19
|
-
|
19
|
+
@measure_def = QualityMeasure.new(@measure_id, @sub_id).definition
|
20
|
+
determine_connection_information()
|
20
21
|
end
|
21
22
|
|
22
23
|
# Examines the patient_cache collection and generates a total of all groups
|
@@ -24,7 +25,7 @@ module QME
|
|
24
25
|
# collection.
|
25
26
|
# @return [Hash] measure groups (like numerator) as keys, counts as values
|
26
27
|
def count_records_in_measure_groups
|
27
|
-
|
28
|
+
pipeline = []
|
28
29
|
base_query = {'value.measure_id' => @measure_id, 'value.sub_id' => @sub_id,
|
29
30
|
'value.effective_date' => @parameter_values['effective_date'],
|
30
31
|
'value.test_id' => @parameter_values['test_id']}
|
@@ -34,25 +35,37 @@ module QME
|
|
34
35
|
query = base_query.clone
|
35
36
|
|
36
37
|
query.merge!({'value.manual_exclusion' => {'$in' => [nil, false]}})
|
38
|
+
|
39
|
+
pipeline << {'$match' => query}
|
40
|
+
pipeline << {'$group' => {
|
41
|
+
"_id" => "$value.measure_id", # we don't really need this, but Mongo requires that we group
|
42
|
+
"population" => {"$sum" => "$value.population"},
|
43
|
+
"denominator" => {"$sum" => "$value.denominator"},
|
44
|
+
"numerator" => {"$sum" => "$value.numerator"},
|
45
|
+
"antinumerator" => {"$sum" => "$value.antinumerator"},
|
46
|
+
"exclusions" => {"$sum" => "$value.exclusions"},
|
47
|
+
"denexcep" => {"$sum" => "$value.denexcep"},
|
48
|
+
"considered" => {"$sum" => 1}
|
49
|
+
}}
|
37
50
|
|
38
|
-
|
51
|
+
aggregate = get_db.command(:aggregate => 'patient_cache', :pipeline => pipeline)
|
52
|
+
if aggregate['ok'] != 1
|
53
|
+
raise RuntimeError, "Aggregation Failed"
|
54
|
+
elsif aggregate['result'].size !=1
|
55
|
+
raise RuntimeError, "Expected one group from patient_cache aggregation, got #{aggregate['result'].size}"
|
56
|
+
end
|
57
|
+
|
58
|
+
nqf_id = @measure_def['nqf_id'] || @measure_def['id']
|
59
|
+
result = {:measure_id => @measure_id, :sub_id => @sub_id, :nqf_id => nqf_id, :population_ids => @measure_def["population_ids"],
|
39
60
|
:effective_date => @parameter_values['effective_date'],
|
40
61
|
:test_id => @parameter_values['test_id'], :filters => @parameter_values['filters']}
|
41
|
-
|
42
|
-
# need to time the old way agains the single query to verify that the single query is more performant
|
43
|
-
aggregate = {"population"=>0, "denominator"=>0, "numerator"=>0, "antinumerator"=>0, "exclusions"=>0}
|
44
|
-
%w(population denominator numerator antinumerator exclusions).each do |measure_group|
|
45
|
-
patient_cache.find(query.merge("value.#{measure_group}" => true)) do |cursor|
|
46
|
-
aggregate[measure_group] = cursor.count
|
47
|
-
end
|
48
|
-
end
|
49
|
-
aggregate["considered"] = patient_cache.find(query).count
|
50
|
-
aggregate["exclusions"] += patient_cache.find(base_query.merge({'value.manual_exclusion'=>true})).count
|
51
|
-
result.merge!(aggregate)
|
52
62
|
|
63
|
+
result.merge!(aggregate['result'].first)
|
64
|
+
result.reject! {|k, v| k == '_id'} # get rid of the group id the Mongo forced us to use
|
65
|
+
result['exclusions'] += get_db['patient_cache'].find(base_query.merge({'value.manual_exclusion'=>true})).count
|
53
66
|
result.merge!(execution_time: (Time.now.to_i - @parameter_values['start_time'].to_i)) if @parameter_values['start_time']
|
54
|
-
|
55
|
-
get_db
|
67
|
+
get_db()["query_cache"].insert(result)
|
68
|
+
get_db().command({:getLastError => 1}) # make sure last insert finished before we continue
|
56
69
|
result
|
57
70
|
end
|
58
71
|
|
@@ -60,13 +73,13 @@ module QME
|
|
60
73
|
# in the patient_cache collection. These documents will state the measure groups
|
61
74
|
# that the record belongs to, such as numerator, etc.
|
62
75
|
def map_records_into_measure_groups
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
76
|
+
measure = Builder.new(get_db(), @measure_def, @parameter_values)
|
77
|
+
get_db().command(:mapReduce => 'records',
|
78
|
+
:map => measure.map_function,
|
79
|
+
:reduce => "function(key, values){return values;}",
|
80
|
+
:out => {:reduce => 'patient_cache'},
|
81
|
+
:finalize => measure.finalize_function,
|
82
|
+
:query => {:test_id => @parameter_values['test_id']})
|
70
83
|
apply_manual_exclusions
|
71
84
|
end
|
72
85
|
|
@@ -74,13 +87,13 @@ module QME
|
|
74
87
|
# This will create a document in the patient_cache collection. This document
|
75
88
|
# will state the measure groups that the record belongs to, such as numerator, etc.
|
76
89
|
def map_record_into_measure_groups(patient_id)
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
90
|
+
measure = Builder.new(get_db(), @measure_def, @parameter_values)
|
91
|
+
get_db().command(:mapReduce => 'records',
|
92
|
+
:map => measure.map_function,
|
93
|
+
:reduce => "function(key, values){return values;}",
|
94
|
+
:out => {:reduce => 'patient_cache'},
|
95
|
+
:finalize => measure.finalize_function,
|
96
|
+
:query => {:medical_record_number => patient_id, :test_id => @parameter_values['test_id']})
|
84
97
|
apply_manual_exclusions
|
85
98
|
end
|
86
99
|
|
@@ -88,14 +101,14 @@ module QME
|
|
88
101
|
# This will *not* create a document in the patient_cache collection, instead the
|
89
102
|
# result is returned directly.
|
90
103
|
def get_patient_result(patient_id)
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
104
|
+
measure = Builder.new(get_db(), @measure_def, @parameter_values)
|
105
|
+
result = get_db().command(:mapReduce => 'records',
|
106
|
+
:map => measure.map_function,
|
107
|
+
:reduce => "function(key, values){return values;}",
|
108
|
+
:out => {:inline => true},
|
109
|
+
:raw => true,
|
110
|
+
:finalize => measure.finalize_function,
|
111
|
+
:query => {:medical_record_number => patient_id, :test_id => @parameter_values['test_id']})
|
99
112
|
raise result['err'] if result['ok']!=1
|
100
113
|
result['results'][0]['value']
|
101
114
|
end
|
@@ -104,12 +117,11 @@ module QME
|
|
104
117
|
# and sets a flag in each cached patient result for patients that have been excluded from the
|
105
118
|
# current measure
|
106
119
|
def apply_manual_exclusions
|
107
|
-
exclusions = get_db
|
120
|
+
exclusions = get_db()['manual_exclusions'].find({'measure_id'=>@measure_id, 'sub_id'=>@sub_id}).to_a.map do |exclusion|
|
108
121
|
exclusion['medical_record_id']
|
109
122
|
end
|
110
|
-
get_db
|
111
|
-
{'
|
112
|
-
{'$set'=>{'value.manual_exclusion'=>true}}, :multi=>true)
|
123
|
+
get_db()['patient_cache'].find({'value.measure_id'=>@measure_id, 'value.sub_id'=>@sub_id, 'value.medical_record_id'=>{'$in'=>exclusions} })
|
124
|
+
.update_all({'$set'=>{'value.manual_exclusion'=>true}})
|
113
125
|
end
|
114
126
|
|
115
127
|
def filter_parameters
|
@@ -117,7 +129,7 @@ module QME
|
|
117
129
|
conditions = []
|
118
130
|
if(filters = @parameter_values['filters'])
|
119
131
|
if (filters['providers'] && filters['providers'].size > 0)
|
120
|
-
providers = filters['providers'].map {|provider_id| BSON::ObjectId(provider_id) if (provider_id and provider_id != 'null') }
|
132
|
+
providers = filters['providers'].map {|provider_id| Moped::BSON::ObjectId(provider_id) if (provider_id and provider_id != 'null') }
|
121
133
|
# provider_performances have already been filtered by start and end date in map_reduce_builder as part of the finalize
|
122
134
|
conditions << {'value.provider_performances.provider_id' => {'$in' => providers}}
|
123
135
|
end
|
@@ -1,11 +1,8 @@
|
|
1
1
|
module QME
|
2
2
|
module MapReduce
|
3
|
-
# A
|
3
|
+
# A delayed_job that allows for measure calculation by a delayed_job worker. Can be created as follows:
|
4
4
|
#
|
5
|
-
#
|
6
|
-
#
|
7
|
-
# This will return a uuid which can be used to check in on the status of a job. More details on this can be found
|
8
|
-
# at the {Resque Stats project page}[https://github.com/quirkey/resque-status].
|
5
|
+
# Delayed::Job.enqueue QME::MapRedude::MeasureCalculationJob.new(:measure_id => '0221', :sub_id => 'a', :effective_date => 1291352400, :test_id => xyzzy)
|
9
6
|
#
|
10
7
|
# MeasureCalculationJob will check to see if a measure has been calculated before running the calculation. It does
|
11
8
|
# this by creating a QME::QualityReport and asking if it has been calculated. If so, it will complete the job without
|
@@ -13,36 +10,40 @@ module QME
|
|
13
10
|
#
|
14
11
|
# When a measure needs calculation, the job will create a QME::MapReduce::Executor and interact with it to calculate
|
15
12
|
# the report.
|
16
|
-
class MeasureCalculationJob
|
17
|
-
|
18
|
-
|
13
|
+
class MeasureCalculationJob
|
14
|
+
attr_accessor :test_id, :measure_id, :sub_id, :effective_date, :filters
|
15
|
+
|
16
|
+
def initialize(options)
|
17
|
+
@measure_id = options['measure_id']
|
18
|
+
@sub_id = options['sub_id']
|
19
|
+
@options = options
|
19
20
|
end
|
20
21
|
|
21
|
-
def
|
22
|
-
|
23
|
-
qr = QualityReport.new(options['measure_id'], options['sub_id'], 'effective_date' => options['effective_date'], 'test_id' => test_id, 'filters' => options['filters'])
|
22
|
+
def perform
|
23
|
+
qr = QualityReport.new(@measure_id, @sub_id, @options)
|
24
24
|
if qr.calculated?
|
25
|
-
completed("#{
|
25
|
+
completed("#{@measure_id}#{@sub_id} has already been calculated")
|
26
26
|
else
|
27
|
-
map = QME::MapReduce::Executor.new(
|
28
|
-
|
27
|
+
map = QME::MapReduce::Executor.new(@measure_id, @sub_id, @options.merge('start_time' => Time.now.to_i))
|
29
28
|
if !qr.patients_cached?
|
30
|
-
tick('Starting MapReduce')
|
29
|
+
tick('Starting MapReduce')
|
31
30
|
map.map_records_into_measure_groups
|
32
|
-
tick('MapReduce complete')
|
31
|
+
tick('MapReduce complete')
|
33
32
|
end
|
34
33
|
|
35
|
-
tick('Calculating group totals')
|
34
|
+
tick('Calculating group totals')
|
36
35
|
result = map.count_records_in_measure_groups
|
37
|
-
completed("#{
|
36
|
+
completed("#{@measure_id}#{@sub_id}: p#{result['population']}, d#{result['denominator']}, n#{result['numerator']}, excl#{result['exclusions']}, excep#{result['denexcep']}")
|
38
37
|
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def completed(message)
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
def tick(message)
|
39
45
|
|
40
46
|
end
|
41
|
-
|
42
|
-
# This can be uncommented and changed to put the jobs on a separate queue.
|
43
|
-
# def self.queue
|
44
|
-
# :statused
|
45
|
-
# end
|
46
47
|
end
|
47
48
|
end
|
48
49
|
end
|
data/lib/qme/quality_measure.rb
CHANGED
@@ -8,7 +8,7 @@ module QME
|
|
8
8
|
# @return [Hash] an hash of measure definitions
|
9
9
|
def self.all
|
10
10
|
result = {}
|
11
|
-
measures = get_db
|
11
|
+
measures = get_db()['measures']
|
12
12
|
measures.find().each do |measure|
|
13
13
|
id = measure['id']
|
14
14
|
sub_id = measure['sub_id']
|
@@ -19,7 +19,7 @@ module QME
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def self.get_measures(measure_ids)
|
22
|
-
get_db
|
22
|
+
get_db()['measures'].find('id' => {"$in" => measure_ids})
|
23
23
|
end
|
24
24
|
|
25
25
|
# Creates a new QualityMeasure
|
@@ -34,11 +34,11 @@ module QME
|
|
34
34
|
# Retrieve a measure definition from the database
|
35
35
|
# @return [Hash] a JSON hash of the encoded measure
|
36
36
|
def definition
|
37
|
-
measures = get_db
|
37
|
+
measures = get_db()['measures']
|
38
38
|
if @sub_id
|
39
|
-
measures.
|
39
|
+
measures.find({'id' => @measure_id, 'sub_id' => @sub_id}).first()
|
40
40
|
else
|
41
|
-
measures.
|
41
|
+
measures.find({'id' => @measure_id}).first()
|
42
42
|
end
|
43
43
|
end
|
44
44
|
end
|
data/lib/qme/quality_report.rb
CHANGED
@@ -10,25 +10,25 @@ module QME
|
|
10
10
|
# and query_cache collections
|
11
11
|
def self.destroy_all
|
12
12
|
determine_connection_information
|
13
|
-
get_db
|
14
|
-
get_db
|
13
|
+
get_db()["query_cache"].drop
|
14
|
+
get_db()["patient_cache"].drop
|
15
15
|
end
|
16
16
|
|
17
17
|
# Removes the cached results for the patient with the supplied id and
|
18
18
|
# recalculates as necessary
|
19
19
|
def self.update_patient_results(id)
|
20
|
-
determine_connection_information
|
20
|
+
determine_connection_information()
|
21
21
|
|
22
22
|
# TODO: need to wait for any outstanding calculations to complete and then prevent
|
23
23
|
# any new ones from starting until we are done.
|
24
24
|
|
25
25
|
# drop any cached measure result calculations for the modified patient
|
26
|
-
get_db
|
26
|
+
get_db()["patient_cache"].find('value.medical_record_id' => id).remove_all()
|
27
27
|
|
28
28
|
# get a list of cached measure results for a single patient
|
29
|
-
sample_patient = get_db
|
29
|
+
sample_patient = get_db()['patient_cache'].find().first()
|
30
30
|
if sample_patient
|
31
|
-
cached_results = get_db
|
31
|
+
cached_results = get_db()['patient_cache'].find({'value.patient_id' => sample_patient['value']['patient_id']})
|
32
32
|
|
33
33
|
# for each cached result (a combination of measure_id, sub_id, effective_date and test_id)
|
34
34
|
cached_results.each do |measure|
|
@@ -42,7 +42,7 @@ module QME
|
|
42
42
|
|
43
43
|
# remove the query totals so they will be recalculated using the new results for
|
44
44
|
# the modified patient
|
45
|
-
get_db
|
45
|
+
get_db()["query_cache"].drop()
|
46
46
|
end
|
47
47
|
|
48
48
|
# Creates a new QualityReport
|
@@ -74,29 +74,47 @@ module QME
|
|
74
74
|
# Kicks off a background job to calculate the measure
|
75
75
|
# @return a unique id for the measure calculation job
|
76
76
|
def calculate(asynchronous=true)
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
77
|
+
|
78
|
+
options = {'measure_id' => @measure_id, 'sub_id' => @sub_id}
|
79
|
+
|
80
|
+
options.merge! @parameter_values
|
81
|
+
options['filters'] = QME::QualityReport.normalize_filters(@parameter_values['filters'])
|
82
|
+
|
81
83
|
if (asynchronous)
|
82
|
-
MapReduce::MeasureCalculationJob.
|
84
|
+
job = Delayed::Job.enqueue(QME::MapReduce::MeasureCalculationJob.new(options))
|
85
|
+
job._id
|
83
86
|
else
|
84
|
-
MapReduce::MeasureCalculationJob.
|
87
|
+
mcj = QME::MapReduce::MeasureCalculationJob.new(options)
|
88
|
+
mcj.perform
|
85
89
|
end
|
86
90
|
end
|
87
91
|
|
88
92
|
# Returns the status of a measure calculation job
|
89
93
|
# @param job_id the id of the job to check on
|
90
|
-
# @return [
|
94
|
+
# @return [Symbol] Will return the status: :complete, :queued, :running, :failed
|
91
95
|
def status(job_id)
|
92
|
-
|
96
|
+
job = Delayed::Job.where(_id: job_id).first
|
97
|
+
if job.nil?
|
98
|
+
# If we can't find the job, we assume that it is complete
|
99
|
+
:complete
|
100
|
+
else
|
101
|
+
if job.locked_at.nil?
|
102
|
+
:queued
|
103
|
+
else
|
104
|
+
if job.failed?
|
105
|
+
:failed
|
106
|
+
else
|
107
|
+
:running
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
93
111
|
end
|
94
112
|
|
95
113
|
# Gets the result of running a quality measure
|
96
114
|
# @return [Hash] measure groups (like numerator) as keys, counts as values or nil if
|
97
115
|
# the measure has not yet been calculated
|
98
116
|
def result
|
99
|
-
cache = get_db
|
117
|
+
cache = get_db()["query_cache"]
|
100
118
|
query = {:measure_id => @measure_id, :sub_id => @sub_id,
|
101
119
|
:effective_date => @parameter_values['effective_date'],
|
102
120
|
:test_id => @parameter_values['test_id']}
|
@@ -106,7 +124,7 @@ module QME
|
|
106
124
|
query.merge!({filters: nil})
|
107
125
|
end
|
108
126
|
|
109
|
-
cache.
|
127
|
+
cache.find(query).first()
|
110
128
|
end
|
111
129
|
|
112
130
|
# make sure all filter id arrays are sorted
|
@@ -115,11 +133,11 @@ module QME
|
|
115
133
|
end
|
116
134
|
|
117
135
|
def patient_result
|
118
|
-
cache = get_db
|
136
|
+
cache = get_db()["patient_cache"]
|
119
137
|
query = {'value.measure_id' => @measure_id, 'value.sub_id' => @sub_id,
|
120
138
|
'value.effective_date' => @parameter_values['effective_date'],
|
121
139
|
'value.test_id' => @parameter_values['test_id']}
|
122
|
-
cache.
|
140
|
+
cache.find(query).first()
|
123
141
|
end
|
124
142
|
|
125
143
|
end
|
data/lib/qme/railtie.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'quality-measure-engine'
|
2
|
+
|
3
|
+
db_name = ENV['DB_NAME'] || 'test'
|
4
|
+
|
5
|
+
namespace :bundle do
|
6
|
+
desc 'Import a quality bundle into the database.'
|
7
|
+
task :import, :bundle_path, :delete_existing, :needs => :environment do |task, args|
|
8
|
+
raise "The path to the measures zip file must be specified" unless args.bundle_path
|
9
|
+
|
10
|
+
bundle = File.open(args.bundle_path)
|
11
|
+
importer = QME::Bundle::Importer.new(db_name)
|
12
|
+
importer.import(bundle, args.delete_existing)
|
13
|
+
end
|
14
|
+
end
|
data/lib/qme/version.rb
ADDED
@@ -1,32 +1,20 @@
|
|
1
1
|
require "bundler/setup"
|
2
2
|
|
3
|
-
require '
|
3
|
+
require 'moped'
|
4
|
+
require 'delayed_job_mongoid'
|
5
|
+
require 'zip/zip'
|
4
6
|
|
5
|
-
|
6
|
-
|
7
|
+
require "qme/version"
|
8
|
+
require 'qme/database_access'
|
9
|
+
require 'qme/quality_measure'
|
7
10
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
+
require 'qme/map/map_reduce_builder'
|
12
|
+
require 'qme/map/map_reduce_executor'
|
13
|
+
require 'qme/map/measure_calculation_job'
|
11
14
|
|
12
|
-
|
15
|
+
require 'qme/quality_report'
|
13
16
|
|
14
|
-
|
15
|
-
|
16
|
-
require_relative 'qme/randomizer/patient_randomization_job'
|
17
|
+
require 'qme/bundle/bundle'
|
18
|
+
require 'qme/bundle/importer'
|
17
19
|
|
18
|
-
require '
|
19
|
-
require 'health-data-standards'
|
20
|
-
|
21
|
-
require_relative 'qme/ext/record'
|
22
|
-
|
23
|
-
require_relative 'qme/importer/property_matcher'
|
24
|
-
require_relative 'qme/importer/generic_importer'
|
25
|
-
require_relative 'qme/importer/measure_properties_generator'
|
26
|
-
|
27
|
-
require 'json'
|
28
|
-
require 'mongo'
|
29
|
-
require 'nokogiri'
|
30
|
-
|
31
|
-
require_relative 'qme/measure/measure_loader'
|
32
|
-
require_relative 'qme/measure/database_loader'
|
20
|
+
require 'qme/railtie' if defined?(Rails)
|