cqm-validators 0.1.1 → 1.0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/.github/PULL_REQUEST_TEMPLATE.md +23 -0
  3. data/.gitignore +3 -1
  4. data/.overcommit.yml +18 -0
  5. data/.rubocop.yml +66 -0
  6. data/.simplecov +10 -0
  7. data/.travis.yml +21 -0
  8. data/Gemfile +11 -3
  9. data/README.md +20 -6
  10. data/Rakefile +8 -6
  11. data/config/mongoid.yml +6 -0
  12. data/cqm_validators.gemspec +21 -14
  13. data/lib/base_validator.rb +20 -20
  14. data/lib/cqm_validators.rb +4 -2
  15. data/lib/cqm_validators/version.rb +3 -1
  16. data/lib/data_validator.rb +74 -79
  17. data/lib/measure_validator.rb +104 -107
  18. data/lib/performance_rate_validator.rb +43 -63
  19. data/lib/qrda_qdm_template_validator.rb +164 -311
  20. data/lib/reported_result_extractor.rb +137 -139
  21. data/lib/schema_validator.rb +20 -19
  22. data/lib/schematron/c_processor.rb +19 -19
  23. data/lib/schematron/java_processor.rb +66 -68
  24. data/lib/schematron/qrda/{cat_1_r4/HL7 QRDA Category I STU 4.sch → cat_1_r5_1/HL7 QRDA Category I STU 5.1.sch } +1559 -1964
  25. data/lib/schematron/qrda/{cat_1_r4 → cat_1_r5_1}/voc.xml +7 -2
  26. data/lib/schematron_validator.rb +31 -32
  27. data/lib/validation_error.rb +11 -9
  28. data/lib/validators.rb +40 -106
  29. data/notice.md +9 -0
  30. metadata +86 -24
  31. data/lib/schematron/qrda/cat_1/HL7_CDAR2_QRDA_Category_I_2_12_16.sch +0 -4693
  32. data/lib/schematron/qrda/cat_1/voc.xml +0 -1177
  33. data/lib/schematron/qrda/cat_1_r2/QRDA Category I Release 2.sch +0 -4069
  34. data/lib/schematron/qrda/cat_1_r2/voc.xml +0 -1065
  35. data/lib/schematron/qrda/cat_1_r3_1/HL7 QRDA Category I STU 3.1.sch +0 -3573
  36. data/lib/schematron/qrda/cat_1_r3_1/HL7 QRDA Category III STU 1.1.sch +0 -464
  37. data/lib/schematron/qrda/cat_1_r3_1/QRDA Category I STU Release 3.1.sch +0 -5394
  38. data/lib/schematron/qrda/cat_1_r3_1/voc.xml +0 -1229
  39. data/lib/schematron/qrda/cat_3/QRDA Category III.sch +0 -675
  40. data/lib/schematron/qrda/cat_3/voc.xml +0 -21
  41. data/lib/schematron/qrda/cat_3_r1_1/HL7 QRDA Category III STU 1.1.sch +0 -528
  42. data/lib/schematron/qrda/cat_3_r1_1/voc.xml +0 -8
  43. data/lib/schematron/qrda/cat_3_r2/HL7 QRDA Category III STU 2.sch +0 -677
  44. data/lib/schematron/qrda/cat_3_r2/voc.xml +0 -1186
@@ -1,130 +1,127 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module CqmValidators
2
- class MeasureValidator
3
- include BaseValidator
4
-
5
- def initialize(template_oid)
6
- @template_oid = template_oid
7
-
8
- end
9
-
10
- def validate(file, data={})
4
+ class MeasureValidator
5
+ include BaseValidator
6
+
7
+ def initialize(template_oid)
8
+ @template_oid = template_oid
9
+ end
10
+
11
+ def validate(file, data = {})
11
12
  @errors = []
12
13
  @doc = get_document(file)
13
14
  @doc.root.add_namespace_definition('cda', 'urn:hl7-org:v3')
14
- measure_ids = HealthDataStandards::CQM::Measure.all.map(&:hqmf_id)
15
+ measure_ids = CQM::Measure.all.map(&:hqmf_id)
15
16
  doc_measure_ids = @doc.xpath(measure_selector).map(&:value).map(&:upcase)
16
- #list of all of the set ids in the QRDA
17
+ # list of all of the set ids in the QRDA
17
18
  doc_neutral_ids = @doc.xpath(neutral_measure_selector).map(&:value).map(&:upcase).sort
18
- #list of all of the setids in the QRDA that are also in the bundle, includes duplicates if code appears twice in document
19
- bundle_neutral_ids = HealthDataStandards::CQM::Measure.distinct(:hqmf_set_id)
19
+ # list of all of the setids in the QRDA that are also in the bundle, includes duplicates if code appears twice in document
20
+ bundle_neutral_ids = CQM::Measure.distinct(:hqmf_set_id)
20
21
  doc_bundle_neutral_ids = doc_neutral_ids - (doc_neutral_ids - bundle_neutral_ids)
21
22
  validate_measure_ids(doc_measure_ids, measure_ids, data)
22
23
  validate_set_ids(doc_neutral_ids, doc_bundle_neutral_ids, data)
23
- if validate_no_repeating_measure_population_ids(data)
24
- validate_measure_ids_set_ids_usage(doc_bundle_neutral_ids, doc_measure_ids, data)
25
- end
26
-
24
+ validate_measure_ids_set_ids_usage(doc_bundle_neutral_ids, doc_measure_ids, data) if validate_no_repeating_measure_population_ids(data)
25
+
27
26
  @errors
27
+ end
28
+
29
+ private
30
+
31
+ # returns true if there are no repeating measures, check to see that the measure id usage is correct
32
+ def validate_no_repeating_measure_population_ids(data = {})
33
+ no_duplicate_measures = true
34
+ doc_population_ids = @doc.xpath(measure_population_selector).map(&:value).map(&:upcase).sort
35
+ duplicates = doc_population_ids.group_by { |e| e }.select { |_k, v| v.size > 1 }.map(&:first)
36
+ duplicates.each do |duplicate|
37
+ begin
38
+ measure_id = @doc.xpath(find_measure_node_for_population(duplicate)).at_xpath("cda:reference/cda:externalDocument/cda:id[./@root='2.16.840.1.113883.4.738']/@extension")
39
+ @errors << build_error("Population #{duplicate} for Measure #{measure_id.value} reported more than once", '/', data[:file_name])
40
+ rescue
41
+ @errors << build_error("Population #{duplicate} for reported more than once", '/', data[:file_name])
28
42
  end
29
-
30
- private
31
-
32
- #returns true if there are no repeating measures, check to see that the measure id usage is correct
33
- def validate_no_repeating_measure_population_ids(data={})
34
- noDuplicateMeasures = true
35
- doc_population_ids = @doc.xpath(measure_population_selector).map(&:value).map(&:upcase).sort
36
- duplicates = doc_population_ids.group_by{ |e| e }.select { |k, v| v.size > 1 }.map(&:first)
37
- duplicates.each do |duplicate|
38
- begin
39
- measureId = @doc.xpath(find_measure_node_for_population(duplicate)).at_xpath("cda:reference/cda:externalDocument/cda:id[./@root='2.16.840.1.113883.4.738']/@extension")
40
- @errors << build_error("Population #{duplicate} for Measure #{measureId.value} reported more than once", "/", data[:file_name])
41
- rescue
42
- @errors << build_error("Population #{duplicate} for reported more than once", "/", data[:file_name])
43
- end
44
- noDuplicateMeasures = false
45
- end
46
- return noDuplicateMeasures
47
- end
48
-
49
- def validate_measure_ids(doc_measure_ids, measure_ids, data={})
43
+ no_duplicate_measures = false
44
+ end
45
+ no_duplicate_measures
46
+ end
47
+
48
+ def validate_measure_ids(doc_measure_ids, measure_ids, data = {})
50
49
  (doc_measure_ids - measure_ids).map do |hqmf_id|
51
- @errors << build_error("Invalid HQMF ID Found: #{hqmf_id}", "/", data[:file_name])
50
+ @errors << build_error("Invalid HQMF ID Found: #{hqmf_id}", '/', data[:file_name])
52
51
  end
53
- end
54
-
55
- def validate_set_ids(doc_neutral_ids, doc_bundle_neutral_ids, data={})
56
- #an error will be returned for all of the setids that are in the QRDA that aren't in the bundle
52
+ end
53
+
54
+ def validate_set_ids(doc_neutral_ids, doc_bundle_neutral_ids, data = {})
55
+ # an error will be returned for all of the setids that are in the QRDA that aren't in the bundle
57
56
  (doc_neutral_ids - doc_bundle_neutral_ids).map do |hqmf_set_id|
58
- @errors << build_error("Invalid HQMF Set ID Found: #{hqmf_set_id}", "/", data[:file_name])
57
+ @errors << build_error("Invalid HQMF Set ID Found: #{hqmf_set_id}", '/', data[:file_name])
59
58
  end
60
- end
61
-
62
- #does not work if the same measure is reported more than once, nested under the repeating measures test
63
- def validate_measure_ids_set_ids_usage(doc_bundle_neutral_ids, doc_measure_ids, data={})
64
- #for each of the setIds that are in the bundle, check that they are for the correct measure id
59
+ end
60
+
61
+ # does not work if the same measure is reported more than once, nested under the repeating measures test
62
+ def validate_measure_ids_set_ids_usage(doc_bundle_neutral_ids, doc_measure_ids, data = {})
63
+ # for each of the setIds that are in the bundle, check that they are for the correct measure id
65
64
  entries_start_position = @doc.xpath(first_entry)
66
- previous = ""
65
+ previous = ''
67
66
  index = 1
68
67
  doc_bundle_neutral_ids.each do |hqmf_set_id|
69
- #selects the measure id that is in the same entry as the set id
70
- #iterates through multiple instances of the same setId
71
- if previous == hqmf_set_id
72
- index = index + 1
73
- else
74
- index = 1
75
- end
76
- measure_id_entry = doc_measure_ids[(@doc.xpath(location_of_set_id(hqmf_set_id,index)) - entries_start_position)]
68
+ # selects the measure id that is in the same entry as the set id
69
+ # iterates through multiple instances of the same setId
70
+ index = if previous == hqmf_set_id
71
+ index + 1
72
+ else
73
+ 1
74
+ end
75
+ measure_id_entry = doc_measure_ids[(@doc.xpath(location_of_set_id(hqmf_set_id, index)) - entries_start_position)]
77
76
  previous = hqmf_set_id
78
- #queries database to see if there is a measure with the combindation of setId and measureId
79
- if HealthDataStandards::CQM::Measure.where(hqmf_id: measure_id_entry, hqmf_set_id: hqmf_set_id).length() == 0
80
- @errors << build_error("Invalid HQMF Set ID Found: #{hqmf_set_id} for HQMF ID: #{measure_id_entry}", "/", data[:file_name])
77
+ # queries database to see if there is a measure with the combindation of setId and measureId
78
+ if CQM::Measure.where(hqmf_id: measure_id_entry, hqmf_set_id: hqmf_set_id).empty?
79
+ @errors << build_error("Invalid HQMF Set ID Found: #{hqmf_set_id} for HQMF ID: #{measure_id_entry}", '/', data[:file_name])
81
80
  end
82
81
  end
83
- end
84
-
85
- def measure_selector
86
- "/cda:ClinicalDocument/cda:component/cda:structuredBody/cda:component/cda:section/cda:entry" +
87
- "/cda:organizer[./cda:templateId[@root='#{@template_oid}']]/cda:reference[@typeCode='REFR']" +
88
- "/cda:externalDocument[@classCode='DOC']/cda:id[@root='2.16.840.1.113883.4.738']/@extension"
89
- end
90
-
91
- #finds all of the setIds in the QRDA document
92
- def neutral_measure_selector
93
- "/cda:ClinicalDocument/cda:component/cda:structuredBody/cda:component/cda:section/cda:entry" +
94
- "/cda:organizer[./cda:templateId[@root='#{@template_oid}']]/cda:reference[@typeCode='REFR']" +
95
- "/cda:externalDocument[@classCode='DOC']/cda:setId/@root"
96
- end
97
-
98
- #finds the node index of the first entry element in the measure template
99
- def first_entry
100
- "count(//cda:entry[cda:organizer[./cda:templateId[@root='#{@template_oid}']]" +
101
- "/cda:reference[@typeCode='REFR']/cda:externalDocument[@classCode='DOC']" +
102
- "/cda:id[@root='2.16.840.1.113883.4.738']][1]/preceding-sibling::*)+1"
103
- end
104
-
105
- #finds the node index of the extry that the specified setId is in, index is used if the same setId appears twice
106
- def location_of_set_id(set_id,index)
107
- "count(//cda:entry[cda:organizer[./cda:templateId[@root='#{@template_oid}']]" +
108
- "/cda:reference[@typeCode='REFR']/cda:externalDocument[@classCode='DOC']" +
109
- "/cda:setId[@root[contains(translate(.,'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLOMNOPQRSTUVWXYZ')" +
110
- ",'#{set_id}')]]][#{index}]/preceding-sibling::*)+1"
111
- end
112
-
113
-
114
- def measure_population_selector
115
- "/cda:ClinicalDocument/cda:component/cda:structuredBody/cda:component/cda:section/cda:entry" +
116
- "/cda:organizer[./cda:templateId[@root='2.16.840.1.113883.10.20.27.3.1']]/cda:component" +
117
- "/cda:observation[./cda:templateId[@root='2.16.840.1.113883.10.20.27.3.5']]/cda:reference" +
118
- "/cda:externalObservation/cda:id/@root"
119
- end
120
-
121
- def find_measure_node_for_population(id)
122
- "/cda:ClinicalDocument/cda:component/cda:structuredBody/cda:component/cda:section/cda:entry" +
123
- "/cda:organizer[ ./cda:templateId[@root='2.16.840.1.113883.10.20.27.3.1']" +
124
- "and ./cda:component/cda:observation[./cda:templateId[@root='2.16.840.1.113883.10.20.27.3.5']]/cda:reference" +
125
- "/cda:externalObservation/cda:id[@root[contains(translate(.,'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLOMNOPQRSTUVWXYZ')" +
82
+ end
83
+
84
+ def measure_selector
85
+ '/cda:ClinicalDocument/cda:component/cda:structuredBody/cda:component/cda:section/cda:entry' \
86
+ "/cda:organizer[./cda:templateId[@root='#{@template_oid}']]/cda:reference[@typeCode='REFR']" \
87
+ "/cda:externalDocument[@classCode='DOC']/cda:id[@root='2.16.840.1.113883.4.738']/@extension"
88
+ end
89
+
90
+ # finds all of the setIds in the QRDA document
91
+ def neutral_measure_selector
92
+ '/cda:ClinicalDocument/cda:component/cda:structuredBody/cda:component/cda:section/cda:entry' \
93
+ "/cda:organizer[./cda:templateId[@root='#{@template_oid}']]/cda:reference[@typeCode='REFR']" \
94
+ "/cda:externalDocument[@classCode='DOC']/cda:setId/@root"
95
+ end
96
+
97
+ # finds the node index of the first entry element in the measure template
98
+ def first_entry
99
+ "count(//cda:entry[cda:organizer[./cda:templateId[@root='#{@template_oid}']]" \
100
+ "/cda:reference[@typeCode='REFR']/cda:externalDocument[@classCode='DOC']" \
101
+ "/cda:id[@root='2.16.840.1.113883.4.738']][1]/preceding-sibling::*)+1"
102
+ end
103
+
104
+ # finds the node index of the extry that the specified setId is in, index is used if the same setId appears twice
105
+ def location_of_set_id(set_id, index)
106
+ "count(//cda:entry[cda:organizer[./cda:templateId[@root='#{@template_oid}']]" \
107
+ "/cda:reference[@typeCode='REFR']/cda:externalDocument[@classCode='DOC']" \
108
+ "/cda:setId[@root[contains(translate(.,'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLOMNOPQRSTUVWXYZ')" \
109
+ ",'#{set_id}')]]][#{index}]/preceding-sibling::*)+1"
110
+ end
111
+
112
+ def measure_population_selector
113
+ '/cda:ClinicalDocument/cda:component/cda:structuredBody/cda:component/cda:section/cda:entry' \
114
+ "/cda:organizer[./cda:templateId[@root='2.16.840.1.113883.10.20.27.3.1']]/cda:component" \
115
+ "/cda:observation[./cda:templateId[@root='2.16.840.1.113883.10.20.27.3.5']]/cda:reference" \
116
+ '/cda:externalObservation/cda:id/@root'
117
+ end
118
+
119
+ def find_measure_node_for_population(id)
120
+ '/cda:ClinicalDocument/cda:component/cda:structuredBody/cda:component/cda:section/cda:entry' \
121
+ "/cda:organizer[ ./cda:templateId[@root='2.16.840.1.113883.10.20.27.3.1']" \
122
+ "and ./cda:component/cda:observation[./cda:templateId[@root='2.16.840.1.113883.10.20.27.3.5']]/cda:reference" \
123
+ "/cda:externalObservation/cda:id[@root[contains(translate(.,'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLOMNOPQRSTUVWXYZ')" \
126
124
  ",'#{id.upcase}')]]]"
127
- end
128
- end
125
+ end
126
+ end
129
127
  end
130
-
@@ -1,92 +1,72 @@
1
- require_relative "reported_result_extractor"
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'reported_result_extractor'
2
4
  module CqmValidators
3
5
  class PerformanceRateValidator
4
6
  include ReportedResultExtractor
5
7
  include BaseValidator
6
-
7
-
8
- def initialize()
9
8
 
10
-
11
-
12
- end
9
+ def initialize; end
13
10
 
14
11
  # Nothing to see here - Move along
15
12
  def validate(file, data = {})
16
- errorsList = []
13
+ errors_list = []
17
14
  document = get_document(file)
18
- #grab measure IDs from QRDA file
15
+ document.root.add_namespace_definition('cda', 'urn:hl7-org:v3')
16
+ # grab measure IDs from QRDA file
19
17
  measure_ids = document.xpath(measure_selector).map(&:value).map(&:upcase)
20
18
  measure_ids.each do |measure_id|
21
- measures = HealthDataStandards::CQM::Measure.where(id: measure_id)
22
- measures.each do |measure|
23
- result_key = measure["population_ids"].dup
24
- reported_result, errors = extract_results_by_ids(measure['id'], result_key, document)
25
- #only check performace rate when there is one
26
- if reported_result['PR'] != nil
27
- error = check_performance_rates(reported_result, result_key, measure['id'], data)
28
- if error != nil
29
- errorsList << error
30
- end
31
- end
19
+ measure = CQM::Measure.where(hqmf_id: measure_id).first
20
+ measure.population_sets.each do |population_set|
21
+ reported_result, = extract_results_by_ids(measure, population_set.population_set_id, document)
22
+ # only check performace rate when there is one
23
+ next if reported_result['PR'].nil?
24
+
25
+ error = check_performance_rates(reported_result, population_set, measure.hqmf_id, data)
26
+ errors_list << error unless error.nil?
32
27
  end
33
28
  end
34
- errorsList
29
+ errors_list
35
30
  end
36
31
 
37
32
  def calculate_performance_rates(reported_result)
38
- #Just in case a measure does not report these populations
33
+ # Just in case a measure does not report these populations
39
34
  denex = 0
40
35
  denexcep = 0
41
36
  denom = 0
42
37
  numer = 0
43
- if reported_result['DENEX'] != nil
44
- denex = reported_result['DENEX']
45
- end
46
- if reported_result['DENEXCEP'] != nil
47
- denexcep = reported_result['DENEXCEP']
48
- end
49
- if reported_result['DENOM'] != nil
50
- denom = reported_result['DENOM']
51
- end
52
- if reported_result['NUMER'] != nil
53
- numer = reported_result['NUMER']
54
- end
55
- denom = denom - denex - denexcep
56
- pr = 0
57
- if denom == 0
58
- pr = "NA"
59
- else
60
- pr = numer / denom.to_f
61
- end
62
- return pr
38
+ denex = reported_result['DENEX'] unless reported_result['DENEX'].nil?
39
+ denexcep = reported_result['DENEXCEP'] unless reported_result['DENEXCEP'].nil?
40
+ denom = reported_result['DENOM'] unless reported_result['DENOM'].nil?
41
+ numer = reported_result['NUMER'] unless reported_result['NUMER'].nil?
42
+ denom = denom - denex - denexcep
43
+ pr = if denom.zero?
44
+ 'NA'
45
+ else
46
+ numer / denom.to_f
47
+ end
48
+ pr
63
49
  end
64
50
 
65
- def check_performance_rates(reported_result, population_ids, measure_id, data = {})
51
+ def check_performance_rates(reported_result, population_set, _measure_id, data = {})
66
52
  expected = calculate_performance_rates(reported_result)
67
- _ids = population_ids
68
- if expected == "NA"
69
- if reported_result['PR']['nullFlavor'] != "NA"
70
- return build_error("Reported Performance Rate for Numerator #{_ids['NUMER']} should be NA", "/", data[:file_name])
71
- end
72
- else
73
- if reported_result['PR']['nullFlavor'] == "NA"
74
- return build_error("Reported Performance Rate for Numerator #{_ids['NUMER']} should not be NA", "/", data[:file_name])
75
- else
76
- if (reported_result['PR']['value'].split('.',2).last.size > 6)
77
- return build_error("Reported Performance Rate SHALL not have a precision greater than .000001 ", "/", data[:file_name])
78
- elsif (reported_result['PR']['value'].to_f - expected.round(6)).abs > 0.0000001
79
- return build_error("Reported Performance Rate of #{reported_result['PR']['value']} for Numerator #{_ids['NUMER']} does not match expected value of #{expected.round(6)}.", "/", data[:file_name])
80
- end
81
- end
53
+ numer_id = population_set.populations.NUMER.hqmf_id
54
+ if expected == 'NA' && reported_result['PR']['nullFlavor'] != 'NA'
55
+ return build_error("Reported Performance Rate for Numerator #{numer_id} should be NA", '/', data[:file_name])
56
+ elsif reported_result['PR']['nullFlavor'] == 'NA'
57
+ return build_error("Reported Performance Rate for Numerator #{numer_id} should not be NA", '/', data[:file_name])
58
+ elsif reported_result['PR']['value'].split('.', 2).last.size > 6
59
+ return build_error('Reported Performance Rate SHALL not have a precision greater than .000001 ', '/', data[:file_name])
60
+ elsif (reported_result['PR']['value'].to_f - expected.round(6)).abs > 0.0000001
61
+ return build_error("Reported Performance Rate of #{reported_result['PR']['value']} for Numerator #{numer_id} does not match expected"\
62
+ " value of #{expected.round(6)}.", '/', data[:file_name])
82
63
  end
83
64
  end
84
65
 
85
66
  def measure_selector
86
- "/cda:ClinicalDocument/cda:component/cda:structuredBody/cda:component/cda:section/cda:entry" +
87
- "/cda:organizer[./cda:templateId[@root='2.16.840.1.113883.10.20.27.3.1']]/cda:reference[@typeCode='REFR']" +
67
+ '/cda:ClinicalDocument/cda:component/cda:structuredBody/cda:component/cda:section/cda:entry' \
68
+ "/cda:organizer[./cda:templateId[@root='2.16.840.1.113883.10.20.27.3.1']]/cda:reference[@typeCode='REFR']" \
88
69
  "/cda:externalDocument[@classCode='DOC']/cda:id[@root='2.16.840.1.113883.4.738']/@extension"
89
70
  end
90
-
91
- end
92
- end
71
+ end
72
+ end
@@ -1,320 +1,173 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module CqmValidators
2
- class QrdaQdmTemplateValidator
3
- include BaseValidator
4
+ class QrdaQdmTemplateValidator
5
+ include BaseValidator
4
6
 
5
- # Hash of templateIds/extensions specified in the Patient Data Section QDM for QRDA R3
6
- QRDA_CAT_1_R3_QDM_OIDS = {
7
- '2.16.840.1.113883.10.20.24.3.1' => '2014-12-01',
8
- '2.16.840.1.113883.10.20.24.3.2' => '2014-12-01',
9
- '2.16.840.1.113883.10.20.24.3.3' => '2014-12-01',
10
- '2.16.840.1.113883.10.20.24.3.4' => '2014-12-01',
11
- '2.16.840.1.113883.10.20.24.3.5' => '2014-12-01',
12
- '2.16.840.1.113883.10.20.24.3.6' => '2014-12-01',
13
- '2.16.840.1.113883.10.20.24.3.7' => '2014-12-01',
14
- '2.16.840.1.113883.10.20.24.3.8' => '2014-12-01',
15
- '2.16.840.1.113883.10.20.24.3.9' => '2014-12-01',
16
- '2.16.840.1.113883.10.20.24.3.10' => '2014-12-01',
17
- '2.16.840.1.113883.10.20.24.3.121' => '2014-12-01',
18
- '2.16.840.1.113883.10.20.24.3.12' => '2014-12-01',
19
- '2.16.840.1.113883.10.20.24.3.123' => '2014-12-01',
20
- '2.16.840.1.113883.10.20.24.3.125' => '2014-12-01',
21
- '2.16.840.1.113883.10.20.24.3.15' => '2014-12-01',
22
- '2.16.840.1.113883.10.20.24.3.16' => '2014-12-01',
23
- '2.16.840.1.113883.10.20.24.3.17' => '2014-12-01',
24
- '2.16.840.1.113883.10.20.24.3.18' => '2014-12-01',
25
- '2.16.840.1.113883.10.20.24.3.19' => '2014-12-01',
26
- '2.16.840.1.113883.10.20.24.3.105' => '2014-12-01',
27
- '2.16.840.1.113883.10.20.24.3.21' => '2014-12-01',
28
- '2.16.840.1.113883.10.20.24.3.22' => '2014-12-01',
29
- '2.16.840.1.113883.10.20.24.3.23' => '2014-12-01',
30
- '2.16.840.1.113883.10.20.24.3.24' => '2014-12-01',
31
- '2.16.840.1.113883.10.20.24.3.25' => '2014-12-01',
32
- '2.16.840.1.113883.10.20.24.3.26' => '2014-12-01',
33
- '2.16.840.1.113883.10.20.24.3.27' => '2014-12-01',
34
- '2.16.840.1.113883.10.20.24.3.29' => '2014-12-01',
35
- '2.16.840.1.113883.10.20.24.3.30' => '2014-12-01',
36
- '2.16.840.1.113883.10.20.24.3.31' => '2014-12-01',
37
- '2.16.840.1.113883.10.20.24.3.32' => '2014-12-01',
38
- '2.16.840.1.113883.10.20.24.3.33' => '2014-12-01',
39
- '2.16.840.1.113883.10.20.24.3.35' => '2014-12-01',
40
- '2.16.840.1.113883.10.20.24.3.36' => '2014-12-01',
41
- '2.16.840.1.113883.10.20.24.3.37' => '2014-12-01',
42
- '2.16.840.1.113883.10.20.24.3.38' => '2014-12-01',
43
- '2.16.840.1.113883.10.20.24.3.39' => '2014-12-01',
44
- '2.16.840.1.113883.10.20.24.3.41' => '2014-12-01',
45
- '2.16.840.1.113883.10.20.24.3.42' => '2014-12-01',
46
- '2.16.840.1.113883.10.20.24.3.43' => '2014-12-01',
47
- '2.16.840.1.113883.10.20.24.3.44' => '2014-12-01',
48
- '2.16.840.1.113883.10.20.24.3.45' => '2014-12-01',
49
- '2.16.840.1.113883.10.20.24.3.46' => '2014-12-01',
50
- '2.16.840.1.113883.10.20.24.3.47' => '2014-12-01',
51
- '2.16.840.1.113883.10.20.24.3.48' => '2014-12-01',
52
- '2.16.840.1.113883.10.20.24.3.51' => '2014-12-01',
53
- '2.16.840.1.113883.10.20.24.3.54' => '2014-12-01',
54
- '2.16.840.1.113883.10.20.24.3.103' => '2014-12-01',
55
- '2.16.840.1.113883.10.20.24.3.55' => nil,
56
- '2.16.840.1.113883.10.20.24.3.58' => '2014-12-01',
57
- '2.16.840.1.113883.10.20.24.3.59' => '2014-12-01',
58
- '2.16.840.1.113883.10.20.24.3.60' => '2014-12-01',
59
- '2.16.840.1.113883.10.20.24.3.61' => '2014-12-01',
60
- '2.16.840.1.113883.10.20.24.3.62' => '2014-12-01',
61
- '2.16.840.1.113883.10.20.24.3.63' => '2014-12-01',
62
- '2.16.840.1.113883.10.20.24.3.64' => '2014-12-01',
63
- '2.16.840.1.113883.10.20.24.3.65' => '2014-12-01',
64
- '2.16.840.1.113883.10.20.24.3.67' => '2014-12-01',
65
- '2.16.840.1.113883.10.20.24.3.114' => '2014-12-01',
66
- '2.16.840.1.113883.10.20.24.3.69' => '2014-12-01',
67
- '2.16.840.1.113883.10.20.24.3.75' => '2014-12-01',
68
- '2.16.840.1.113883.10.20.24.3.120' => '2014-12-01',
69
- '2.16.840.1.113883.10.20.24.3.127' => '2014-12-01',
70
- '2.16.840.1.113883.10.20.24.3.122' => '2014-12-01',
71
- '2.16.840.1.113883.10.20.24.3.124' => '2014-12-01',
72
- '2.16.840.1.113883.10.20.24.3.81' => '2014-12-01',
73
- '2.16.840.1.113883.10.20.24.3.82' => '2014-12-01'
74
- }
75
- # Hash of templateIds/extensions specified in the Patient Data Section QDM for QRDA R3_1
76
- QRDA_CAT_1_R3_1_QDM_OIDS = {
77
- '2.16.840.1.113883.10.20.24.3.1' => '2016-02-01',
78
- '2.16.840.1.113883.10.20.24.3.2' => '2016-02-01',
79
- '2.16.840.1.113883.10.20.24.3.3' => '2016-02-01',
80
- '2.16.840.1.113883.10.20.24.3.4' => '2016-02-01',
81
- '2.16.840.1.113883.10.20.24.3.5' => '2016-02-01',
82
- '2.16.840.1.113883.10.20.24.3.6' => '2016-02-01',
83
- '2.16.840.1.113883.10.20.24.3.7' => '2016-02-01',
84
- '2.16.840.1.113883.10.20.24.3.8' => '2016-02-01',
85
- '2.16.840.1.113883.10.20.24.3.130' => nil,
86
- '2.16.840.1.113883.10.20.24.3.131' => nil,
87
- '2.16.840.1.113883.10.20.24.3.137' => nil,
88
- '2.16.840.1.113883.10.20.24.3.15' => '2016-02-01',
89
- '2.16.840.1.113883.10.20.24.3.16' => '2016-02-01',
90
- '2.16.840.1.113883.10.20.24.3.17' => '2016-02-01',
91
- '2.16.840.1.113883.10.20.24.3.18' => '2016-02-01',
92
- '2.16.840.1.113883.10.20.24.3.19' => '2016-02-01',
93
- '2.16.840.1.113883.10.20.24.3.105' => '2016-02-01',
94
- '2.16.840.1.113883.10.20.24.3.21' => '2016-02-01',
95
- '2.16.840.1.113883.10.20.24.3.132' => nil,
96
- '2.16.840.1.113883.10.20.24.3.133' => nil,
97
- '2.16.840.1.113883.10.20.24.3.134' => nil,
98
- '2.16.840.1.113883.10.20.24.3.12' => '2016-02-01',
99
- '2.16.840.1.113883.10.20.24.3.25' => '2016-02-01',
100
- '2.16.840.1.113883.10.20.24.3.26' => '2016-02-01',
101
- '2.16.840.1.113883.10.20.24.3.27' => '2016-02-01',
102
- '2.16.840.1.113883.10.20.24.3.140' => nil,
103
- '2.16.840.1.113883.10.20.24.3.143' => nil,
104
- '2.16.840.1.113883.10.20.24.3.29' => '2016-02-01',
105
- '2.16.840.1.113883.10.20.24.3.30' => '2016-02-01',
106
- '2.16.840.1.113883.10.20.24.3.31' => '2016-02-01',
107
- '2.16.840.1.113883.10.20.24.3.32' => '2016-02-01',
108
- '2.16.840.1.113883.10.20.24.3.33' => '2016-02-01',
109
- '2.16.840.1.113883.10.20.24.3.35' => '2016-02-01',
110
- '2.16.840.1.113883.10.20.24.3.36' => '2016-02-01',
111
- '2.16.840.1.113883.10.20.24.3.37' => '2016-02-01',
112
- '2.16.840.1.113883.10.20.24.3.38' => '2016-02-01',
113
- '2.16.840.1.113883.10.20.24.3.39' => '2016-02-01',
114
- '2.16.840.1.113883.10.20.24.3.41' => '2016-02-01',
115
- '2.16.840.1.113883.10.20.24.3.42' => '2016-02-01',
116
- '2.16.840.1.113883.10.20.24.3.43' => '2016-02-01',
117
- '2.16.840.1.113883.10.20.24.3.44' => '2016-02-01',
118
- '2.16.840.1.113883.10.20.24.3.139' => nil,
119
- '2.16.840.1.113883.10.20.24.3.46' => '2016-02-01',
120
- '2.16.840.1.113883.10.20.24.3.47' => '2016-02-01',
121
- '2.16.840.1.113883.10.20.24.3.48' => '2016-02-01',
122
- '2.16.840.1.113883.10.20.24.3.51' => '2016-02-01',
123
- '2.16.840.1.113883.10.20.24.3.54' => '2016-02-01',
124
- '2.16.840.1.113883.10.20.24.3.103' => '2016-02-01',
125
- '2.16.840.1.113883.10.20.24.3.58' => '2016-02-01',
126
- '2.16.840.1.113883.10.20.24.3.59' => '2016-02-01',
127
- '2.16.840.1.113883.10.20.24.3.55' => nil,
128
- '2.16.840.1.113883.10.20.24.3.60' => '2016-02-01',
129
- '2.16.840.1.113883.10.20.24.3.61' => '2016-02-01',
130
- '2.16.840.1.113883.10.20.24.3.62' => '2016-02-01',
131
- '2.16.840.1.113883.10.20.24.3.63' => '2016-02-01',
132
- '2.16.840.1.113883.10.20.24.3.64' => '2016-02-01',
133
- '2.16.840.1.113883.10.20.24.3.65' => '2016-02-01',
134
- '2.16.840.1.113883.10.20.24.3.67' => '2016-02-01',
135
- '2.16.840.1.113883.10.20.24.3.69' => '2016-02-01',
136
- '2.16.840.1.113883.10.20.24.3.75' => '2016-02-01',
137
- '2.16.840.1.113883.10.20.24.3.138' => nil,
138
- '2.16.840.1.113883.10.20.24.3.141' => nil,
139
- '2.16.840.1.113883.10.20.24.3.142' => nil
140
- }
141
- # Hash of templateIds/extensions specified in the Patient Data Section QDM for QRDA R4
142
- QRDA_CAT_1_R4_QDM_OIDS = {
143
- '2.16.840.1.113883.10.20.24.3.1' => '2016-02-01',
144
- '2.16.840.1.113883.10.20.24.3.2' => '2016-02-01',
145
- '2.16.840.1.113883.10.20.24.3.3' => '2016-02-01',
146
- '2.16.840.1.113883.10.20.24.3.4' => '2016-02-01',
147
- '2.16.840.1.113883.10.20.24.3.5' => '2016-02-01',
148
- '2.16.840.1.113883.10.20.24.3.6' => '2016-02-01',
149
- '2.16.840.1.113883.10.20.24.3.7' => '2016-02-01',
150
- '2.16.840.1.113883.10.20.24.3.8' => '2016-02-01',
151
- '2.16.840.1.113883.10.20.24.3.130' => nil,
152
- '2.16.840.1.113883.10.20.24.3.131' => nil,
153
- '2.16.840.1.113883.10.20.24.3.137' => '2016-08-01',
154
- '2.16.840.1.113883.10.20.24.3.15' => '2016-02-01',
155
- '2.16.840.1.113883.10.20.24.3.16' => '2016-02-01',
156
- '2.16.840.1.113883.10.20.24.3.17' => '2016-02-01',
157
- '2.16.840.1.113883.10.20.24.3.18' => '2016-02-01',
158
- '2.16.840.1.113883.10.20.24.3.19' => '2016-02-01',
159
- '2.16.840.1.113883.10.20.24.3.105' => '2016-02-01',
160
- '2.16.840.1.113883.10.20.24.3.21' => '2016-02-01',
161
- '2.16.840.1.113883.10.20.24.3.132' => nil,
162
- '2.16.840.1.113883.10.20.24.3.133' => nil,
163
- '2.16.840.1.113883.10.20.24.3.134' => nil,
164
- '2.16.840.1.113883.10.20.24.3.12' => '2016-02-01',
165
- '2.16.840.1.113883.10.20.24.3.140' => nil,
166
- '2.16.840.1.113883.10.20.24.3.143' => nil,
167
- '2.16.840.1.113883.10.20.24.3.29' => '2016-02-01',
168
- '2.16.840.1.113883.10.20.24.3.30' => '2016-02-01',
169
- '2.16.840.1.113883.10.20.24.3.31' => '2016-02-01',
170
- '2.16.840.1.113883.10.20.24.3.32' => '2016-02-01',
171
- '2.16.840.1.113883.10.20.24.3.33' => '2016-02-01',
172
- '2.16.840.1.113883.10.20.24.3.35' => '2016-02-01',
173
- '2.16.840.1.113883.10.20.24.3.36' => '2016-02-01',
174
- '2.16.840.1.113883.10.20.24.3.37' => '2016-02-01',
175
- '2.16.840.1.113883.10.20.24.3.38' => '2016-02-01',
176
- '2.16.840.1.113883.10.20.24.3.39' => '2016-02-01',
177
- '2.16.840.1.113883.10.20.24.3.41' => '2016-02-01',
178
- '2.16.840.1.113883.10.20.24.3.42' => '2016-02-01',
179
- '2.16.840.1.113883.10.20.24.3.43' => '2016-02-01',
180
- '2.16.840.1.113883.10.20.24.3.44' => '2016-02-01',
181
- '2.16.840.1.113883.10.20.24.3.139' => nil,
182
- '2.16.840.1.113883.10.20.24.3.46' => '2016-02-01',
183
- '2.16.840.1.113883.10.20.24.3.47' => '2016-02-01',
184
- '2.16.840.1.113883.10.20.24.3.48' => '2016-02-01',
185
- '2.16.840.1.113883.10.20.24.3.51' => '2016-02-01',
186
- '2.16.840.1.113883.10.20.24.3.54' => '2016-02-01',
187
- '2.16.840.1.113883.10.20.24.3.103' => '2016-02-01',
188
- '2.16.840.1.113883.10.20.24.3.58' => '2016-02-01',
189
- '2.16.840.1.113883.10.20.24.3.59' => '2016-02-01',
190
- '2.16.840.1.113883.10.20.24.3.55' => nil,
191
- '2.16.840.1.113883.10.20.24.3.60' => '2016-02-01',
192
- '2.16.840.1.113883.10.20.24.3.61' => '2016-02-01',
193
- '2.16.840.1.113883.10.20.24.3.62' => '2016-02-01',
194
- '2.16.840.1.113883.10.20.24.3.63' => '2016-02-01',
195
- '2.16.840.1.113883.10.20.24.3.64' => '2016-02-01',
196
- '2.16.840.1.113883.10.20.24.3.65' => '2016-02-01',
197
- '2.16.840.1.113883.10.20.24.3.67' => '2016-02-01',
198
- '2.16.840.1.113883.10.20.24.3.75' => '2016-02-01',
199
- '2.16.840.1.113883.10.20.24.3.138' => '2016-08-01',
200
- '2.16.840.1.113883.10.20.24.3.141' => nil,
201
- '2.16.840.1.113883.10.20.24.3.142' => nil,
202
- '2.16.840.1.113883.10.20.24.3.144' => '2016-08-01',
203
- '2.16.840.1.113883.10.20.24.3.145' => '2016-08-01'
204
- }
205
- # Hash of templateIds/extensions specified in the Patient Data Section QDM for QRDA R4
206
- QRDA_CAT_1_R5_QDM_OIDS = {
207
- '2.16.840.1.113883.10.20.24.3.1' => '2017-08-01',
208
- '2.16.840.1.113883.10.20.24.3.2' => '2017-08-01',
209
- '2.16.840.1.113883.10.20.24.3.3' => '2017-08-01',
210
- '2.16.840.1.113883.10.20.24.3.4' => '2017-08-01',
211
- # '2.16.840.1.113883.10.20.24.3.5' => '2016-02-01', Removed
212
- # '2.16.840.1.113883.10.20.24.3.6' => '2016-02-01', Removed
213
- '2.16.840.1.113883.10.20.24.3.7' => '2017-08-01',
214
- # '2.16.840.1.113883.10.20.24.3.8' => '2016-02-01',
215
- '2.16.840.1.113883.10.20.24.3.130' => '2017-08-01',
216
- '2.16.840.1.113883.10.20.24.3.131' => '2017-08-01',
217
- '2.16.840.1.113883.10.20.24.3.137' => '2017-08-01',
218
- # '2.16.840.1.113883.10.20.24.3.15' => '2016-02-01', Removed
219
- # '2.16.840.1.113883.10.20.24.3.16' => '2016-02-01', Removed
220
- '2.16.840.1.113883.10.20.24.3.17' => '2017-08-01',
221
- '2.16.840.1.113883.10.20.24.3.18' => '2017-08-01',
222
- '2.16.840.1.113883.10.20.24.3.19' => '2017-08-01',
223
- '2.16.840.1.113883.10.20.24.3.105' => '2016-02-01',
224
- # '2.16.840.1.113883.10.20.24.3.21' => '2016-02-01', Removed
225
- '2.16.840.1.113883.10.20.24.3.132' => '2017-08-01',
226
- '2.16.840.1.113883.10.20.24.3.133' => '2017-08-01',
227
- '2.16.840.1.113883.10.20.24.3.134' => '2017-08-01',
228
- '2.16.840.1.113883.10.20.24.3.12' => '2017-08-01',
229
- '2.16.840.1.113883.10.20.24.3.140' => '2017-08-01',
230
- '2.16.840.1.113883.10.20.24.3.143' => '2017-08-01',
231
- # '2.16.840.1.113883.10.20.24.3.29' => '2016-02-01', Removed
232
- # '2.16.840.1.113883.10.20.24.3.30' => '2016-02-01', Removed
233
- '2.16.840.1.113883.10.20.24.3.31' => '2017-08-01',
234
- '2.16.840.1.113883.10.20.24.3.32' => '2017-08-01',
235
- '2.16.840.1.113883.10.20.24.3.33' => '2017-08-01',
236
- # '2.16.840.1.113883.10.20.24.3.35' => '2016-02-01', Removed
237
- # '2.16.840.1.113883.10.20.24.3.36' => '2016-02-01', Removed
238
- '2.16.840.1.113883.10.20.24.3.37' => '2017-08-01',
239
- '2.16.840.1.113883.10.20.24.3.38' => '2017-08-01',
240
- '2.16.840.1.113883.10.20.24.3.39' => '2017-08-01',
241
- '2.16.840.1.113883.10.20.24.3.41' => '2017-08-01',
242
- '2.16.840.1.113883.10.20.24.3.42' => '2017-08-01',
243
- # '2.16.840.1.113883.10.20.24.3.43' => '2016-02-01', Removed
244
- # '2.16.840.1.113883.10.20.24.3.44' => '2016-02-01', Removed
245
- '2.16.840.1.113883.10.20.24.3.139' => '2017-08-01',
246
- # '2.16.840.1.113883.10.20.24.3.46' => '2016-02-01', Removed
247
- '2.16.840.1.113883.10.20.24.3.47' => '2017-08-01',
248
- '2.16.840.1.113883.10.20.24.3.48' => '2017-08-01',
249
- '2.16.840.1.113883.10.20.24.3.51' => '2017-08-01',
250
- '2.16.840.1.113883.10.20.24.3.54' => '2016-02-01',
251
- '2.16.840.1.113883.10.20.24.3.103' => '2017-08-01',
252
- '2.16.840.1.113883.10.20.24.3.58' => '2017-08-01',
253
- '2.16.840.1.113883.10.20.24.3.59' => '2017-08-01',
254
- '2.16.840.1.113883.10.20.24.3.55' => nil,
255
- '2.16.840.1.113883.10.20.24.3.60' => '2017-08-01',
256
- # '2.16.840.1.113883.10.20.24.3.61' => '2016-02-01', Removed
257
- # '2.16.840.1.113883.10.20.24.3.62' => '2016-02-01', Removed
258
- '2.16.840.1.113883.10.20.24.3.63' => '2017-08-01',
259
- '2.16.840.1.113883.10.20.24.3.64' => '2017-08-01',
260
- '2.16.840.1.113883.10.20.24.3.65' => '2017-08-01',
261
- '2.16.840.1.113883.10.20.24.3.67' => '2017-08-01',
262
- '2.16.840.1.113883.10.20.24.3.75' => '2017-08-01',
263
- '2.16.840.1.113883.10.20.24.3.138' => '2017-08-01',
264
- # '2.16.840.1.113883.10.20.24.3.141' => nil, Removed
265
- # '2.16.840.1.113883.10.20.24.3.142' => nil, Removed
266
- '2.16.840.1.113883.10.20.24.3.144' => '2017-08-01',
267
- '2.16.840.1.113883.10.20.24.3.145' => '2017-08-01',
268
- '2.16.840.1.113883.10.20.24.3.146' => '2017-08-01',
269
- '2.16.840.1.113883.10.20.24.3.147' => '2017-08-01',
270
- '2.16.840.1.113883.10.20.24.3.114' => '2017-08-01',
271
- '2.16.840.1.113883.10.20.24.3.154' => '2017-08-01'
272
- }
273
-
274
- def initialize(qrda_version)
275
- @name = 'QRDA QDM Template Validator'
276
- @templateshash = case qrda_version
277
- when 'r3' then QRDA_CAT_1_R3_QDM_OIDS
278
- when 'r3_1' then QRDA_CAT_1_R3_1_QDM_OIDS
279
- when 'r4' then QRDA_CAT_1_R4_QDM_OIDS
280
- when 'r5' then QRDA_CAT_1_R5_QDM_OIDS
281
- end
282
- end
7
+ # Hash of templateIds/extensions specified in the Patient Data Section QDM for QRDA R5
8
+ QRDA_CAT_1_R5_QDM_OIDS = {
9
+ '2.16.840.1.113883.10.20.24.3.1' => '2017-08-01',
10
+ '2.16.840.1.113883.10.20.24.3.2' => '2017-08-01',
11
+ '2.16.840.1.113883.10.20.24.3.3' => '2017-08-01',
12
+ '2.16.840.1.113883.10.20.24.3.4' => '2017-08-01',
13
+ # '2.16.840.1.113883.10.20.24.3.5' => '2016-02-01', Removed
14
+ # '2.16.840.1.113883.10.20.24.3.6' => '2016-02-01', Removed
15
+ '2.16.840.1.113883.10.20.24.3.7' => '2017-08-01',
16
+ # '2.16.840.1.113883.10.20.24.3.8' => '2016-02-01',
17
+ '2.16.840.1.113883.10.20.24.3.130' => '2017-08-01',
18
+ '2.16.840.1.113883.10.20.24.3.131' => '2017-08-01',
19
+ '2.16.840.1.113883.10.20.24.3.137' => '2017-08-01',
20
+ # '2.16.840.1.113883.10.20.24.3.15' => '2016-02-01', Removed
21
+ # '2.16.840.1.113883.10.20.24.3.16' => '2016-02-01', Removed
22
+ '2.16.840.1.113883.10.20.24.3.17' => '2017-08-01',
23
+ '2.16.840.1.113883.10.20.24.3.18' => '2017-08-01',
24
+ '2.16.840.1.113883.10.20.24.3.19' => '2017-08-01',
25
+ '2.16.840.1.113883.10.20.24.3.105' => '2016-02-01',
26
+ # '2.16.840.1.113883.10.20.24.3.21' => '2016-02-01', Removed
27
+ '2.16.840.1.113883.10.20.24.3.132' => '2017-08-01',
28
+ '2.16.840.1.113883.10.20.24.3.133' => '2017-08-01',
29
+ '2.16.840.1.113883.10.20.24.3.134' => '2017-08-01',
30
+ '2.16.840.1.113883.10.20.24.3.12' => '2017-08-01',
31
+ '2.16.840.1.113883.10.20.24.3.140' => '2017-08-01',
32
+ '2.16.840.1.113883.10.20.24.3.143' => '2017-08-01',
33
+ # '2.16.840.1.113883.10.20.24.3.29' => '2016-02-01', Removed
34
+ # '2.16.840.1.113883.10.20.24.3.30' => '2016-02-01', Removed
35
+ '2.16.840.1.113883.10.20.24.3.31' => '2017-08-01',
36
+ '2.16.840.1.113883.10.20.24.3.32' => '2017-08-01',
37
+ '2.16.840.1.113883.10.20.24.3.33' => '2017-08-01',
38
+ # '2.16.840.1.113883.10.20.24.3.35' => '2016-02-01', Removed
39
+ # '2.16.840.1.113883.10.20.24.3.36' => '2016-02-01', Removed
40
+ '2.16.840.1.113883.10.20.24.3.37' => '2017-08-01',
41
+ '2.16.840.1.113883.10.20.24.3.38' => '2017-08-01',
42
+ '2.16.840.1.113883.10.20.24.3.39' => '2017-08-01',
43
+ '2.16.840.1.113883.10.20.24.3.41' => '2017-08-01',
44
+ '2.16.840.1.113883.10.20.24.3.42' => '2017-08-01',
45
+ # '2.16.840.1.113883.10.20.24.3.43' => '2016-02-01', Removed
46
+ # '2.16.840.1.113883.10.20.24.3.44' => '2016-02-01', Removed
47
+ '2.16.840.1.113883.10.20.24.3.139' => '2017-08-01',
48
+ # '2.16.840.1.113883.10.20.24.3.46' => '2016-02-01', Removed
49
+ '2.16.840.1.113883.10.20.24.3.47' => '2017-08-01',
50
+ '2.16.840.1.113883.10.20.24.3.48' => '2017-08-01',
51
+ '2.16.840.1.113883.10.20.24.3.51' => '2017-08-01',
52
+ '2.16.840.1.113883.10.20.24.3.54' => '2016-02-01',
53
+ '2.16.840.1.113883.10.20.24.3.103' => '2017-08-01',
54
+ '2.16.840.1.113883.10.20.24.3.58' => '2017-08-01',
55
+ '2.16.840.1.113883.10.20.24.3.59' => '2017-08-01',
56
+ '2.16.840.1.113883.10.20.24.3.55' => nil,
57
+ '2.16.840.1.113883.10.20.24.3.60' => '2017-08-01',
58
+ # '2.16.840.1.113883.10.20.24.3.61' => '2016-02-01', Removed
59
+ # '2.16.840.1.113883.10.20.24.3.62' => '2016-02-01', Removed
60
+ '2.16.840.1.113883.10.20.24.3.63' => '2017-08-01',
61
+ '2.16.840.1.113883.10.20.24.3.64' => '2017-08-01',
62
+ '2.16.840.1.113883.10.20.24.3.65' => '2017-08-01',
63
+ '2.16.840.1.113883.10.20.24.3.67' => '2017-08-01',
64
+ '2.16.840.1.113883.10.20.24.3.75' => '2017-08-01',
65
+ '2.16.840.1.113883.10.20.24.3.138' => '2017-08-01',
66
+ # '2.16.840.1.113883.10.20.24.3.141' => nil, Removed
67
+ # '2.16.840.1.113883.10.20.24.3.142' => nil, Removed
68
+ '2.16.840.1.113883.10.20.24.3.144' => '2017-08-01',
69
+ '2.16.840.1.113883.10.20.24.3.145' => '2017-08-01',
70
+ '2.16.840.1.113883.10.20.24.3.146' => '2017-08-01',
71
+ '2.16.840.1.113883.10.20.24.3.147' => '2017-08-01',
72
+ '2.16.840.1.113883.10.20.24.3.114' => '2017-08-01',
73
+ '2.16.840.1.113883.10.20.24.3.154' => '2017-08-01'
74
+ }.freeze
75
+ # Hash of templateIds/extensions specified in the Patient Data Section QDM for QRDA R5.1
76
+ QRDA_CAT_1_R5_1_QDM_OIDS = {
77
+ '2.16.840.1.113883.10.20.24.3.1' => '2017-08-01',
78
+ # '2.16.840.1.113883.10.20.24.3.2' => '2017-08-01', Removed
79
+ # '2.16.840.1.113883.10.20.24.3.3' => '2017-08-01', Removed
80
+ # '2.16.840.1.113883.10.20.24.3.4' => '2017-08-01', Removed
81
+ '2.16.840.1.113883.10.20.24.3.7' => '2018-10-01',
82
+ '2.16.840.1.113883.10.20.24.3.130' => '2017-08-01',
83
+ '2.16.840.1.113883.10.20.24.3.131' => '2017-08-01',
84
+ '2.16.840.1.113883.10.20.24.3.137' => '2017-08-01',
85
+ '2.16.840.1.113883.10.20.24.3.17' => '2017-08-01',
86
+ '2.16.840.1.113883.10.20.24.3.18' => '2017-08-01',
87
+ '2.16.840.1.113883.10.20.24.3.19' => '2017-08-01',
88
+ '2.16.840.1.113883.10.20.24.3.105' => '2018-10-01',
89
+ '2.16.840.1.113883.10.20.24.3.132' => '2017-08-01',
90
+ '2.16.840.1.113883.10.20.24.3.133' => '2017-08-01',
91
+ '2.16.840.1.113883.10.20.24.3.134' => '2017-08-01',
92
+ '2.16.840.1.113883.10.20.24.3.12' => '2017-08-01',
93
+ '2.16.840.1.113883.10.20.24.3.140' => '2017-08-01',
94
+ '2.16.840.1.113883.10.20.24.3.143' => '2017-08-01',
95
+ '2.16.840.1.113883.10.20.24.3.31' => '2017-08-01',
96
+ '2.16.840.1.113883.10.20.24.3.32' => '2017-08-01',
97
+ '2.16.840.1.113883.10.20.24.3.33' => '2017-08-01',
98
+ '2.16.840.1.113883.10.20.24.3.37' => '2017-08-01',
99
+ '2.16.840.1.113883.10.20.24.3.38' => '2017-08-01',
100
+ '2.16.840.1.113883.10.20.24.3.39' => '2017-08-01',
101
+ '2.16.840.1.113883.10.20.24.3.41' => '2017-08-01',
102
+ '2.16.840.1.113883.10.20.24.3.42' => '2017-08-01',
103
+ '2.16.840.1.113883.10.20.24.3.139' => '2018-10-01',
104
+ '2.16.840.1.113883.10.20.24.3.47' => '2018-10-01',
105
+ '2.16.840.1.113883.10.20.24.3.48' => '2017-08-01',
106
+ '2.16.840.1.113883.10.20.24.3.51' => '2017-08-01',
107
+ '2.16.840.1.113883.10.20.24.3.54' => '2016-02-01',
108
+ '2.16.840.1.113883.10.20.24.3.103' => '2017-08-01',
109
+ '2.16.840.1.113883.10.20.24.3.58' => '2017-08-01',
110
+ '2.16.840.1.113883.10.20.24.3.59' => '2017-08-01',
111
+ '2.16.840.1.113883.10.20.24.3.55' => nil,
112
+ '2.16.840.1.113883.10.20.24.3.60' => '2017-08-01',
113
+ '2.16.840.1.113883.10.20.24.3.63' => '2018-10-01',
114
+ '2.16.840.1.113883.10.20.24.3.64' => '2018-10-01',
115
+ '2.16.840.1.113883.10.20.24.3.65' => '2018-10-01',
116
+ '2.16.840.1.113883.10.20.24.3.67' => '2017-08-01',
117
+ '2.16.840.1.113883.10.20.24.3.75' => '2017-08-01',
118
+ '2.16.840.1.113883.10.20.24.3.138' => '2017-08-01',
119
+ '2.16.840.1.113883.10.20.24.3.144' => '2017-08-01',
120
+ '2.16.840.1.113883.10.20.24.3.145' => '2017-08-01',
121
+ '2.16.840.1.113883.10.20.24.3.146' => '2017-08-01',
122
+ '2.16.840.1.113883.10.20.24.3.147' => '2017-08-01',
123
+ '2.16.840.1.113883.10.20.24.3.114' => '2017-08-01',
124
+ '2.16.840.1.113883.10.20.24.3.154' => '2017-08-01',
125
+ '2.16.840.1.113883.10.20.24.3.156' => '2018-10-01',
126
+ '2.16.840.1.113883.10.20.24.3.158' => '2018-10-01'
127
+ }.freeze
283
128
 
284
- # Validates that a QRDA Cat I file's Patient Data Section QDM (V3) contains entries that conform
285
- # to the QDM approach to QRDA. In contrast to a QRDA Framework Patient Data Section that requires
286
- # but does not specify the structured entries, the Patient Data Section QDM contained entry templates
287
- # have specific requirements to align the quality measure data element type with its corresponding NQF
288
- # QDM HQMF pattern, its referenced value set and potential QDM attributes.
289
- # The result will be an Array of execution errors indicating use of templates that are not valid for the
290
- # specified QRDA version
291
- def validate(file, data={})
292
- @errors = []
293
- # if validator does not support the qrda version specified, no checks are made
294
- unless @templateshash.nil?
295
- @doc = get_document(file)
296
- @doc.root.add_namespace_definition('cda', 'urn:hl7-org:v3')
297
- extract_entries.each do |entry|
298
- # each entry is evaluated separetly.
299
- entry_value_for_qrda_version(entry, data)
300
- end
301
- end
302
- @errors
303
- end
129
+ def initialize(qrda_version)
130
+ @name = 'QRDA QDM Template Validator'
131
+ @templateshash = case qrda_version
132
+ when 'r5' then QRDA_CAT_1_R5_QDM_OIDS
133
+ when 'r5_1' then QRDA_CAT_1_R5_1_QDM_OIDS
134
+ end
135
+ end
304
136
 
305
- def entry_value_for_qrda_version(entry, data={})
306
- # an entry may have multiple templateIds
307
- tids = entry.xpath('./*/cda:templateId')
308
- # an entry only needs one valid templateId to be acceptable
309
- unless tids.map { |tid| @templateshash.has_key?(tid['root']) && @templateshash[tid['root']] == tid['extension'] }.include? true
310
- msg = "#{tids.map { |tid| "#{tid['root']}:#{tid['extension']}" }} are not valid Patient Data Section QDM entries for this QRDA Version"
311
- @errors << build_error(msg, entry.path, data[:file_name])
137
+ # Validates that a QRDA Cat I file's Patient Data Section QDM (V3) contains entries that conform
138
+ # to the QDM approach to QRDA. In contrast to a QRDA Framework Patient Data Section that requires
139
+ # but does not specify the structured entries, the Patient Data Section QDM contained entry templates
140
+ # have specific requirements to align the quality measure data element type with its corresponding NQF
141
+ # QDM HQMF pattern, its referenced value set and potential QDM attributes.
142
+ # The result will be an Array of execution errors indicating use of templates that are not valid for the
143
+ # specified QRDA version
144
+ def validate(file, data = {})
145
+ @errors = []
146
+ # if validator does not support the qrda version specified, no checks are made
147
+ unless @templateshash.nil?
148
+ @doc = get_document(file)
149
+ @doc.root.add_namespace_definition('cda', 'urn:hl7-org:v3')
150
+ extract_entries.each do |entry|
151
+ # each entry is evaluated separetly.
152
+ entry_value_for_qrda_version(entry, data)
312
153
  end
313
154
  end
155
+ @errors
156
+ end
314
157
 
315
- # returns a list of the patient data entries
316
- def extract_entries
317
- @doc.xpath('//cda:component/cda:section[cda:templateId/@root="2.16.840.1.113883.10.20.24.2.1"]/cda:entry')
158
+ def entry_value_for_qrda_version(entry, data = {})
159
+ # an entry may have multiple templateIds
160
+ tids = entry.xpath('./*/cda:templateId')
161
+ # an entry only needs one valid templateId to be acceptable
162
+ unless tids.map { |tid| @templateshash.key?(tid['root']) && @templateshash[tid['root']] == tid['extension'] }.include? true
163
+ msg = "#{tids.map { |tid| "#{tid['root']}:#{tid['extension']}" }} are not valid Patient Data Section QDM entries for this QRDA Version"
164
+ @errors << build_error(msg, entry.path, data[:file_name])
318
165
  end
319
166
  end
320
- end
167
+
168
+ # returns a list of the patient data entries
169
+ def extract_entries
170
+ @doc.xpath('//cda:component/cda:section[cda:templateId/@root="2.16.840.1.113883.10.20.24.2.1"]/cda:entry')
171
+ end
172
+ end
173
+ end