cqm-validators 0.1.0 → 2.0.2

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.
Files changed (44) hide show
  1. checksums.yaml +5 -5
  2. data/.github/PULL_REQUEST_TEMPLATE.md +23 -0
  3. data/.gitignore +3 -1
  4. data/.overcommit.yml +18 -0
  5. data/.rubocop.yml +68 -0
  6. data/.simplecov +12 -0
  7. data/.travis.yml +20 -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 +23 -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 } +1684 -2082
  25. data/lib/schematron/qrda/{cat_1_r3_1 → cat_1_r5_1}/voc.xml +1223 -1228
  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 +97 -36
  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_r4/voc.xml +0 -1186
  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.pluck(: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
+ build_error("Reported Performance Rate for Numerator #{numer_id} should be NA", '/', data[:file_name])
56
+ elsif expected != 'NA' && reported_result['PR']['nullFlavor'] == 'NA'
57
+ build_error("Reported Performance Rate for Numerator #{numer_id} should not be NA", '/', data[:file_name])
58
+ elsif expected != 'NA' && reported_result['PR']['value'].split('.', 2).last.size > 6
59
+ build_error('Reported Performance Rate SHALL not have a precision greater than .000001 ', '/', data[:file_name])
60
+ elsif expected != 'NA' && (reported_result['PR']['value'].to_f - expected.round(6)).abs > 0.0000001
61
+ 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