quality-measure-engine 3.0.2 → 3.0.3
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/Gemfile +0 -5
- data/Gemfile.lock +98 -96
- data/README.md +5 -18
- data/lib/qme/map/map_reduce_builder.rb +28 -14
- data/lib/qme/map/map_reduce_executor.rb +3 -3
- data/lib/qme/quality_measure.rb +1 -2
- data/lib/qme/quality_report.rb +7 -6
- data/lib/qme/version.rb +1 -1
- data/quality-measure-engine.gemspec +6 -6
- data/test/fixtures/records/barry_berry.json +9 -2
- data/test/fixtures/records/billy_jones_ipp.json +7 -0
- data/test/fixtures/records/jane_jones_numerator.json +12 -0
- data/test/fixtures/records/jill_jones_denominator.json +7 -0
- data/test/test_helper.rb +5 -6
- data/test/unit/qme/map/map_reduce_executor_test.rb +16 -8
- data/test/unit/qme/quality_report_test.rb +14 -16
- metadata +14 -14
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 2ac3f8a80c26556684d7f21bd6201e5265b256eb
|
|
4
|
+
data.tar.gz: b8379f12837783c518639ebadb3d21fe7e07546f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: fb88b3fecf9ce6d5cee8f489195ed8e02b5d2a91f8549dd97a417af732d4225aadad6c0d0f1a5fd331736140d19d23821aee251b1f47ae40ee3f56b18334f589
|
|
7
|
+
data.tar.gz: 5da3dd5bc12ee8383df188b97d1dfefadd23591daee55674bed0ae2da4ec6a29209c36e3eac2310d6a4e206146bdbec3162f4a35922dbd2881753bdb286bc44c
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
|
@@ -1,142 +1,144 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
quality-measure-engine (3.0.
|
|
5
|
-
delayed_job_mongoid (~> 2.
|
|
6
|
-
mongoid (~>
|
|
7
|
-
moped (~>
|
|
4
|
+
quality-measure-engine (3.0.3)
|
|
5
|
+
delayed_job_mongoid (~> 2.1.0)
|
|
6
|
+
mongoid (~> 4.0.0)
|
|
7
|
+
moped (~> 2.0.0)
|
|
8
8
|
rubyzip (~> 0.9.9)
|
|
9
9
|
|
|
10
10
|
GEM
|
|
11
11
|
remote: https://rubygems.org/
|
|
12
12
|
specs:
|
|
13
|
-
actionmailer (
|
|
14
|
-
actionpack (=
|
|
13
|
+
actionmailer (4.1.5)
|
|
14
|
+
actionpack (= 4.1.5)
|
|
15
|
+
actionview (= 4.1.5)
|
|
15
16
|
mail (~> 2.5.4)
|
|
16
|
-
actionpack (
|
|
17
|
-
|
|
18
|
-
activesupport (=
|
|
19
|
-
|
|
17
|
+
actionpack (4.1.5)
|
|
18
|
+
actionview (= 4.1.5)
|
|
19
|
+
activesupport (= 4.1.5)
|
|
20
|
+
rack (~> 1.5.2)
|
|
21
|
+
rack-test (~> 0.6.2)
|
|
22
|
+
actionview (4.1.5)
|
|
23
|
+
activesupport (= 4.1.5)
|
|
24
|
+
builder (~> 3.1)
|
|
20
25
|
erubis (~> 2.7.0)
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
tzinfo (~>
|
|
34
|
-
|
|
35
|
-
activemodel (= 3.2.14)
|
|
36
|
-
activesupport (= 3.2.14)
|
|
37
|
-
activesupport (3.2.14)
|
|
38
|
-
i18n (~> 0.6, >= 0.6.4)
|
|
39
|
-
multi_json (~> 1.0)
|
|
40
|
-
ansi (1.4.3)
|
|
41
|
-
arel (3.0.2)
|
|
26
|
+
activemodel (4.1.5)
|
|
27
|
+
activesupport (= 4.1.5)
|
|
28
|
+
builder (~> 3.1)
|
|
29
|
+
activerecord (4.1.5)
|
|
30
|
+
activemodel (= 4.1.5)
|
|
31
|
+
activesupport (= 4.1.5)
|
|
32
|
+
arel (~> 5.0.0)
|
|
33
|
+
activesupport (4.1.5)
|
|
34
|
+
i18n (~> 0.6, >= 0.6.9)
|
|
35
|
+
json (~> 1.7, >= 1.7.7)
|
|
36
|
+
minitest (~> 5.1)
|
|
37
|
+
thread_safe (~> 0.1)
|
|
38
|
+
tzinfo (~> 1.1)
|
|
39
|
+
arel (5.0.1.20140414130214)
|
|
42
40
|
binding_of_caller (0.7.2)
|
|
43
41
|
debug_inspector (>= 0.0.1)
|
|
44
|
-
|
|
45
|
-
|
|
42
|
+
bson (2.3.0)
|
|
43
|
+
builder (3.2.2)
|
|
44
|
+
coderay (1.1.0)
|
|
45
|
+
connection_pool (2.0.0)
|
|
46
46
|
debug_inspector (0.0.2)
|
|
47
|
-
delayed_job (
|
|
48
|
-
activesupport (
|
|
49
|
-
delayed_job_mongoid (2.
|
|
50
|
-
delayed_job (
|
|
51
|
-
mongoid (
|
|
47
|
+
delayed_job (4.0.2)
|
|
48
|
+
activesupport (>= 3.0, < 4.2)
|
|
49
|
+
delayed_job_mongoid (2.1.0)
|
|
50
|
+
delayed_job (>= 3.0, < 5)
|
|
51
|
+
mongoid (>= 3.0, < 5)
|
|
52
|
+
docile (1.1.5)
|
|
52
53
|
erubis (2.7.0)
|
|
53
54
|
hike (1.2.3)
|
|
54
|
-
i18n (0.6.
|
|
55
|
-
interception (0.
|
|
56
|
-
|
|
57
|
-
json (1.8.0)
|
|
55
|
+
i18n (0.6.11)
|
|
56
|
+
interception (0.5)
|
|
57
|
+
json (1.8.1)
|
|
58
58
|
mail (2.5.4)
|
|
59
59
|
mime-types (~> 1.16)
|
|
60
60
|
treetop (~> 1.4.8)
|
|
61
61
|
method_source (0.8.2)
|
|
62
|
-
mime-types (1.
|
|
63
|
-
minitest (4.
|
|
64
|
-
mongoid (
|
|
65
|
-
activemodel (~>
|
|
66
|
-
moped (~>
|
|
67
|
-
origin (~> 1
|
|
68
|
-
tzinfo (
|
|
69
|
-
moped (
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
62
|
+
mime-types (1.25.1)
|
|
63
|
+
minitest (5.4.0)
|
|
64
|
+
mongoid (4.0.0)
|
|
65
|
+
activemodel (~> 4.0)
|
|
66
|
+
moped (~> 2.0.0)
|
|
67
|
+
origin (~> 2.1)
|
|
68
|
+
tzinfo (>= 0.3.37)
|
|
69
|
+
moped (2.0.0)
|
|
70
|
+
bson (~> 2.2)
|
|
71
|
+
connection_pool (~> 2.0)
|
|
72
|
+
optionable (~> 0.2.0)
|
|
73
|
+
multi_json (1.10.1)
|
|
74
|
+
optionable (0.2.0)
|
|
75
|
+
origin (2.1.1)
|
|
76
|
+
polyglot (0.3.5)
|
|
77
|
+
pry (0.10.1)
|
|
78
|
+
coderay (~> 1.1.0)
|
|
79
|
+
method_source (~> 0.8.1)
|
|
76
80
|
slop (~> 3.4)
|
|
77
|
-
pry-nav (0.2.
|
|
78
|
-
pry (
|
|
79
|
-
pry-rescue (1.
|
|
80
|
-
interception (>= 0.
|
|
81
|
+
pry-nav (0.2.4)
|
|
82
|
+
pry (>= 0.9.10, < 0.11.0)
|
|
83
|
+
pry-rescue (1.4.1)
|
|
84
|
+
interception (>= 0.5)
|
|
81
85
|
pry
|
|
82
86
|
pry-stack_explorer (0.4.9.1)
|
|
83
87
|
binding_of_caller (>= 0.7)
|
|
84
88
|
pry (>= 0.9.11)
|
|
85
|
-
rack (1.
|
|
86
|
-
rack-cache (1.2)
|
|
87
|
-
rack (>= 0.4)
|
|
88
|
-
rack-ssl (1.3.3)
|
|
89
|
-
rack
|
|
89
|
+
rack (1.5.2)
|
|
90
90
|
rack-test (0.6.2)
|
|
91
91
|
rack (>= 1.0)
|
|
92
|
-
rails (
|
|
93
|
-
actionmailer (=
|
|
94
|
-
actionpack (=
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
92
|
+
rails (4.1.5)
|
|
93
|
+
actionmailer (= 4.1.5)
|
|
94
|
+
actionpack (= 4.1.5)
|
|
95
|
+
actionview (= 4.1.5)
|
|
96
|
+
activemodel (= 4.1.5)
|
|
97
|
+
activerecord (= 4.1.5)
|
|
98
|
+
activesupport (= 4.1.5)
|
|
99
|
+
bundler (>= 1.3.0, < 2.0)
|
|
100
|
+
railties (= 4.1.5)
|
|
101
|
+
sprockets-rails (~> 2.0)
|
|
102
|
+
railties (4.1.5)
|
|
103
|
+
actionpack (= 4.1.5)
|
|
104
|
+
activesupport (= 4.1.5)
|
|
104
105
|
rake (>= 0.8.7)
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
rake (10.1.0)
|
|
108
|
-
rdoc (3.12.2)
|
|
109
|
-
json (~> 1.4)
|
|
106
|
+
thor (>= 0.18.1, < 2.0)
|
|
107
|
+
rake (10.3.2)
|
|
110
108
|
rubyzip (0.9.9)
|
|
111
|
-
simplecov (0.
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
109
|
+
simplecov (0.9.0)
|
|
110
|
+
docile (~> 1.1.0)
|
|
111
|
+
multi_json
|
|
112
|
+
simplecov-html (~> 0.8.0)
|
|
113
|
+
simplecov-html (0.8.0)
|
|
114
|
+
slop (3.6.0)
|
|
115
|
+
sprockets (2.12.1)
|
|
117
116
|
hike (~> 1.2)
|
|
118
117
|
multi_json (~> 1.0)
|
|
119
118
|
rack (~> 1.0)
|
|
120
119
|
tilt (~> 1.1, != 1.3.0)
|
|
121
|
-
|
|
120
|
+
sprockets-rails (2.1.3)
|
|
121
|
+
actionpack (>= 3.0)
|
|
122
|
+
activesupport (>= 3.0)
|
|
123
|
+
sprockets (~> 2.8)
|
|
124
|
+
thor (0.19.1)
|
|
125
|
+
thread_safe (0.3.4)
|
|
122
126
|
tilt (1.4.1)
|
|
123
127
|
treetop (1.4.15)
|
|
124
128
|
polyglot
|
|
125
129
|
polyglot (>= 0.3.1)
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
tzinfo (0.3.38)
|
|
130
|
+
tzinfo (1.2.2)
|
|
131
|
+
thread_safe (~> 0.1)
|
|
129
132
|
|
|
130
133
|
PLATFORMS
|
|
131
134
|
ruby
|
|
132
135
|
|
|
133
136
|
DEPENDENCIES
|
|
134
|
-
minitest (~> 4.0)
|
|
137
|
+
minitest (~> 5.4.0)
|
|
135
138
|
pry
|
|
136
139
|
pry-nav
|
|
137
140
|
pry-rescue
|
|
138
141
|
pry-stack_explorer
|
|
139
142
|
quality-measure-engine!
|
|
140
|
-
rails (~>
|
|
141
|
-
simplecov (~> 0.
|
|
142
|
-
turn
|
|
143
|
+
rails (~> 4.1.5)
|
|
144
|
+
simplecov (~> 0.9.0)
|
data/README.md
CHANGED
|
@@ -11,7 +11,7 @@ Results of quality measures are represented by QME::QualityReport. This class pr
|
|
|
11
11
|
Environment
|
|
12
12
|
===========
|
|
13
13
|
|
|
14
|
-
This project currently uses Ruby 1.
|
|
14
|
+
This project currently uses Ruby 2.1.X and is built using [Bundler](http://gembundler.com/). To get all of the dependencies for the project, first install bundler:
|
|
15
15
|
|
|
16
16
|
gem install bundler
|
|
17
17
|
|
|
@@ -19,23 +19,10 @@ Then run bundler to grab all of the necessary gems:
|
|
|
19
19
|
|
|
20
20
|
bundle install
|
|
21
21
|
|
|
22
|
-
The Quality Measure engine relies on a MongoDB [MongoDB](http://www.mongodb.org/) running a minimum of version 2.
|
|
22
|
+
The Quality Measure engine relies on a MongoDB [MongoDB](http://www.mongodb.org/) running a minimum of version 2.6.* or higher. To get and install Mongo refer to:
|
|
23
23
|
|
|
24
24
|
http://www.mongodb.org/display/DOCS/Quickstart
|
|
25
25
|
|
|
26
|
-
It also relies on [Redis](http://redis.io/) for background jobs via [Resque](https://github.com/defunkt/resque). To install Redis, please refer to:
|
|
27
|
-
|
|
28
|
-
http://redis.io/download
|
|
29
|
-
|
|
30
|
-
You can also find information on Redis at the [Resque homepage](https://github.com/defunkt/resque). Resque is used by this project to calculate quality measures in background jobs. We also use [resque-status](https://github.com/quirkey/resque-status). Please consult the resque-status instructions for working with the resque-web application if you would like to use it to monitor status.
|
|
31
|
-
|
|
32
|
-
Running Resque Workers
|
|
33
|
-
----------------------
|
|
34
|
-
|
|
35
|
-
QME::QualityReport will kick off background jobs with Resque. For these jobs to to actually get performed, you need to be running resque workers. This can be done with the following:
|
|
36
|
-
|
|
37
|
-
QUEUE=* bundle exec rake resque:work
|
|
38
|
-
|
|
39
26
|
Testing
|
|
40
27
|
=======
|
|
41
28
|
|
|
@@ -43,17 +30,17 @@ This project uses [minitest](https://github.com/seattlerb/minitest) for testing.
|
|
|
43
30
|
|
|
44
31
|
bundle exec rake test
|
|
45
32
|
|
|
46
|
-
The coverage of the test suite is monitored with [
|
|
33
|
+
The coverage of the test suite is monitored with [simplecov](https://github.com/colszowka/simplecov). You can see the code coverage by looking in the coverage directory after running the test suite
|
|
47
34
|
|
|
48
35
|
Project Practices
|
|
49
36
|
=================
|
|
50
37
|
|
|
51
|
-
Please try to follow
|
|
38
|
+
Please try to follow the [GitHub Coding Style Guides](https://github.com/styleguide). Additionally, we are switching to the git workflow described in [Juan Batiz-Benet's Gist](https://gist.github.com/jbenet/ee6c9ac48068889b0912). If you are new to the project and would like to make changes, please fork and do your work in a feature branch. Submit a pull request and we'll check to see if it is suitable to be merged in.
|
|
52
39
|
|
|
53
40
|
License
|
|
54
41
|
=======
|
|
55
42
|
|
|
56
|
-
Copyright
|
|
43
|
+
Copyright 2014 The MITRE Corporation
|
|
57
44
|
|
|
58
45
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
59
46
|
you may not use this file except in compliance with the License.
|
|
@@ -3,7 +3,7 @@ require 'ostruct'
|
|
|
3
3
|
|
|
4
4
|
module QME
|
|
5
5
|
module MapReduce
|
|
6
|
-
|
|
6
|
+
|
|
7
7
|
# Builds Map and Reduce functions for a particular measure
|
|
8
8
|
class Builder
|
|
9
9
|
attr_reader :id, :params
|
|
@@ -11,19 +11,19 @@ module QME
|
|
|
11
11
|
# Utility class used to supply a binding to Erb
|
|
12
12
|
class Context < OpenStruct
|
|
13
13
|
# Create a new context
|
|
14
|
-
# @param [Hash] vars a hash of parameter names (String) and values (Object). Each
|
|
14
|
+
# @param [Hash] vars a hash of parameter names (String) and values (Object). Each
|
|
15
15
|
# entry is added as an accessor of the new Context
|
|
16
16
|
def initialize(db, vars)
|
|
17
17
|
super(Context.add_defaults(vars))
|
|
18
18
|
@db = db
|
|
19
19
|
end
|
|
20
|
-
|
|
20
|
+
|
|
21
21
|
# Get a binding that contains all the instance variables
|
|
22
22
|
# @return [Binding]
|
|
23
23
|
def get_binding
|
|
24
24
|
binding
|
|
25
25
|
end
|
|
26
|
-
|
|
26
|
+
|
|
27
27
|
# Add default parameter values if not specified
|
|
28
28
|
def self.add_defaults(vars)
|
|
29
29
|
if !vars.has_key?('enable_logging')
|
|
@@ -34,7 +34,7 @@ module QME
|
|
|
34
34
|
end
|
|
35
35
|
vars
|
|
36
36
|
end
|
|
37
|
-
|
|
37
|
+
|
|
38
38
|
# Inserts any library code into the measure JS. JS library code is loaded from
|
|
39
39
|
# three locations: the js directory of the quality-measure-engine project, the
|
|
40
40
|
# js sub-directory of the current directory (e.g. measures/js), and the bundles
|
|
@@ -60,7 +60,7 @@ module QME
|
|
|
60
60
|
@id = measure_def['id']
|
|
61
61
|
@params = {}
|
|
62
62
|
@db = db
|
|
63
|
-
|
|
63
|
+
|
|
64
64
|
# normalize parameters hash to accept either symbol or string keys
|
|
65
65
|
params.each do |name, value|
|
|
66
66
|
@params[name.to_s] = value
|
|
@@ -93,11 +93,12 @@ module QME
|
|
|
93
93
|
# map-reduce-utils.js
|
|
94
94
|
# @return [String] the reduce function
|
|
95
95
|
def finalize_function
|
|
96
|
-
|
|
97
|
-
|
|
96
|
+
reporting_period_start = Time.at(@params['effective_date']).prev_year.to_i
|
|
97
|
+
reduce =
|
|
98
|
+
"function (key, value) {
|
|
98
99
|
var patient = value;
|
|
99
100
|
patient.measure_id = \"#{@measure_def['id']}\";\n"
|
|
100
|
-
if @params['test_id'] && @params['test_id'].class==
|
|
101
|
+
if @params['test_id'] && @params['test_id'].class==BSON::ObjectId
|
|
101
102
|
reduce += " patient.test_id = new ObjectId(\"#{@params['test_id']}\");\n"
|
|
102
103
|
end
|
|
103
104
|
if @measure_def.sub_id
|
|
@@ -106,20 +107,33 @@ module QME
|
|
|
106
107
|
if @measure_def.nqf_id
|
|
107
108
|
reduce += " patient.nqf_id = \"#{@measure_def.nqf_id}\";\n"
|
|
108
109
|
end
|
|
109
|
-
|
|
110
|
+
|
|
110
111
|
reduce += "patient.effective_date = #{@params['effective_date']};
|
|
111
112
|
if (patient.provider_performances) {
|
|
112
113
|
var tmp = [];
|
|
113
114
|
for(var i=0; i<patient.provider_performances.length; i++) {
|
|
114
115
|
var value = patient.provider_performances[i];
|
|
115
|
-
if (
|
|
116
|
+
if (
|
|
117
|
+
// Early Overlap
|
|
118
|
+
((value['start_date'] <= #{reporting_period_start} || value['start_date'] == null) && (value['end_date'] > #{reporting_period_start})) ||
|
|
119
|
+
// Late Overlap
|
|
120
|
+
((value['start_date'] < #{@params['effective_date']}) && (value['end_date'] >= #{@params['effective_date']} || value['end_date'] == null)) ||
|
|
121
|
+
// Full Overlap
|
|
122
|
+
((value['start_date'] <= #{reporting_period_start} || value['start_date'] == null) && (value['end_date'] >= #{@params['effective_date']} || value['end_date'] == null)) ||
|
|
123
|
+
// Full Containment
|
|
124
|
+
(value['start_date'] > #{reporting_period_start} && value['end_date'] < #{@params['effective_date']})
|
|
125
|
+
)
|
|
116
126
|
tmp.push(value);
|
|
117
127
|
}
|
|
118
|
-
if (tmp.length
|
|
119
|
-
|
|
128
|
+
if (tmp.length > 0) {
|
|
129
|
+
patient.provider_performances = tmp;
|
|
130
|
+
} else {
|
|
131
|
+
sortedProviders = _.sortBy(patient.provider_performances, function(performance){return performance['end_date']});
|
|
132
|
+
patient.provider_performances = [_.last(sortedProviders)];
|
|
133
|
+
}
|
|
120
134
|
}
|
|
121
135
|
return patient;}"
|
|
122
|
-
|
|
136
|
+
|
|
123
137
|
reduce
|
|
124
138
|
end
|
|
125
139
|
|
|
@@ -52,9 +52,9 @@ module QME
|
|
|
52
52
|
match['value.gender'] = {'$in' => filters['genders']}
|
|
53
53
|
end
|
|
54
54
|
if (filters['providers'] && filters['providers'].size > 0)
|
|
55
|
-
providers = filters['providers'].map { |pv| {'providers' =>
|
|
56
|
-
pipeline.concat [{'$project' => {'value' => 1, 'providers' => "$value.provider_performances.provider_id"}},
|
|
57
|
-
{'$unwind' => '$providers'},
|
|
55
|
+
providers = filters['providers'].map { |pv| {'providers' => BSON::ObjectId.from_string(pv) } }
|
|
56
|
+
pipeline.concat [{'$project' => {'value' => 1, 'providers' => "$value.provider_performances.provider_id"}},
|
|
57
|
+
{'$unwind' => '$providers'},
|
|
58
58
|
{'$match' => {'$or' => providers}},
|
|
59
59
|
{'$group' => {"_id" => "$_id", "value" => {"$first" => "$value"}}}]
|
|
60
60
|
end
|
data/lib/qme/quality_measure.rb
CHANGED
|
@@ -4,13 +4,12 @@ module QME
|
|
|
4
4
|
include Mongoid::Document
|
|
5
5
|
store_in collection: 'measures'
|
|
6
6
|
|
|
7
|
-
field :id, type: String
|
|
7
|
+
field :id, as: :id, type: String
|
|
8
8
|
field :sub_id, type: String
|
|
9
9
|
field :map_fn, type: String
|
|
10
10
|
field :nqf_id, type: String
|
|
11
11
|
field :continuous_variable, type: Boolean, default: false
|
|
12
12
|
field :aggregator, type: String
|
|
13
|
-
field :map_fn, type: String
|
|
14
13
|
field :population_ids, type: Hash
|
|
15
14
|
field :parameters, type: Hash, default: {}
|
|
16
15
|
|
data/lib/qme/quality_report.rb
CHANGED
|
@@ -34,6 +34,7 @@ module QME
|
|
|
34
34
|
field :test_id
|
|
35
35
|
field :effective_date, type: Integer
|
|
36
36
|
field :filters, type: Hash
|
|
37
|
+
field :prefilter, type: Hash
|
|
37
38
|
embeds_one :result, class_name: "QME::QualityReportResult", inverse_of: :quality_report
|
|
38
39
|
index "measure_id" => 1
|
|
39
40
|
index "sub_id" => 1
|
|
@@ -197,7 +198,7 @@ module QME
|
|
|
197
198
|
match['value.gender'] = {'$in' => filters['genders']}
|
|
198
199
|
end
|
|
199
200
|
if (filters['providers'] && filters['providers'].size > 0)
|
|
200
|
-
providers = filters['providers'].map { |pv|
|
|
201
|
+
providers = filters['providers'].map { |pv| BSON::ObjectId.from_string(pv) }
|
|
201
202
|
match['value.provider_performances.provider_id'] = {'$in' => providers}
|
|
202
203
|
end
|
|
203
204
|
if (filters['languages'] && filters['languages'].size > 0)
|
|
@@ -209,15 +210,15 @@ module QME
|
|
|
209
210
|
|
|
210
211
|
protected
|
|
211
212
|
|
|
212
|
-
#In the older version of QME QualityReport was not treated as
|
|
213
|
+
# In the older version of QME QualityReport was not treated as a persisted object. As
|
|
213
214
|
# a result anytime you wanted to get the cached results for a calculation you would create
|
|
214
215
|
# a new QR object which would then go to the db and see if the calculation was performed or
|
|
215
|
-
# not yet and then return the results.
|
|
216
|
+
# not yet and then return the results. Now that QR objects are persisted you need to go through
|
|
216
217
|
# the find_or_create by method to ensure that duplicate entries are not being created. Protecting
|
|
217
218
|
# this method causes an exception to be thrown for anyone attempting to use this version of QME with the
|
|
218
|
-
# sematics of the older version to highlight the issue
|
|
219
|
-
def initialize(attrs = nil
|
|
220
|
-
super(attrs
|
|
219
|
+
# sematics of the older version to highlight the issue.
|
|
220
|
+
def initialize(attrs = nil)
|
|
221
|
+
super(attrs)
|
|
221
222
|
end
|
|
222
223
|
|
|
223
224
|
def self.enque_job(options,queue)
|
data/lib/qme/version.rb
CHANGED
|
@@ -17,12 +17,12 @@ Gem::Specification.new do |gem|
|
|
|
17
17
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
|
18
18
|
gem.require_paths = ["lib"]
|
|
19
19
|
|
|
20
|
-
gem.add_dependency 'moped', '~>
|
|
21
|
-
gem.add_dependency 'mongoid', '~>
|
|
20
|
+
gem.add_dependency 'moped', '~> 2.0.0'
|
|
21
|
+
gem.add_dependency 'mongoid', '~> 4.0.0'
|
|
22
22
|
gem.add_dependency 'rubyzip', '~> 0.9.9'
|
|
23
|
-
gem.add_dependency 'delayed_job_mongoid', '~> 2.
|
|
23
|
+
gem.add_dependency 'delayed_job_mongoid', '~> 2.1.0'
|
|
24
24
|
|
|
25
|
-
gem.add_development_dependency "minitest", "~> 4.
|
|
26
|
-
gem.add_development_dependency "simplecov", "~> 0.
|
|
27
|
-
gem.add_development_dependency "rails", "~>
|
|
25
|
+
gem.add_development_dependency "minitest", "~> 5.4.0"
|
|
26
|
+
gem.add_development_dependency "simplecov", "~> 0.9.0"
|
|
27
|
+
gem.add_development_dependency "rails", "~> 4.1.5"
|
|
28
28
|
end
|
|
@@ -446,7 +446,7 @@
|
|
|
446
446
|
"codes": {
|
|
447
447
|
"SNOMED-CT": [
|
|
448
448
|
"273447005"
|
|
449
|
-
]
|
|
449
|
+
]
|
|
450
450
|
},
|
|
451
451
|
"start_time": 1269762691,
|
|
452
452
|
"end_time": 1269762693,
|
|
@@ -462,11 +462,18 @@
|
|
|
462
462
|
"codes": {
|
|
463
463
|
"SNOMED-CT": [
|
|
464
464
|
"273447005"
|
|
465
|
-
]
|
|
465
|
+
]
|
|
466
466
|
},
|
|
467
467
|
"start_time": 1269762691,
|
|
468
468
|
"end_time": 1269762693,
|
|
469
469
|
"anatomicalStructure" : {"code": "13648007", "codeSystem": "SNOMED-CT"}
|
|
470
470
|
}
|
|
471
|
+
],
|
|
472
|
+
"provider_performances" : [
|
|
473
|
+
{
|
|
474
|
+
"start_date" : 946684800,
|
|
475
|
+
"end_date" : 1291161600,
|
|
476
|
+
"provider_id" : "early_overlap"
|
|
477
|
+
}
|
|
471
478
|
]
|
|
472
479
|
}
|
|
@@ -82,6 +82,18 @@
|
|
|
82
82
|
}
|
|
83
83
|
}
|
|
84
84
|
],
|
|
85
|
+
"provider_performances" : [
|
|
86
|
+
{
|
|
87
|
+
"start_date" : 2,
|
|
88
|
+
"end_date" : 7200,
|
|
89
|
+
"provider_id" : "waaay_too_early_provider"
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
"start_date" : 946684800,
|
|
93
|
+
"end_date" : 978307200,
|
|
94
|
+
"provider_id" : "too_early_provider"
|
|
95
|
+
}
|
|
96
|
+
],
|
|
85
97
|
"vital_signs": [
|
|
86
98
|
{
|
|
87
99
|
"codes": {
|
data/test/test_helper.rb
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
require 'simplecov_setup'
|
|
2
2
|
require 'minitest/autorun'
|
|
3
3
|
require 'quality-measure-engine'
|
|
4
|
-
require 'test/unit'
|
|
5
|
-
require 'turn'
|
|
6
4
|
require 'pry-nav'
|
|
5
|
+
|
|
7
6
|
Mongoid.load!(File.join(File.dirname(__FILE__),"mongoid.yml"), :test)
|
|
8
7
|
|
|
9
8
|
class MiniTest::Unit::TestCase
|
|
@@ -16,22 +15,22 @@ class MiniTest::Unit::TestCase
|
|
|
16
15
|
Mongoid.default_session['system.js'].find('_id' => name).upsert(
|
|
17
16
|
{
|
|
18
17
|
"_id" => name,
|
|
19
|
-
"value" =>
|
|
18
|
+
"value" => BSON::Code.new(fn)
|
|
20
19
|
}
|
|
21
20
|
)
|
|
22
21
|
end
|
|
23
|
-
|
|
22
|
+
|
|
24
23
|
end
|
|
25
24
|
|
|
26
25
|
# Add more helper methods to be used by all tests here...
|
|
27
|
-
|
|
26
|
+
|
|
28
27
|
def collection_fixtures(db, collection, *id_attributes)
|
|
29
28
|
db[collection].drop
|
|
30
29
|
Dir.glob(File.join(File.dirname(__FILE__), 'fixtures', collection, '*.json')).each do |json_fixture_file|
|
|
31
30
|
#puts "Loading #{json_fixture_file}"
|
|
32
31
|
fixture_json = JSON.parse(File.read(json_fixture_file))
|
|
33
32
|
id_attributes.each do |attr|
|
|
34
|
-
fixture_json[attr] =
|
|
33
|
+
fixture_json[attr] = BSON::ObjectId.from_string(fixture_json[attr])
|
|
35
34
|
end
|
|
36
35
|
|
|
37
36
|
db[collection].insert(fixture_json)
|
|
@@ -19,9 +19,9 @@ class MapReduceExecutorTest < MiniTest::Unit::TestCase
|
|
|
19
19
|
def test_map_records_into_measure_groups
|
|
20
20
|
executor = QME::MapReduce::Executor.new(@quality_report.measure_id,@quality_report.sub_id, {
|
|
21
21
|
'effective_date' => Time.gm(2011, 1, 15).to_i})
|
|
22
|
-
|
|
22
|
+
|
|
23
23
|
executor.map_records_into_measure_groups
|
|
24
|
-
|
|
24
|
+
|
|
25
25
|
|
|
26
26
|
assert_equal 4, get_db['patient_cache'].find().count
|
|
27
27
|
assert_equal 3, get_db['patient_cache'].find("value.#{QME::QualityReport::POPULATION}" => 1).count
|
|
@@ -31,13 +31,13 @@ class MapReduceExecutorTest < MiniTest::Unit::TestCase
|
|
|
31
31
|
end
|
|
32
32
|
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
def test_calculate_supplemental_data_elements
|
|
35
35
|
executor = QME::MapReduce::Executor.new(@quality_report.measure_id,@quality_report.sub_id, {
|
|
36
36
|
'effective_date' => Time.gm(2011, 1, 15).to_i})
|
|
37
|
-
|
|
37
|
+
|
|
38
38
|
executor.map_records_into_measure_groups
|
|
39
39
|
result = executor.count_records_in_measure_groups
|
|
40
|
-
|
|
40
|
+
|
|
41
41
|
suppl = result["supplemental_data"]
|
|
42
42
|
|
|
43
43
|
assert !suppl.empty?, "should contain supplemental data entries"
|
|
@@ -59,13 +59,13 @@ class MapReduceExecutorTest < MiniTest::Unit::TestCase
|
|
|
59
59
|
QME::QualityReport::SEX => {"F"=>1}
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
|
|
62
|
+
|
|
63
63
|
|
|
64
64
|
assert_equal ipp, suppl[QME::QualityReport::POPULATION]
|
|
65
65
|
assert_equal denom, suppl[QME::QualityReport::DENOMINATOR]
|
|
66
66
|
assert_equal numer, suppl[QME::QualityReport::NUMERATOR]
|
|
67
67
|
|
|
68
|
-
|
|
68
|
+
|
|
69
69
|
end
|
|
70
70
|
|
|
71
71
|
def test_count_records_in_measure_groups
|
|
@@ -79,7 +79,7 @@ class MapReduceExecutorTest < MiniTest::Unit::TestCase
|
|
|
79
79
|
|
|
80
80
|
executor = QME::MapReduce::Executor.new(@quality_report.measure_id,@quality_report.sub_id, {
|
|
81
81
|
'effective_date' => Time.gm(2011, 1, 14).to_i})
|
|
82
|
-
|
|
82
|
+
|
|
83
83
|
result = executor.count_records_in_measure_groups
|
|
84
84
|
assert_equal 0, result[QME::QualityReport::POPULATION]
|
|
85
85
|
assert_equal 0, result[QME::QualityReport::DENOMINATOR]
|
|
@@ -106,6 +106,14 @@ class MapReduceExecutorTest < MiniTest::Unit::TestCase
|
|
|
106
106
|
assert result[QME::QualityReport::NUMERATOR]
|
|
107
107
|
end
|
|
108
108
|
|
|
109
|
+
def test_provider_assignment
|
|
110
|
+
executor = QME::MapReduce::Executor.new(@quality_report.measure_id,@quality_report.sub_id, {
|
|
111
|
+
'effective_date' => Time.gm(2011, 1, 15).to_i})
|
|
112
|
+
executor.map_records_into_measure_groups
|
|
113
|
+
assert_equal 4, get_db['patient_cache'].find("value.provider_performances" => {'$size' => 1}).count
|
|
114
|
+
assert_equal 1, QME::PatientCache.where('value.medical_record_id' => '12345', 'value.provider_performances.provider_id' => 'too_early_provider').count
|
|
115
|
+
end
|
|
116
|
+
|
|
109
117
|
def test_get_patient_result_with_bundle_id
|
|
110
118
|
measure_id = "2E679CD2-3FEC-4A75-A75A-61403E5EFEE8"
|
|
111
119
|
bundle_id = get_db()['bundles'].find.first
|
|
@@ -2,11 +2,12 @@ require 'test_helper'
|
|
|
2
2
|
|
|
3
3
|
class QualityReportTest < MiniTest::Unit::TestCase
|
|
4
4
|
include QME::DatabaseAccess
|
|
5
|
-
|
|
5
|
+
|
|
6
6
|
def setup
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
load_system_js
|
|
8
|
+
collection_fixtures(get_db(), 'bundles')
|
|
9
|
+
collection_fixtures(get_db(), 'records')
|
|
10
|
+
collection_fixtures(get_db(), 'measures')
|
|
10
11
|
get_db()['query_cache'].drop()
|
|
11
12
|
get_db()['patient_cache'].drop()
|
|
12
13
|
get_db()['query_cache'].insert(
|
|
@@ -44,7 +45,7 @@ class QualityReportTest < MiniTest::Unit::TestCase
|
|
|
44
45
|
},
|
|
45
46
|
"measure_id" => "test2",
|
|
46
47
|
"sub_id" => "b",
|
|
47
|
-
"effective_date" => Time.gm(2010, 9, 19).to_i
|
|
48
|
+
"effective_date" => Time.gm(2010, 9, 19).to_i
|
|
48
49
|
}
|
|
49
50
|
)
|
|
50
51
|
collection_fixtures(get_db(), 'delayed_backend_mongoid_jobs', '_id')
|
|
@@ -53,25 +54,25 @@ class QualityReportTest < MiniTest::Unit::TestCase
|
|
|
53
54
|
def test_calculated
|
|
54
55
|
qr = QME::QualityReport.find_or_create('test2', 'b', "effective_date" => Time.gm(2010, 9, 19).to_i)
|
|
55
56
|
assert qr.calculated?
|
|
56
|
-
|
|
57
|
+
|
|
57
58
|
qr = QME::QualityReport.find_or_create('test2', 'b', "effective_date" => Time.gm(2010, 9, 20).to_i)
|
|
58
59
|
assert !qr.calculated?
|
|
59
60
|
end
|
|
60
|
-
|
|
61
|
+
|
|
61
62
|
def test_result
|
|
62
63
|
qr = QME::QualityReport.find_or_create('test2', 'b', "effective_date" => Time.gm(2010, 9, 19).to_i)
|
|
63
64
|
result = qr.result
|
|
64
|
-
|
|
65
|
+
|
|
65
66
|
assert_equal 1, result[QME::QualityReport::NUMERATOR]
|
|
66
67
|
end
|
|
67
|
-
|
|
68
|
+
|
|
68
69
|
def test_destroy_all
|
|
69
70
|
QME::QualityReport.destroy_all
|
|
70
|
-
|
|
71
|
+
|
|
71
72
|
qr = QME::QualityReport.find_or_create('test2', 'b', "effective_date" => Time.gm(2010, 9, 19).to_i)
|
|
72
73
|
assert !qr.calculated?
|
|
73
74
|
end
|
|
74
|
-
|
|
75
|
+
|
|
75
76
|
def test_update_patient_results
|
|
76
77
|
qr = QME::QualityReport.find_or_create('test2', 'b', "effective_date" => Time.gm(2010, 9, 19).to_i)
|
|
77
78
|
assert qr.calculated?
|
|
@@ -83,7 +84,6 @@ class QualityReportTest < MiniTest::Unit::TestCase
|
|
|
83
84
|
end
|
|
84
85
|
|
|
85
86
|
def test_status
|
|
86
|
-
|
|
87
87
|
status = QME::MapReduce::MeasureCalculationJob.status('not really a job id')
|
|
88
88
|
assert_equal :complete, status
|
|
89
89
|
status = QME::MapReduce::MeasureCalculationJob.status("508aeff07042f9f88900000d")
|
|
@@ -106,7 +106,7 @@ class QualityReportTest < MiniTest::Unit::TestCase
|
|
|
106
106
|
|
|
107
107
|
assert !qr.calculation_queued_or_running?
|
|
108
108
|
assert !qr2.calculation_queued_or_running?
|
|
109
|
-
|
|
109
|
+
|
|
110
110
|
qr.calculate({"oid_dictionary"=>{}},true)
|
|
111
111
|
|
|
112
112
|
assert qr.calculation_queued_or_running?
|
|
@@ -129,6 +129,4 @@ class QualityReportTest < MiniTest::Unit::TestCase
|
|
|
129
129
|
|
|
130
130
|
assert_equal 0, Mongoid.default_session["rollup_buffer"].find({}).count
|
|
131
131
|
end
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
end
|
|
132
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: quality-measure-engine
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.0.
|
|
4
|
+
version: 3.0.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Marc Hadley
|
|
@@ -12,7 +12,7 @@ authors:
|
|
|
12
12
|
autorequire:
|
|
13
13
|
bindir: bin
|
|
14
14
|
cert_chain: []
|
|
15
|
-
date: 2014-
|
|
15
|
+
date: 2014-08-27 00:00:00.000000000 Z
|
|
16
16
|
dependencies:
|
|
17
17
|
- !ruby/object:Gem::Dependency
|
|
18
18
|
name: moped
|
|
@@ -20,28 +20,28 @@ dependencies:
|
|
|
20
20
|
requirements:
|
|
21
21
|
- - "~>"
|
|
22
22
|
- !ruby/object:Gem::Version
|
|
23
|
-
version:
|
|
23
|
+
version: 2.0.0
|
|
24
24
|
type: :runtime
|
|
25
25
|
prerelease: false
|
|
26
26
|
version_requirements: !ruby/object:Gem::Requirement
|
|
27
27
|
requirements:
|
|
28
28
|
- - "~>"
|
|
29
29
|
- !ruby/object:Gem::Version
|
|
30
|
-
version:
|
|
30
|
+
version: 2.0.0
|
|
31
31
|
- !ruby/object:Gem::Dependency
|
|
32
32
|
name: mongoid
|
|
33
33
|
requirement: !ruby/object:Gem::Requirement
|
|
34
34
|
requirements:
|
|
35
35
|
- - "~>"
|
|
36
36
|
- !ruby/object:Gem::Version
|
|
37
|
-
version:
|
|
37
|
+
version: 4.0.0
|
|
38
38
|
type: :runtime
|
|
39
39
|
prerelease: false
|
|
40
40
|
version_requirements: !ruby/object:Gem::Requirement
|
|
41
41
|
requirements:
|
|
42
42
|
- - "~>"
|
|
43
43
|
- !ruby/object:Gem::Version
|
|
44
|
-
version:
|
|
44
|
+
version: 4.0.0
|
|
45
45
|
- !ruby/object:Gem::Dependency
|
|
46
46
|
name: rubyzip
|
|
47
47
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -62,56 +62,56 @@ dependencies:
|
|
|
62
62
|
requirements:
|
|
63
63
|
- - "~>"
|
|
64
64
|
- !ruby/object:Gem::Version
|
|
65
|
-
version: 2.
|
|
65
|
+
version: 2.1.0
|
|
66
66
|
type: :runtime
|
|
67
67
|
prerelease: false
|
|
68
68
|
version_requirements: !ruby/object:Gem::Requirement
|
|
69
69
|
requirements:
|
|
70
70
|
- - "~>"
|
|
71
71
|
- !ruby/object:Gem::Version
|
|
72
|
-
version: 2.
|
|
72
|
+
version: 2.1.0
|
|
73
73
|
- !ruby/object:Gem::Dependency
|
|
74
74
|
name: minitest
|
|
75
75
|
requirement: !ruby/object:Gem::Requirement
|
|
76
76
|
requirements:
|
|
77
77
|
- - "~>"
|
|
78
78
|
- !ruby/object:Gem::Version
|
|
79
|
-
version: 4.
|
|
79
|
+
version: 5.4.0
|
|
80
80
|
type: :development
|
|
81
81
|
prerelease: false
|
|
82
82
|
version_requirements: !ruby/object:Gem::Requirement
|
|
83
83
|
requirements:
|
|
84
84
|
- - "~>"
|
|
85
85
|
- !ruby/object:Gem::Version
|
|
86
|
-
version: 4.
|
|
86
|
+
version: 5.4.0
|
|
87
87
|
- !ruby/object:Gem::Dependency
|
|
88
88
|
name: simplecov
|
|
89
89
|
requirement: !ruby/object:Gem::Requirement
|
|
90
90
|
requirements:
|
|
91
91
|
- - "~>"
|
|
92
92
|
- !ruby/object:Gem::Version
|
|
93
|
-
version: 0.
|
|
93
|
+
version: 0.9.0
|
|
94
94
|
type: :development
|
|
95
95
|
prerelease: false
|
|
96
96
|
version_requirements: !ruby/object:Gem::Requirement
|
|
97
97
|
requirements:
|
|
98
98
|
- - "~>"
|
|
99
99
|
- !ruby/object:Gem::Version
|
|
100
|
-
version: 0.
|
|
100
|
+
version: 0.9.0
|
|
101
101
|
- !ruby/object:Gem::Dependency
|
|
102
102
|
name: rails
|
|
103
103
|
requirement: !ruby/object:Gem::Requirement
|
|
104
104
|
requirements:
|
|
105
105
|
- - "~>"
|
|
106
106
|
- !ruby/object:Gem::Version
|
|
107
|
-
version:
|
|
107
|
+
version: 4.1.5
|
|
108
108
|
type: :development
|
|
109
109
|
prerelease: false
|
|
110
110
|
version_requirements: !ruby/object:Gem::Requirement
|
|
111
111
|
requirements:
|
|
112
112
|
- - "~>"
|
|
113
113
|
- !ruby/object:Gem::Version
|
|
114
|
-
version:
|
|
114
|
+
version: 4.1.5
|
|
115
115
|
description: A library for running clinical quality measures
|
|
116
116
|
email:
|
|
117
117
|
- talk@projectpophealth.org
|