quality-measure-engine 2.0.0 → 2.1.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/.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