quality-measure-engine 2.0.0 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.travis.yml CHANGED
@@ -1,7 +1,7 @@
1
1
  language: ruby
2
2
  rvm:
3
3
  - 1.9.3
4
- script: bundle exec rake spec
4
+ script: bundle exec rake test
5
5
  services:
6
6
  - mongodb
7
7
  notifications:
data/Gemfile CHANGED
@@ -4,4 +4,6 @@ source 'https://rubygems.org'
4
4
  gemspec
5
5
 
6
6
  gem 'pry'
7
- gem 'pry-nav'
7
+ gem 'pry-nav'
8
+ gem 'pry-rescue'
9
+ gem 'pry-stack_explorer'
data/Gemfile.lock CHANGED
@@ -1,10 +1,12 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- quality-measure-engine (2.0.0)
4
+ quality-measure-engine (2.1.0)
5
5
  delayed_job_mongoid (~> 2.0.0)
6
6
  mongoid (~> 3.0.9)
7
7
  moped (~> 1.2.7)
8
+ nokogiri (~> 1.5.5)
9
+ rubyXL (~> 1.2.10)
8
10
  rubyzip (~> 0.9.9)
9
11
 
10
12
  GEM
@@ -38,6 +40,7 @@ GEM
38
40
  i18n (~> 0.6)
39
41
  multi_json (~> 1.0)
40
42
  arel (3.0.2)
43
+ binding_of_caller (0.6.8)
41
44
  builder (3.0.4)
42
45
  coderay (1.0.8)
43
46
  delayed_job (3.0.3)
@@ -48,6 +51,7 @@ GEM
48
51
  erubis (2.7.0)
49
52
  hike (1.2.1)
50
53
  i18n (0.6.1)
54
+ interception (0.3)
51
55
  journey (1.0.4)
52
56
  json (1.7.5)
53
57
  mail (2.4.4)
@@ -64,7 +68,8 @@ GEM
64
68
  tzinfo (~> 0.3.22)
65
69
  moped (1.2.7)
66
70
  multi_json (1.3.6)
67
- origin (1.0.9)
71
+ nokogiri (1.5.5)
72
+ origin (1.0.10)
68
73
  polyglot (0.3.3)
69
74
  pry (0.9.10)
70
75
  coderay (~> 1.0.5)
@@ -72,6 +77,11 @@ GEM
72
77
  slop (~> 3.3.1)
73
78
  pry-nav (0.2.2)
74
79
  pry (~> 0.9.10)
80
+ pry-rescue (0.12)
81
+ interception (>= 0.3)
82
+ pry
83
+ pry-stack_explorer (0.4.7)
84
+ binding_of_caller (~> 0.6.8)
75
85
  rack (1.4.1)
76
86
  rack-cache (1.2)
77
87
  rack (>= 0.4)
@@ -97,6 +107,7 @@ GEM
97
107
  rake (0.9.2.2)
98
108
  rdoc (3.12)
99
109
  json (~> 1.4)
110
+ rubyXL (1.2.10)
100
111
  rubyzip (0.9.9)
101
112
  simplecov (0.7.1)
102
113
  multi_json (~> 1.0)
@@ -121,6 +132,8 @@ DEPENDENCIES
121
132
  minitest (~> 4.1.0)
122
133
  pry
123
134
  pry-nav
135
+ pry-rescue
136
+ pry-stack_explorer
124
137
  quality-measure-engine!
125
138
  rails (~> 3.2.8)
126
139
  simplecov (~> 0.7.1)
@@ -30,5 +30,19 @@ module QME
30
30
  def self.entry_key(original, extension)
31
31
  original.split('/').last.gsub(".#{extension}", '')
32
32
  end
33
+
34
+ def self.unpack_bundle_contents(zip)
35
+ bundle_contents = { bundle: nil, measures: {}, patients: {}, extensions: {}, results: {} }
36
+ Zip::ZipFile.open(zip.path) do |zipfile|
37
+ zipfile.entries.each do |entry|
38
+ bundle_contents[:bundle] = zipfile.read(entry.name) if entry.name.include? "bundle"
39
+ bundle_contents[:measures][Bundle.entry_key(entry.name, "json")] = zipfile.read(entry.name) if entry.name.match /^measures.*\.json$/
40
+ bundle_contents[:patients][Bundle.entry_key(entry.name, "json")] = zipfile.read(entry.name) if entry.name.match /^patients.*\.json$/ # Only need to import one of the formats
41
+ bundle_contents[:extensions][Bundle.entry_key(entry.name,"js")] = zipfile.read(entry.name) if entry.name.match /^library_functions.*\.js/
42
+ bundle_contents[:results][Bundle.entry_key(entry.name,"json")] = zipfile.read(entry.name) if entry.name.match /^results.*\.json/
43
+ end
44
+ end
45
+ bundle_contents
46
+ end
33
47
  end
34
48
  end
@@ -0,0 +1,114 @@
1
+ module QME
2
+ module Bundle
3
+ class EHMeasureSheet
4
+ attr_reader :query_cache_document, :patient_cache_documents,
5
+ :patient_updates
6
+
7
+ def initialize(db, sheet, effective_date=nil)
8
+ @db = db
9
+ @sheet = sheet
10
+ @effective_date = effective_date
11
+ @patient_cache_documents = []
12
+ @patient_updates = []
13
+ end
14
+
15
+ def parse
16
+ qc_document = {}
17
+ measure_info = extract_measure_info
18
+ qc_document['population_ids'] = measure_info
19
+ measure_doc = @db['measures'].where('population_ids' => measure_info).first
20
+ measure_ids = measure_doc.slice('sub_id', 'nqf_id')
21
+ measure_ids['measure_id'] = measure_doc['hqmf_id']
22
+ qc_document.merge!(measure_ids)
23
+ extract_patients(measure_ids)
24
+
25
+ qc_document['population'] = extract_data_from_cell("C#{@population_totals_row}")
26
+ qc_document['considered'] = @population_totals_row - 3 # header row, blank row and totals row
27
+ if cv_measure?
28
+ qc_document['msrpopl'] = extract_data_from_cell("E#{@population_totals_row}")
29
+ else
30
+ qc_document['denominator'] = extract_data_from_cell("D#{@population_totals_row}")
31
+ qc_document['numerator'] = extract_data_from_cell("E#{@population_totals_row}")
32
+ qc_document['antinumerator'] = qc_document['denominator'] - qc_document['numerator']
33
+ qc_document['exclusions'] = extract_data_from_cell("F#{@population_totals_row}")
34
+ qc_document['denexcep'] = extract_data_from_cell("G#{@population_totals_row}")
35
+ end
36
+
37
+ qc_document['test_id'] = nil
38
+ qc_document['filters'] = nil
39
+ qc_document['execution_time'] = 0
40
+ qc_document['effective_date'] = @effective_date
41
+
42
+ @query_cache_document = qc_document
43
+ end
44
+
45
+ def extract_patients(measure_ids)
46
+ row = 2
47
+ medical_record_number = extract_data_from_cell("B#{row}")
48
+ while medical_record_number.present?
49
+ patient_document = extract_patient(row, medical_record_number.to_s)
50
+ patient_document.merge!(measure_ids)
51
+ @patient_cache_documents << {'value' => patient_document}
52
+ @patient_updates << {'medical_record_number' => medical_record_number.to_s,
53
+ 'measure_id' => measure_ids['measure_id']}
54
+ row = row + 1
55
+ medical_record_number = extract_data_from_cell("B#{row}")
56
+ end
57
+
58
+ @population_totals_row = row + 1
59
+ end
60
+
61
+ def extract_measure_info
62
+ measure_info = {}
63
+ measure_info['IPP'] = extract_data_from_cell('I5')
64
+ if cv_measure?
65
+ measure_info['MSRPOPL'] = extract_data_from_cell('I10')
66
+ measure_info['stratification'] = extract_data_from_cell('I11') if extract_data_from_cell('I11').present?
67
+ else
68
+ measure_info['DENOM'] = extract_data_from_cell('I6')
69
+ measure_info['NUMER'] = extract_data_from_cell('I7')
70
+ measure_info['DENEXCEP'] = extract_data_from_cell('I8') if extract_data_from_cell('I8').present?
71
+ measure_info['DENEX'] = extract_data_from_cell('I9') if extract_data_from_cell('I9').present?
72
+ measure_info['stratification'] = extract_data_from_cell('I11') if extract_data_from_cell('I11').present?
73
+ end
74
+
75
+ measure_info
76
+ end
77
+
78
+ def extract_patient(row, medical_record_number)
79
+ record = @db['records'].where('medical_record_number' => medical_record_number).first
80
+ patient_document = record.slice('first', 'last', 'gender', 'birthdate', 'race',
81
+ 'ethnicity', 'languages')
82
+ patient_document['medical_record_id'] = medical_record_number
83
+ patient_document['patient_id'] = record['_id'].to_s
84
+ patient_document['population'] = extract_data_from_cell("C#{row}") || 0
85
+ if cv_measure?
86
+ patient_document['values'] = [extract_data_from_cell("E#{row}")]
87
+ else
88
+ patient_document['denominator'] = extract_data_from_cell("D#{row}") || 0
89
+ patient_document['numerator'] = extract_data_from_cell("E#{row}") || 0
90
+ patient_document['exclusions'] = extract_data_from_cell("F#{row}") || 0
91
+ patient_document['denexcep'] = extract_data_from_cell("G#{row}") || 0
92
+ patient_document['antinumerator'] = patient_document['denominator'] - patient_document['numerator']
93
+
94
+ end
95
+ patient_document['test_id'] = nil
96
+ patient_document['effective_date'] = @effective_date
97
+
98
+ patient_document
99
+ end
100
+
101
+ def cv_measure?
102
+ extract_data_from_cell('E1').eql?('MSRPOPL')
103
+ end
104
+
105
+ private
106
+
107
+ def extract_data_from_cell(cell_name)
108
+ row, column = RubyXL::Parser.convert_to_index(cell_name)
109
+ @sheet.sheet_data[row][column].try(:value)
110
+ end
111
+ end
112
+
113
+ end
114
+ end
@@ -0,0 +1,21 @@
1
+ module QME
2
+ module Bundle
3
+ class EHPatientImporter
4
+ def self.load(db, spreadsheet, effective_date=nil)
5
+ spreadsheet.worksheets.each do |worksheet|
6
+ ms = EHMeasureSheet.new(db, worksheet, effective_date)
7
+ ms.parse
8
+ qc_document = ms.query_cache_document
9
+ db['query_cache'].insert(qc_document)
10
+ ms.patient_cache_documents.each do |pcd|
11
+ db['patient_cache'].insert(pcd)
12
+ end
13
+ ms.patient_updates.each do |patient_update|
14
+ db['records'].find('medical_record_number' => patient_update['medical_record_number']).update(
15
+ '$push' => {'measure_ids' => patient_update['measure_id']})
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -18,16 +18,7 @@ module QME
18
18
  Bundle.drop_collections(@db) if delete_existing
19
19
 
20
20
  # Unpack content from the bundle.
21
- bundle_contents = { bundle: nil, measures: {}, patients: {}, extensions: {}, results: {} }
22
- Zip::ZipFile.open(zip.path) do |zipfile|
23
- zipfile.entries.each do |entry|
24
- bundle_contents[:bundle] = zipfile.read(entry.name) if entry.name.include? "bundle"
25
- bundle_contents[:measures][Bundle.entry_key(entry.name, "json")] = zipfile.read(entry.name) if entry.name.match /^measures.*\.json$/
26
- bundle_contents[:patients][Bundle.entry_key(entry.name, "json")] = zipfile.read(entry.name) if entry.name.match /^patients.*\.json$/ # Only need to import one of the formats
27
- bundle_contents[:extensions][Bundle.entry_key(entry.name,"js")] = zipfile.read(entry.name) if entry.name.match /^library_functions/
28
- bundle_contents[:results][Bundle.entry_key(entry.name,"json")] = zipfile.read(entry.name) if entry.name.match /^results/
29
- end
30
- end
21
+ bundle_contents = QME::Bundle.unpack_bundle_contents(zip)
31
22
 
32
23
  # Store all JS libraries.
33
24
  bundle_contents[:extensions].each do |key, contents|
@@ -63,6 +54,8 @@ module QME
63
54
  contents = JSON.parse(contents, {:max_nesting => 100})
64
55
  contents.each {|document| @db[collection].insert(document)}
65
56
  end
57
+
58
+ bundle_contents
66
59
  end
67
60
  end
68
61
  end
@@ -4,11 +4,90 @@ db_name = ENV['DB_NAME'] || 'test'
4
4
 
5
5
  namespace :bundle do
6
6
  desc 'Import a quality bundle into the database.'
7
- task :import, :bundle_path, :delete_existing, :needs => :environment do |task, args|
7
+ task :import, [:bundle_path, :delete_existing] => [:environment] do |task, args|
8
8
  raise "The path to the measures zip file must be specified" unless args.bundle_path
9
9
 
10
10
  bundle = File.open(args.bundle_path)
11
11
  importer = QME::Bundle::Importer.new(db_name)
12
- importer.import(bundle, args.delete_existing)
12
+ bundle_contents = importer.import(bundle, args.delete_existing == "true")
13
+
14
+ puts "Successfully imported bundle at: #{args.bundle_path}"
15
+ puts "\t Imported into environment: #{Rails.env.upcase}" if defined? Rails
16
+ puts "\t Measures Loaded: #{bundle_contents[:measures].count}"
17
+ puts "\t Test Patients Loaded: #{bundle_contents[:patients].count}"
18
+ puts "\t Extensions Loaded: #{bundle_contents[:extensions].count}"
19
+
13
20
  end
14
- end
21
+
22
+ # this task is most likely temporary. Once Bonnie can handle both EP and EH measures together, this would no longer be required.
23
+ desc 'Merge two bundles into one.'
24
+ task :merge, [:bundle_one,:bundle_two] do |t, args|
25
+ raise "Two bundle zip file paths to be merged must be specified" unless args.bundle_one && args.bundle_two
26
+
27
+ tmpdir = Dir.mktmpdir
28
+ ['measures','patients','library_functions','results', 'sources'].each do |dir|
29
+
30
+ FileUtils.mkdir_p(File.join(tmpdir, 'output', dir))
31
+
32
+ end
33
+
34
+ begin
35
+
36
+ ({'one'=>args.bundle_one,'two'=>args.bundle_two}).each do |key, source|
37
+ Zip::ZipFile.open(source) do |zip_file|
38
+ zip_file.each do |f|
39
+ f_path=File.join(tmpdir, key, f.name)
40
+ FileUtils.mkdir_p(File.dirname(f_path))
41
+ zip_file.extract(f, f_path) unless File.exist?(f_path)
42
+ end
43
+ end
44
+ end
45
+
46
+
47
+ ['measures','patients','library_functions', 'sources'].each do |dir|
48
+ ['one','two'].each do |key|
49
+ FileUtils.mv(Dir.glob(File.join(tmpdir,key,dir,'*')), File.join(tmpdir,'output',dir))
50
+ end
51
+ end
52
+
53
+ Dir.glob(File.join(tmpdir,'one','results','*.json')).each do |result_path_one|
54
+ json_one = JSON.parse(File.new(result_path_one).read)
55
+ result_filename = Pathname.new(result_path_one).basename.to_s
56
+ json_two = JSON.parse(File.new(File.join(tmpdir,'two','results',result_filename)).read)
57
+ File.open(File.join(tmpdir,'output','results',result_filename), 'w') {|f| f.write(JSON.pretty_generate(json_one + json_two)) }
58
+ end
59
+
60
+ json_one = JSON.parse(File.new(File.join(tmpdir,'one','bundle.json')).read)
61
+ json_two = JSON.parse(File.new(File.join(tmpdir,'two','bundle.json')).read)
62
+ json_out = {}
63
+
64
+ ['title','effective_date','version','license','exported'].each do |key|
65
+ json_out[key] = json_one[key]
66
+ end
67
+
68
+ ['measures','patients','extensions'].each do |key|
69
+ json_out[key] = (json_one[key] + json_two[key]).uniq
70
+ end
71
+
72
+ File.open(File.join(tmpdir,'output','bundle.json'), 'w') {|f| f.write(JSON.pretty_generate(json_out)) }
73
+ date_string = Time.now.strftime("%Y-%m-%d")
74
+
75
+ out_zip = File.join('tmp','bundles',"bundle-merged-#{date_string}.zip")
76
+ FileUtils.remove_entry_secure out_zip if File.exists?(out_zip)
77
+ Zip::ZipFile.open(out_zip, 'w') do |zipfile|
78
+ path = File.join(tmpdir,'output')
79
+ Dir[File.join(path,'**','**')].each do |file|
80
+ zipfile.add(file.sub(path+'/',''),file)
81
+ end
82
+ end
83
+
84
+ puts "wrote merged bundle to: #{out_zip}"
85
+
86
+ ensure
87
+ FileUtils.remove_entry_secure tmpdir
88
+ end
89
+
90
+
91
+ end
92
+
93
+ end
data/lib/qme/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module QME
2
- VERSION = "2.0.0"
2
+ VERSION = "2.1.0"
3
3
  end
@@ -3,6 +3,7 @@ require "bundler/setup"
3
3
  require 'moped'
4
4
  require 'delayed_job_mongoid'
5
5
  require 'zip/zip'
6
+ require 'rubyXL'
6
7
 
7
8
  require "qme/version"
8
9
  require 'qme/database_access'
@@ -14,6 +15,8 @@ require 'qme/map/measure_calculation_job'
14
15
 
15
16
  require 'qme/quality_report'
16
17
 
18
+ require 'qme/bundle/eh_measure_sheet'
19
+ require 'qme/bundle/eh_patient_importer'
17
20
  require 'qme/bundle/bundle'
18
21
  require 'qme/bundle/importer'
19
22
 
@@ -21,6 +21,8 @@ Gem::Specification.new do |gem|
21
21
  gem.add_dependency 'mongoid', '~> 3.0.9'
22
22
  gem.add_dependency 'rubyzip', '~> 0.9.9'
23
23
  gem.add_dependency 'delayed_job_mongoid', '~> 2.0.0'
24
+ gem.add_dependency 'nokogiri', '~> 1.5.5'
25
+ gem.add_dependency 'rubyXL', '~> 1.2.10'
24
26
 
25
27
  gem.add_development_dependency "minitest", "~> 4.1.0"
26
28
  gem.add_development_dependency "simplecov", "~> 0.7.1"
@@ -1,9 +1,6 @@
1
1
  {
2
- _id: "508aeff07042f9f88900000d",
3
- priority: 0,
4
- attempts: 0,
5
- handler: "--- !ruby/object:QME::MapReduce::MeasureCalculationJob\ntest_id: \nmeasure_id: test2\nsub_id: b\neffective_date: 1284854400\nfilters: \n",
6
- run_at: ISODate("2012-10-26T20:17:52+00:00"),
7
- updated_at: ISODate("2012-10-26T20:17:52+00:00"),
8
- created_at: ISODate("2012-10-26T20:17:52+00:00")
2
+ "_id": "508aeff07042f9f88900000d",
3
+ "priority": 0,
4
+ "attempts": 0,
5
+ "handler": "--- !ruby/object:QME::MapReduce::MeasureCalculationJob\ntest_id: \nmeasure_id: test2\nsub_id: b\neffective_date: 1284854400\nfilters: \n"
9
6
  }
@@ -0,0 +1,19 @@
1
+ {
2
+ "id": "8A4D92B2-3887-5DF3-0139-0D01C6626E46",
3
+ "nqf_id": "0142",
4
+ "hqmf_id": "8A4D92B2-3887-5DF3-0139-0D01C6626E46",
5
+ "hqmf_set_id": "BB481284-30DD-4383-928C-82385BBF1B17",
6
+ "hqmf_version_number": 1,
7
+ "endorser": null,
8
+ "name": "Aspirin Prescribed at Discharge",
9
+ "description": "Acute myocardial infarction (AMI) patients who are prescribed aspirin at hospital discharge",
10
+ "type": "eh",
11
+ "category": "Miscellaneous",
12
+ "steward": null,
13
+ "population_ids": {
14
+ "IPP": "EDD90083-3417-4221-B3B9-52C4E5FAFAF4",
15
+ "DENOM": "193A17EC-66B4-4C44-9302-192556C78454",
16
+ "NUMER": "C224FC7D-B0C3-4A7F-BB9C-4480C3095F9F",
17
+ "DENEX": "FCE06869-6ADE-4A43-9A28-098D808A55BD"
18
+ }
19
+ }
@@ -0,0 +1,23 @@
1
+ {
2
+ "id": "8A4D92B2-3887-5DF3-0139-0C4E41594C98",
3
+ "nqf_id": "0495",
4
+ "hqmf_id": "8A4D92B2-3887-5DF3-0139-0C4E41594C98",
5
+ "hqmf_set_id": "9A033274-3D9B-11E1-8634-00237D5BF174",
6
+ "hqmf_version_number": 1,
7
+ "endorser": null,
8
+ "name": "Median Time from ED Arrival to ED Departure for Admitted ED Patients",
9
+ "description": "Median time from emergency department arrival to time of departure from the emergency room for patients admitted to the facility from the emergency department.",
10
+ "type": "eh",
11
+ "category": "Miscellaneous",
12
+ "steward": null,
13
+ "denominator": null,
14
+ "numerator": null,
15
+ "exclusions": null,
16
+ "sub_id": "a",
17
+ "subtitle": "Population 1",
18
+ "short_subtitle": "Population 1",
19
+ "population_ids": {
20
+ "IPP": "FA8BE62B-09FB-4B01-8CA8-E3CF1F9A16F6",
21
+ "MSRPOPL": "F3441A34-7FEA-4DAB-9907-A19885CFF92F"
22
+ }
23
+ }
@@ -0,0 +1,24 @@
1
+ {
2
+ "id": "8A4D92B2-3887-5DF3-0139-0C4E41594C98",
3
+ "nqf_id": "0495",
4
+ "hqmf_id": "8A4D92B2-3887-5DF3-0139-0C4E41594C98",
5
+ "hqmf_set_id": "9A033274-3D9B-11E1-8634-00237D5BF174",
6
+ "hqmf_version_number": 1,
7
+ "endorser": null,
8
+ "name": "Median Time from ED Arrival to ED Departure for Admitted ED Patients",
9
+ "description": "Median time from emergency department arrival to time of departure from the emergency room for patients admitted to the facility from the emergency department.",
10
+ "type": "eh",
11
+ "category": "Miscellaneous",
12
+ "steward": null,
13
+ "denominator": null,
14
+ "numerator": null,
15
+ "exclusions": null,
16
+ "sub_id": "b",
17
+ "subtitle": "Population 2",
18
+ "short_subtitle": "Population 2",
19
+ "population_ids": {
20
+ "IPP": "FA8BE62B-09FB-4B01-8CA8-E3CF1F9A16F6",
21
+ "MSRPOPL": "F3441A34-7FEA-4DAB-9907-A19885CFF92F",
22
+ "stratification": "1509C6DA-2465-4571-A6D4-AD634BE49BE6"
23
+ }
24
+ }
@@ -7,6 +7,7 @@
7
7
  "expired": true,
8
8
  "clinicalTrialParticipant": false,
9
9
  "birthdate": -223262033,
10
+ "medical_record_number" : "1234",
10
11
  "maritalStatus": {
11
12
  "code": "M",
12
13
  "codeSystem": "HL7"
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "_id": "507eb5977042f9362c000001",
3
3
  "birthdate": 1059723000,
4
+ "medical_record_number" : "1235",
4
5
  "conditions": [
5
6
  {
6
7
  "codes": {
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "_id": "507ec1407042f9362c000017",
3
3
  "birthdate": 946715400,
4
+ "medical_record_number" : "1236",
4
5
  "conditions": [
5
6
  {
6
7
  "codes": {
@@ -0,0 +1,37 @@
1
+ require 'test_helper'
2
+
3
+ class EHMeasureSheetTest < MiniTest::Unit::TestCase
4
+ include QME::DatabaseAccess
5
+
6
+ def setup
7
+ collection_fixtures(get_db(), 'measures')
8
+ collection_fixtures(get_db(), 'records', '_id')
9
+ @workbook = RubyXL::Parser.parse(File.join('test', 'fixtures', 'eh_patient_sheets', 'results_matrix_eh.xlsx'))
10
+ sheet = @workbook.worksheets[0]
11
+ @ms = QME::Bundle::EHMeasureSheet.new(get_db(), sheet, 12345000)
12
+ end
13
+
14
+ def test_extract_measure_info
15
+ measure_info = @ms.extract_measure_info
16
+ assert_equal 'EDD90083-3417-4221-B3B9-52C4E5FAFAF4', measure_info['IPP']
17
+ assert_equal '193A17EC-66B4-4C44-9302-192556C78454', measure_info['DENOM']
18
+ end
19
+
20
+ def test_query_cache_document
21
+ @ms.parse
22
+ qcd = @ms.query_cache_document
23
+ assert_equal '0142', qcd['nqf_id']
24
+ assert_equal 4, qcd['population']
25
+ assert_equal 12345000, qcd['effective_date']
26
+ end
27
+
28
+ def test_patient_cache_documents
29
+ @ms.parse
30
+ pcd = @ms.patient_cache_documents.first
31
+ assert_equal 1, pcd['value']['population']
32
+ assert_equal 0, pcd['value']['numerator']
33
+ assert_equal 1, pcd['value']['antinumerator']
34
+ assert_equal '1234', pcd['value']['medical_record_id']
35
+ assert_equal 12345000, pcd['value']['effective_date']
36
+ end
37
+ end
@@ -0,0 +1,20 @@
1
+ require 'test_helper'
2
+
3
+ class EHPatientImporterTest < MiniTest::Unit::TestCase
4
+ include QME::DatabaseAccess
5
+
6
+ def setup
7
+ get_db['query_cache'].drop()
8
+ get_db['patient_cache'].drop()
9
+ collection_fixtures(get_db(), 'measures')
10
+ collection_fixtures(get_db(), 'records', '_id')
11
+ @workbook = RubyXL::Parser.parse(File.join('test', 'fixtures', 'eh_patient_sheets', 'results_matrix_eh.xlsx'))
12
+ end
13
+
14
+ def test_load
15
+ assert_equal 0, get_db['query_cache'].find().count
16
+ QME::Bundle::EHPatientImporter.load(get_db, @workbook)
17
+ assert_equal 3, get_db['query_cache'].find().count
18
+ assert_equal 12, get_db['patient_cache'].find().count
19
+ end
20
+ end
@@ -42,6 +42,7 @@ class QualityReportTest < MiniTest::Unit::TestCase
42
42
  "effective_date" => Time.gm(2010, 9, 19).to_i
43
43
  }
44
44
  )
45
+ collection_fixtures(get_db(), 'delayed_backend_mongoid_jobs', '_id')
45
46
  end
46
47
 
47
48
  def test_calculated
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: 2.0.0
4
+ version: 2.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -12,7 +12,7 @@ authors:
12
12
  autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
- date: 2012-10-31 00:00:00.000000000 Z
15
+ date: 2012-11-14 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: moped
@@ -78,6 +78,38 @@ dependencies:
78
78
  - - ~>
79
79
  - !ruby/object:Gem::Version
80
80
  version: 2.0.0
81
+ - !ruby/object:Gem::Dependency
82
+ name: nokogiri
83
+ requirement: !ruby/object:Gem::Requirement
84
+ none: false
85
+ requirements:
86
+ - - ~>
87
+ - !ruby/object:Gem::Version
88
+ version: 1.5.5
89
+ type: :runtime
90
+ prerelease: false
91
+ version_requirements: !ruby/object:Gem::Requirement
92
+ none: false
93
+ requirements:
94
+ - - ~>
95
+ - !ruby/object:Gem::Version
96
+ version: 1.5.5
97
+ - !ruby/object:Gem::Dependency
98
+ name: rubyXL
99
+ requirement: !ruby/object:Gem::Requirement
100
+ none: false
101
+ requirements:
102
+ - - ~>
103
+ - !ruby/object:Gem::Version
104
+ version: 1.2.10
105
+ type: :runtime
106
+ prerelease: false
107
+ version_requirements: !ruby/object:Gem::Requirement
108
+ none: false
109
+ requirements:
110
+ - - ~>
111
+ - !ruby/object:Gem::Version
112
+ version: 1.2.10
81
113
  - !ruby/object:Gem::Dependency
82
114
  name: minitest
83
115
  requirement: !ruby/object:Gem::Requirement
@@ -141,6 +173,8 @@ files:
141
173
  - README.md
142
174
  - Rakefile
143
175
  - lib/qme/bundle/bundle.rb
176
+ - lib/qme/bundle/eh_measure_sheet.rb
177
+ - lib/qme/bundle/eh_patient_importer.rb
144
178
  - lib/qme/bundle/importer.rb
145
179
  - lib/qme/database_access.rb
146
180
  - lib/qme/map/map_reduce_builder.rb
@@ -155,6 +189,10 @@ files:
155
189
  - quality-measure-engine.gemspec
156
190
  - test/fixtures/bundles/just_measure_0002.zip
157
191
  - test/fixtures/delayed_backend_mongoid_jobs/queued_job.json
192
+ - test/fixtures/eh_patient_sheets/results_matrix_eh.xlsx
193
+ - test/fixtures/measures/0142.json
194
+ - test/fixtures/measures/0495a.json
195
+ - test/fixtures/measures/0495b.json
158
196
  - test/fixtures/measures/measure_metadata.json
159
197
  - test/fixtures/records/barry_berry.json
160
198
  - test/fixtures/records/billy_jones_ipp.json
@@ -162,6 +200,8 @@ files:
162
200
  - test/fixtures/records/jill_jones_denominator.json
163
201
  - test/simplecov_setup.rb
164
202
  - test/test_helper.rb
203
+ - test/unit/qme/bundle/eh_measure_sheet_test.rb
204
+ - test/unit/qme/bundle/eh_patient_importer_test.rb
165
205
  - test/unit/qme/map/map_reduce_builder_test.rb
166
206
  - test/unit/qme/map/map_reduce_executor_test.rb
167
207
  - test/unit/qme/map/measure_calculation_job_test.rb
@@ -195,6 +235,10 @@ summary: This library can run JavaScript based clinical quality measures on a re
195
235
  test_files:
196
236
  - test/fixtures/bundles/just_measure_0002.zip
197
237
  - test/fixtures/delayed_backend_mongoid_jobs/queued_job.json
238
+ - test/fixtures/eh_patient_sheets/results_matrix_eh.xlsx
239
+ - test/fixtures/measures/0142.json
240
+ - test/fixtures/measures/0495a.json
241
+ - test/fixtures/measures/0495b.json
198
242
  - test/fixtures/measures/measure_metadata.json
199
243
  - test/fixtures/records/barry_berry.json
200
244
  - test/fixtures/records/billy_jones_ipp.json
@@ -202,6 +246,8 @@ test_files:
202
246
  - test/fixtures/records/jill_jones_denominator.json
203
247
  - test/simplecov_setup.rb
204
248
  - test/test_helper.rb
249
+ - test/unit/qme/bundle/eh_measure_sheet_test.rb
250
+ - test/unit/qme/bundle/eh_patient_importer_test.rb
205
251
  - test/unit/qme/map/map_reduce_builder_test.rb
206
252
  - test/unit/qme/map/map_reduce_executor_test.rb
207
253
  - test/unit/qme/map/measure_calculation_job_test.rb