us_core_test_kit 0.2.2 → 0.2.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/us_core_test_kit/fhir_resource_navigation.rb +11 -3
- data/lib/us_core_test_kit/generated/v3.1.1/device/device_must_support_test.rb +1 -2
- data/lib/us_core_test_kit/generated/v3.1.1/document_reference/document_reference_must_support_test.rb +1 -2
- data/lib/us_core_test_kit/generated/v4.0.0/document_reference/document_reference_must_support_test.rb +1 -2
- data/lib/us_core_test_kit/generated/v4.0.0/encounter/encounter_must_support_test.rb +2 -4
- data/lib/us_core_test_kit/generated/v4.0.0/medication_request/medication_request_must_support_test.rb +1 -2
- data/lib/us_core_test_kit/generated/v4.0.0/metadata.yml +20 -2
- data/lib/us_core_test_kit/generated/v4.0.0/patient/metadata.yml +20 -1
- data/lib/us_core_test_kit/generated/v4.0.0/patient/patient_must_support_test.rb +9 -5
- data/lib/us_core_test_kit/generated/v4.0.0/provenance/metadata.yml +0 -1
- data/lib/us_core_test_kit/generator/must_support_metadata_extractor.rb +35 -22
- data/lib/us_core_test_kit/generator/must_support_test_generator.rb +26 -3
- data/lib/us_core_test_kit/must_support_test.rb +19 -3
- data/lib/us_core_test_kit/search_test.rb +95 -51
- data/lib/us_core_test_kit/version.rb +3 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 423a133232c347722fccf2898b4ad15c164310066ee3490b21f597fbc71f9687
|
4
|
+
data.tar.gz: d6976a899786dd91a28e63671f4e94bb8062e743be466b72db5c1fc037cee661
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fff0f5644ac84c70e2a6782d245437c62d82115e6b6c22772c2290b641ea60c3cfd293cf41a642419de436168f03f691b351d348b5bdd61818eceb9f6c01aba2
|
7
|
+
data.tar.gz: e47893ae3a7207fbc0e85bd958a1d8ffc94d516206971af365f1a962f338155c40d538be86c89732bb519101d2d31e724887c05bffff98346049d3fb56f1a584
|
@@ -1,5 +1,7 @@
|
|
1
1
|
module USCoreTestKit
|
2
2
|
module FHIRResourceNavigation
|
3
|
+
DAR_EXTENSION_URL = 'http://hl7.org/fhir/StructureDefinition/data-absent-reason'.freeze
|
4
|
+
|
3
5
|
def resolve_path(elements, path)
|
4
6
|
elements = Array.wrap(elements)
|
5
7
|
return elements if path.blank?
|
@@ -14,12 +16,18 @@ module USCoreTestKit
|
|
14
16
|
end.compact
|
15
17
|
end
|
16
18
|
|
17
|
-
def find_a_value_at(element, path)
|
19
|
+
def find_a_value_at(element, path, include_dar: false)
|
18
20
|
return nil if element.nil?
|
19
21
|
|
20
22
|
elements = Array.wrap(element)
|
21
23
|
|
22
24
|
if path.empty?
|
25
|
+
unless include_dar
|
26
|
+
elements = elements.reject do |el|
|
27
|
+
el.respond_to?(:extension) && el.extension.any? { |ext| ext.url == DAR_EXTENSION_URL}
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
23
31
|
return elements.find { |el| yield(el) } if block_given?
|
24
32
|
|
25
33
|
return elements.first
|
@@ -43,9 +51,9 @@ module USCoreTestKit
|
|
43
51
|
child = get_next_value(element, segment)
|
44
52
|
element_found =
|
45
53
|
if block_given?
|
46
|
-
find_a_value_at(child, remaining_path) { |value_found| yield(value_found) }
|
54
|
+
find_a_value_at(child, remaining_path, include_dar: include_dar) { |value_found| yield(value_found) }
|
47
55
|
else
|
48
|
-
find_a_value_at(child, remaining_path)
|
56
|
+
find_a_value_at(child, remaining_path, include_dar: include_dar)
|
49
57
|
end
|
50
58
|
|
51
59
|
return element_found if element_found.present? || element_found == false
|
@@ -20,8 +20,7 @@ module USCoreTestKit
|
|
20
20
|
* Device.serialNumber
|
21
21
|
* Device.type
|
22
22
|
* Device.udiCarrier
|
23
|
-
* Device.udiCarrier.carrierAIDC
|
24
|
-
* Device.udiCarrier.carrierHRF
|
23
|
+
* Device.udiCarrier.carrierAIDC or Device.udiCarrier.carrierHRF
|
25
24
|
* Device.udiCarrier.deviceIdentifier
|
26
25
|
)
|
27
26
|
|
@@ -17,8 +17,7 @@ module USCoreTestKit
|
|
17
17
|
* DocumentReference.content
|
18
18
|
* DocumentReference.content.attachment
|
19
19
|
* DocumentReference.content.attachment.contentType
|
20
|
-
* DocumentReference.content.attachment.data
|
21
|
-
* DocumentReference.content.attachment.url
|
20
|
+
* DocumentReference.content.attachment.data or DocumentReference.content.attachment.url
|
22
21
|
* DocumentReference.content.format
|
23
22
|
* DocumentReference.context
|
24
23
|
* DocumentReference.context.encounter
|
@@ -17,8 +17,7 @@ module USCoreTestKit
|
|
17
17
|
* DocumentReference.content
|
18
18
|
* DocumentReference.content.attachment
|
19
19
|
* DocumentReference.content.attachment.contentType
|
20
|
-
* DocumentReference.content.attachment.data
|
21
|
-
* DocumentReference.content.attachment.url
|
20
|
+
* DocumentReference.content.attachment.data or DocumentReference.content.attachment.url
|
22
21
|
* DocumentReference.content.format
|
23
22
|
* DocumentReference.context
|
24
23
|
* DocumentReference.context.encounter
|
@@ -19,15 +19,13 @@ module USCoreTestKit
|
|
19
19
|
* Encounter.identifier.system
|
20
20
|
* Encounter.identifier.value
|
21
21
|
* Encounter.location
|
22
|
-
* Encounter.location.location
|
22
|
+
* Encounter.location.location or Encounter.serviceProvider
|
23
23
|
* Encounter.participant
|
24
24
|
* Encounter.participant.individual
|
25
25
|
* Encounter.participant.period
|
26
26
|
* Encounter.participant.type
|
27
27
|
* Encounter.period
|
28
|
-
* Encounter.reasonCode
|
29
|
-
* Encounter.reasonReference
|
30
|
-
* Encounter.serviceProvider
|
28
|
+
* Encounter.reasonCode or Encounter.reasonReference
|
31
29
|
* Encounter.status
|
32
30
|
* Encounter.subject
|
33
31
|
* Encounter.type
|
@@ -19,8 +19,7 @@ module USCoreTestKit
|
|
19
19
|
* MedicationRequest.encounter
|
20
20
|
* MedicationRequest.intent
|
21
21
|
* MedicationRequest.medication[x]
|
22
|
-
* MedicationRequest.reportedBoolean
|
23
|
-
* MedicationRequest.reportedReference
|
22
|
+
* MedicationRequest.reportedBoolean or MedicationRequest.reportedReference
|
24
23
|
* MedicationRequest.requester
|
25
24
|
* MedicationRequest.status
|
26
25
|
* MedicationRequest.subject
|
@@ -12119,10 +12119,13 @@
|
|
12119
12119
|
:extensions:
|
12120
12120
|
- :id: Patient.extension:race
|
12121
12121
|
:url: http://hl7.org/fhir/us/core/StructureDefinition/us-core-race
|
12122
|
+
:uscdi_only: true
|
12122
12123
|
- :id: Patient.extension:ethnicity
|
12123
12124
|
:url: http://hl7.org/fhir/us/core/StructureDefinition/us-core-ethnicity
|
12125
|
+
:uscdi_only: true
|
12124
12126
|
- :id: Patient.extension:birthsex
|
12125
12127
|
:url: http://hl7.org/fhir/us/core/StructureDefinition/us-core-birthsex
|
12128
|
+
:uscdi_only: true
|
12126
12129
|
:slices: []
|
12127
12130
|
:elements:
|
12128
12131
|
- :path: identifier
|
@@ -12132,8 +12135,11 @@
|
|
12132
12135
|
- :path: name.family
|
12133
12136
|
- :path: name.given
|
12134
12137
|
- :path: telecom.system
|
12138
|
+
:uscdi_only: true
|
12135
12139
|
- :path: telecom.value
|
12140
|
+
:uscdi_only: true
|
12136
12141
|
- :path: telecom.use
|
12142
|
+
:uscdi_only: true
|
12137
12143
|
- :path: gender
|
12138
12144
|
- :path: birthDate
|
12139
12145
|
- :path: address
|
@@ -12143,10 +12149,23 @@
|
|
12143
12149
|
- :path: address.postalCode
|
12144
12150
|
- :path: address.period
|
12145
12151
|
- :path: communication.language
|
12146
|
-
|
12152
|
+
:uscdi_only: true
|
12147
12153
|
- :path: name.suffix
|
12154
|
+
:uscdi_only: true
|
12148
12155
|
- :path: name.use
|
12149
12156
|
:fixed_value: old
|
12157
|
+
:uscdi_only: true
|
12158
|
+
- :path: name.period.end
|
12159
|
+
:uscdi_only: true
|
12160
|
+
- :path: telecom
|
12161
|
+
:uscdi_only: true
|
12162
|
+
- :path: communication
|
12163
|
+
:uscdi_only: true
|
12164
|
+
:choices:
|
12165
|
+
- :paths:
|
12166
|
+
- name.period.end
|
12167
|
+
- name.use
|
12168
|
+
:uscdi_only: true
|
12150
12169
|
:mandatory_elements:
|
12151
12170
|
- Patient.identifier
|
12152
12171
|
- Patient.identifier.system
|
@@ -13976,7 +13995,6 @@
|
|
13976
13995
|
- Reference
|
13977
13996
|
:target_profiles:
|
13978
13997
|
- http://hl7.org/fhir/us/core/StructureDefinition/us-core-practitioner
|
13979
|
-
- http://hl7.org/fhir/us/core/StructureDefinition/us-core-organization
|
13980
13998
|
- :path: agent.onBehalfOf
|
13981
13999
|
:types:
|
13982
14000
|
- Reference
|
@@ -151,10 +151,13 @@
|
|
151
151
|
:extensions:
|
152
152
|
- :id: Patient.extension:race
|
153
153
|
:url: http://hl7.org/fhir/us/core/StructureDefinition/us-core-race
|
154
|
+
:uscdi_only: true
|
154
155
|
- :id: Patient.extension:ethnicity
|
155
156
|
:url: http://hl7.org/fhir/us/core/StructureDefinition/us-core-ethnicity
|
157
|
+
:uscdi_only: true
|
156
158
|
- :id: Patient.extension:birthsex
|
157
159
|
:url: http://hl7.org/fhir/us/core/StructureDefinition/us-core-birthsex
|
160
|
+
:uscdi_only: true
|
158
161
|
:slices: []
|
159
162
|
:elements:
|
160
163
|
- :path: identifier
|
@@ -164,8 +167,11 @@
|
|
164
167
|
- :path: name.family
|
165
168
|
- :path: name.given
|
166
169
|
- :path: telecom.system
|
170
|
+
:uscdi_only: true
|
167
171
|
- :path: telecom.value
|
172
|
+
:uscdi_only: true
|
168
173
|
- :path: telecom.use
|
174
|
+
:uscdi_only: true
|
169
175
|
- :path: gender
|
170
176
|
- :path: birthDate
|
171
177
|
- :path: address
|
@@ -175,10 +181,23 @@
|
|
175
181
|
- :path: address.postalCode
|
176
182
|
- :path: address.period
|
177
183
|
- :path: communication.language
|
178
|
-
|
184
|
+
:uscdi_only: true
|
179
185
|
- :path: name.suffix
|
186
|
+
:uscdi_only: true
|
180
187
|
- :path: name.use
|
181
188
|
:fixed_value: old
|
189
|
+
:uscdi_only: true
|
190
|
+
- :path: name.period.end
|
191
|
+
:uscdi_only: true
|
192
|
+
- :path: telecom
|
193
|
+
:uscdi_only: true
|
194
|
+
- :path: communication
|
195
|
+
:uscdi_only: true
|
196
|
+
:choices:
|
197
|
+
- :paths:
|
198
|
+
- name.period.end
|
199
|
+
- name.use
|
200
|
+
:uscdi_only: true
|
182
201
|
:mandatory_elements:
|
183
202
|
- Patient.identifier
|
184
203
|
- Patient.identifier.system
|
@@ -19,10 +19,6 @@ module USCoreTestKit
|
|
19
19
|
* Patient.address.postalCode
|
20
20
|
* Patient.address.state
|
21
21
|
* Patient.birthDate
|
22
|
-
* Patient.communication.language
|
23
|
-
* Patient.extension:birthsex
|
24
|
-
* Patient.extension:ethnicity
|
25
|
-
* Patient.extension:race
|
26
22
|
* Patient.gender
|
27
23
|
* Patient.identifier
|
28
24
|
* Patient.identifier.system
|
@@ -30,8 +26,16 @@ module USCoreTestKit
|
|
30
26
|
* Patient.name
|
31
27
|
* Patient.name.family
|
32
28
|
* Patient.name.given
|
29
|
+
|
30
|
+
For ONC USCDI requirements, each Patient must support the following additional elements:
|
31
|
+
|
32
|
+
* Patient.communication
|
33
|
+
* Patient.communication.language
|
34
|
+
* Patient.extension:birthsex
|
35
|
+
* Patient.extension:ethnicity
|
36
|
+
* Patient.extension:race
|
37
|
+
* Patient.name.period.end or Patient.name.use
|
33
38
|
* Patient.name.suffix
|
34
|
-
* Patient.name.use
|
35
39
|
* Patient.telecom
|
36
40
|
* Patient.telecom.system
|
37
41
|
* Patient.telecom.use
|
@@ -277,7 +277,6 @@ module USCoreTestKit
|
|
277
277
|
when '4.0.0'
|
278
278
|
add_device_distinct_identifier
|
279
279
|
add_patient_uscdi_elements
|
280
|
-
add_provenance_agent_who
|
281
280
|
end
|
282
281
|
end
|
283
282
|
|
@@ -344,18 +343,23 @@ module USCoreTestKit
|
|
344
343
|
def add_must_support_choices
|
345
344
|
choices = []
|
346
345
|
|
347
|
-
choices << {paths: ['content.attachment.data', 'content.attachment.url']} if profile.type == 'DocumentReference'
|
346
|
+
choices << { paths: ['content.attachment.data', 'content.attachment.url'] } if profile.type == 'DocumentReference'
|
348
347
|
|
349
348
|
case profile.version
|
350
349
|
when '3.1.1'
|
351
|
-
choices << {paths: ['udiCarrier.carrierAIDC', 'udiCarrier.carrierHRF']} if profile.type == 'Device'
|
350
|
+
choices << { paths: ['udiCarrier.carrierAIDC', 'udiCarrier.carrierHRF'] } if profile.type == 'Device'
|
352
351
|
when '4.0.0'
|
353
352
|
case profile.type
|
354
353
|
when 'Encounter'
|
355
|
-
choices << {paths: ['reasonCode', 'reasonReference']}
|
356
|
-
choices << {paths: ['location.location', 'serviceProvider']}
|
354
|
+
choices << { paths: ['reasonCode', 'reasonReference'] }
|
355
|
+
choices << { paths: ['location.location', 'serviceProvider'] }
|
357
356
|
when 'MedicationRequest'
|
358
|
-
choices << {paths: ['reportedBoolean', 'reportedReference']}
|
357
|
+
choices << { paths: ['reportedBoolean', 'reportedReference'] }
|
358
|
+
when 'Patient'
|
359
|
+
choices << {
|
360
|
+
paths: ['name.period.end', 'name.use'],
|
361
|
+
uscdi_only: true
|
362
|
+
}
|
359
363
|
end
|
360
364
|
end
|
361
365
|
|
@@ -377,35 +381,44 @@ module USCoreTestKit
|
|
377
381
|
#US Core 4.0.0 Section 10.112.1.1 Additional USCDI v1 Requirement:
|
378
382
|
@must_supports[:extensions] << {
|
379
383
|
id: 'Patient.extension:race',
|
380
|
-
url: 'http://hl7.org/fhir/us/core/StructureDefinition/us-core-race'
|
384
|
+
url: 'http://hl7.org/fhir/us/core/StructureDefinition/us-core-race',
|
385
|
+
uscdi_only: true
|
381
386
|
}
|
382
387
|
@must_supports[:extensions] << {
|
383
388
|
id: 'Patient.extension:ethnicity',
|
384
|
-
url: 'http://hl7.org/fhir/us/core/StructureDefinition/us-core-ethnicity'
|
389
|
+
url: 'http://hl7.org/fhir/us/core/StructureDefinition/us-core-ethnicity',
|
390
|
+
uscdi_only: true
|
385
391
|
}
|
386
392
|
@must_supports[:extensions] << {
|
387
393
|
id: 'Patient.extension:birthsex',
|
388
|
-
url: 'http://hl7.org/fhir/us/core/StructureDefinition/us-core-birthsex'
|
394
|
+
url: 'http://hl7.org/fhir/us/core/StructureDefinition/us-core-birthsex',
|
395
|
+
uscdi_only: true
|
389
396
|
}
|
390
397
|
@must_supports[:elements] << {
|
391
|
-
path: '
|
398
|
+
path: 'name.suffix',
|
399
|
+
uscdi_only: true
|
392
400
|
}
|
393
401
|
@must_supports[:elements] << {
|
394
|
-
path: 'name.
|
402
|
+
path: 'name.use',
|
403
|
+
fixed_value: 'old',
|
404
|
+
uscdi_only: true
|
395
405
|
}
|
396
406
|
@must_supports[:elements] << {
|
397
|
-
path: 'name.
|
398
|
-
|
407
|
+
path: 'name.period.end',
|
408
|
+
uscdi_only: true
|
399
409
|
}
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
410
|
+
@must_supports[:elements] << {
|
411
|
+
path: 'telecom',
|
412
|
+
uscdi_only: true
|
413
|
+
}
|
414
|
+
@must_supports[:elements] << {
|
415
|
+
path: 'communication',
|
416
|
+
uscdi_only: true
|
417
|
+
}
|
418
|
+
@must_supports[:elements].each do |element|
|
419
|
+
path = element[:path]
|
420
|
+
element[:uscdi_only] = true if path.include?('telecom.') || path.include?('communication.')
|
421
|
+
end
|
409
422
|
end
|
410
423
|
end
|
411
424
|
end
|
@@ -68,9 +68,32 @@ module USCoreTestKit
|
|
68
68
|
end
|
69
69
|
|
70
70
|
def must_support_list_string
|
71
|
-
|
72
|
-
|
73
|
-
|
71
|
+
build_must_support_list_string(false)
|
72
|
+
end
|
73
|
+
|
74
|
+
def uscdi_list_string
|
75
|
+
build_must_support_list_string(true)
|
76
|
+
end
|
77
|
+
|
78
|
+
def build_must_support_list_string(uscdi_only)
|
79
|
+
slice_names = group_metadata.must_supports[:slices]
|
80
|
+
.select { |slice| slice[:uscdi_only].presence == uscdi_only.presence }
|
81
|
+
.map { |slice| slice[:name] }
|
82
|
+
|
83
|
+
element_names = group_metadata.must_supports[:elements]
|
84
|
+
.select { |element| element[:uscdi_only].presence == uscdi_only.presence }
|
85
|
+
.map { |element| "#{resource_type}.#{element[:path]}" }
|
86
|
+
|
87
|
+
extension_names = group_metadata.must_supports[:extensions]
|
88
|
+
.select { |extension| extension[:uscdi_only].presence == uscdi_only.presence }
|
89
|
+
.map { |extension| extension[:id] }
|
90
|
+
|
91
|
+
group_metadata.must_supports[:choices]&.each do |choice|
|
92
|
+
next unless choice[:uscdi_only].presence == uscdi_only.presence
|
93
|
+
choice[:paths].each { |path| element_names.delete("#{resource_type}.#{path}") }
|
94
|
+
element_names << choice[:paths].map { |path| "#{resource_type}.#{path}" }.join(' or ')
|
95
|
+
end
|
96
|
+
|
74
97
|
(slice_names + element_names + extension_names)
|
75
98
|
.uniq
|
76
99
|
.sort
|
@@ -36,8 +36,16 @@ module USCoreTestKit
|
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
39
|
+
def include_uscdi_only_test?
|
40
|
+
config.options[:include_uscdi_only_test] == true
|
41
|
+
end
|
42
|
+
|
39
43
|
def must_support_extensions
|
40
|
-
|
44
|
+
if include_uscdi_only_test?
|
45
|
+
metadata.must_supports[:extensions]
|
46
|
+
else
|
47
|
+
metadata.must_supports[:extensions].reject{ |extension| extension[:uscdi_only] }
|
48
|
+
end
|
41
49
|
end
|
42
50
|
|
43
51
|
def missing_extensions(resources = [])
|
@@ -50,7 +58,11 @@ module USCoreTestKit
|
|
50
58
|
end
|
51
59
|
|
52
60
|
def must_support_elements
|
53
|
-
|
61
|
+
if include_uscdi_only_test?
|
62
|
+
metadata.must_supports[:elements]
|
63
|
+
else
|
64
|
+
metadata.must_supports[:elements].reject{ |element| element[:uscdi_only] }
|
65
|
+
end
|
54
66
|
end
|
55
67
|
|
56
68
|
def missing_elements(resources = [])
|
@@ -85,7 +97,11 @@ module USCoreTestKit
|
|
85
97
|
end
|
86
98
|
|
87
99
|
def must_support_slices
|
88
|
-
|
100
|
+
if include_uscdi_only_test?
|
101
|
+
metadata.must_supports[:slices]
|
102
|
+
else
|
103
|
+
metadata.must_supports[:slices].reject{ |slice| slice[:uscdi_only] }
|
104
|
+
end
|
89
105
|
end
|
90
106
|
|
91
107
|
def missing_slices(resources = [])
|
@@ -31,7 +31,7 @@ module USCoreTestKit
|
|
31
31
|
if fixed_value_search?
|
32
32
|
fixed_value_search_param_values.map { |value| fixed_value_search_params(value, patient_id) }
|
33
33
|
else
|
34
|
-
[search_params_with_values(patient_id)]
|
34
|
+
[search_params_with_values(search_param_names, patient_id)]
|
35
35
|
end
|
36
36
|
new_params.reject! do |params|
|
37
37
|
params.any? { |_key, value| value.blank? }
|
@@ -135,6 +135,9 @@ module USCoreTestKit
|
|
135
135
|
check_search_response
|
136
136
|
|
137
137
|
post_search_resources = fetch_all_bundled_resources.select { |resource| resource.resourceType == resource_type }
|
138
|
+
|
139
|
+
filter_devices(post_search_resources) if resource_type == 'Device'
|
140
|
+
|
138
141
|
get_resource_count = get_search_resources.length
|
139
142
|
post_resource_count = post_search_resources.length
|
140
143
|
|
@@ -240,10 +243,11 @@ module USCoreTestKit
|
|
240
243
|
new_search_params = params.merge('patient' => "Patient/#{params['patient']}")
|
241
244
|
search_and_check_response(new_search_params)
|
242
245
|
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
246
|
+
reference_with_type_resources = fetch_all_bundled_resources.select { |resource| resource.resourceType == resource_type }
|
247
|
+
|
248
|
+
filter_devices(reference_with_type_resources) if resource_type == 'Device'
|
249
|
+
|
250
|
+
new_resource_count = reference_with_type_resources.count
|
247
251
|
|
248
252
|
assert new_resource_count == resource_count,
|
249
253
|
"Expected search by `#{params['patient']}` to to return the same results as searching " \
|
@@ -256,9 +260,7 @@ module USCoreTestKit
|
|
256
260
|
def perform_search_with_system(params, patient_id)
|
257
261
|
return if search_variant_test_records[:token_variants]
|
258
262
|
|
259
|
-
new_search_params = token_search_params
|
260
|
-
search_params[name] = search_param_value(name, patient_id, include_system: true)
|
261
|
-
end
|
263
|
+
new_search_params = search_params_with_values(token_search_params, patient_id, include_system: true)
|
262
264
|
return if new_search_params.any? { |_name, value| value.blank? }
|
263
265
|
|
264
266
|
search_params = params.merge(new_search_params)
|
@@ -308,7 +310,7 @@ module USCoreTestKit
|
|
308
310
|
definition = metadata.search_definitions[param_name]
|
309
311
|
return [] if definition.blank?
|
310
312
|
|
311
|
-
definition[:multiple_or] == 'SHALL' ? [definition[:values].join(',')] :
|
313
|
+
definition[:multiple_or] == 'SHALL' ? [definition[:values].join(',')] : Array.wrap(definition[:values])
|
312
314
|
end
|
313
315
|
|
314
316
|
|
@@ -317,7 +319,7 @@ module USCoreTestKit
|
|
317
319
|
|
318
320
|
all_search_params.each do |patient_id, params_list|
|
319
321
|
next unless params_list.present?
|
320
|
-
|
322
|
+
|
321
323
|
search_params = params_list.first
|
322
324
|
existing_values = {}
|
323
325
|
missing_values = {}
|
@@ -423,11 +425,29 @@ module USCoreTestKit
|
|
423
425
|
end
|
424
426
|
end
|
425
427
|
|
426
|
-
def search_params_with_values(patient_id)
|
427
|
-
|
428
|
-
|
429
|
-
|
428
|
+
def search_params_with_values(search_param_names, patient_id, include_system: false)
|
429
|
+
resources = scratch_resources_for_patient(patient_id)
|
430
|
+
|
431
|
+
if resources.empty?
|
432
|
+
return search_param_names.each_with_object({}) do |name, params|
|
433
|
+
value = patient_id_param?(name) ? patient_id : nil
|
434
|
+
params[name] = value
|
435
|
+
end
|
430
436
|
end
|
437
|
+
|
438
|
+
params_with_partial_value = resources.each_with_object({}) do |resource, outer_params|
|
439
|
+
results_from_one_resource = search_param_names.each_with_object({}) do |name, params|
|
440
|
+
value = patient_id_param?(name) ? patient_id : search_param_value(name, resource, include_system: include_system)
|
441
|
+
params[name] = value
|
442
|
+
end
|
443
|
+
|
444
|
+
outer_params.merge!(results_from_one_resource)
|
445
|
+
|
446
|
+
# stop if all parameter values are found
|
447
|
+
return outer_params if outer_params.all? { |_key, value| value.present? }
|
448
|
+
end
|
449
|
+
|
450
|
+
params_with_partial_value
|
431
451
|
end
|
432
452
|
|
433
453
|
def patient_id_list
|
@@ -446,10 +466,10 @@ module USCoreTestKit
|
|
446
466
|
|
447
467
|
def search_param_paths(name)
|
448
468
|
paths = metadata.search_definitions[name.to_sym][:paths]
|
449
|
-
if paths.first =='class'
|
469
|
+
if paths.first =='class'
|
450
470
|
paths[0] = 'local_class'
|
451
471
|
end
|
452
|
-
|
472
|
+
|
453
473
|
paths
|
454
474
|
end
|
455
475
|
|
@@ -470,8 +490,13 @@ module USCoreTestKit
|
|
470
490
|
end
|
471
491
|
|
472
492
|
def no_resources_skip_message(resource_type = self.resource_type)
|
473
|
-
"No #{resource_type} resources appear to be available
|
474
|
-
|
493
|
+
msg = "No #{resource_type} resources appear to be available"
|
494
|
+
|
495
|
+
if (resource_type == 'Device' && implantable_device_codes.present?)
|
496
|
+
msg.concat(" with the following Device Type Code filter: #{implantable_device_codes}")
|
497
|
+
end
|
498
|
+
|
499
|
+
msg + ". Please use patients with more information"
|
475
500
|
end
|
476
501
|
|
477
502
|
def fetch_all_bundled_resources(
|
@@ -504,15 +529,6 @@ module USCoreTestKit
|
|
504
529
|
page_count += 1
|
505
530
|
end
|
506
531
|
|
507
|
-
valid_resource_types = [resource_type, 'OperationOutcome'].concat(additional_resource_types)
|
508
|
-
valid_resource_types << 'Medication' if resource_type == 'MedicationRequest'
|
509
|
-
|
510
|
-
all_valid_resource_types =
|
511
|
-
resources.all? { |entry| valid_resource_types.include? entry.resourceType }
|
512
|
-
|
513
|
-
assert all_valid_resource_types,
|
514
|
-
"All resources returned must be of the type: #{valid_resource_types.join(', ')}"
|
515
|
-
|
516
532
|
resources
|
517
533
|
end
|
518
534
|
|
@@ -520,11 +536,11 @@ module USCoreTestKit
|
|
520
536
|
"Could not resolve next bundle: #{link}"
|
521
537
|
end
|
522
538
|
|
523
|
-
def search_param_value(name,
|
539
|
+
def search_param_value(name, resource, include_system: false)
|
524
540
|
paths = search_param_paths(name)
|
525
541
|
search_value = nil
|
526
542
|
paths.each do |path|
|
527
|
-
element = find_a_value_at(
|
543
|
+
element = find_a_value_at(resource, path) { |element| element_has_valid_value?(element, include_system) }
|
528
544
|
|
529
545
|
search_value =
|
530
546
|
case element
|
@@ -541,34 +557,37 @@ module USCoreTestKit
|
|
541
557
|
if include_system
|
542
558
|
coding =
|
543
559
|
find_a_value_at(element, 'coding') { |coding| coding.code.present? && coding.system.present? }
|
544
|
-
|
560
|
+
"#{coding.system}|#{coding.code}"
|
545
561
|
else
|
546
562
|
find_a_value_at(element, 'coding.code')
|
547
563
|
end
|
548
564
|
when FHIR::Identifier
|
549
|
-
|
550
|
-
identifier = find_a_value_at(scratch_resources_for_patient(patient_id), path) do |identifier|
|
551
|
-
identifier.value.present? && identifier.system.present?
|
552
|
-
end
|
553
|
-
identifier.present? ? "#{identifier.system}|#{identifier.value}" : nil
|
554
|
-
else
|
555
|
-
element.value
|
556
|
-
end
|
565
|
+
include_system ? "#{element.system}|#{element.value}" : element.value
|
557
566
|
when FHIR::Coding
|
558
|
-
|
559
|
-
coding = find_a_value_at(scratch_resources_for_patient(patient_id), path) do |coding|
|
560
|
-
coding.code.present? && coding.system.present?
|
561
|
-
end
|
562
|
-
coding.present? ? "#{coding.system}|#{coding.code}" : nil
|
563
|
-
else
|
564
|
-
element.code
|
565
|
-
end
|
567
|
+
include_system ? "#{element.system}|#{element.code}" : element.code
|
566
568
|
when FHIR::HumanName
|
567
569
|
element.family || element.given&.first || element.text
|
568
570
|
when FHIR::Address
|
569
571
|
element.text || element.city || element.state || element.postalCode || element.country
|
570
572
|
else
|
571
|
-
|
573
|
+
if metadata.version != 'v3.1.1' &&
|
574
|
+
metadata.search_definitions[name.to_sym][:type] == 'date' &&
|
575
|
+
params_with_comparators&.include?(name)
|
576
|
+
# convert date search to greath-than comparator search with correct precision
|
577
|
+
# For all date search parameters:
|
578
|
+
# Patient.birthDate does not mandate comparators so cannot be converted
|
579
|
+
# Goal.target-date has day precision
|
580
|
+
# All others have second + time offset precision
|
581
|
+
if /^\d{4}$/.match?(element) || # YYYY
|
582
|
+
/^\d{4}-\d{2}$/.match?(element) || # YYYY-MM
|
583
|
+
(/^\d{4}-\d{2}-\d{2}$/.match?(element) && resource_type != "Goal") # YYYY-MM-DD AND Resource is NOT Goal
|
584
|
+
"gt#{(DateTime.xmlschema(element)-1).xmlschema}"
|
585
|
+
else
|
586
|
+
element
|
587
|
+
end
|
588
|
+
else
|
589
|
+
element
|
590
|
+
end
|
572
591
|
end
|
573
592
|
|
574
593
|
break if search_value.present?
|
@@ -578,6 +597,31 @@ module USCoreTestKit
|
|
578
597
|
escaped_value
|
579
598
|
end
|
580
599
|
|
600
|
+
def element_has_valid_value?(element, include_system)
|
601
|
+
case element
|
602
|
+
when FHIR::Reference
|
603
|
+
element.reference.present?
|
604
|
+
when FHIR::CodeableConcept
|
605
|
+
if include_system
|
606
|
+
coding =
|
607
|
+
find_a_value_at(element, 'coding') { |coding| coding.code.present? && coding.system.present? }
|
608
|
+
coding.present?
|
609
|
+
else
|
610
|
+
find_a_value_at(element, 'coding.code').present?
|
611
|
+
end
|
612
|
+
when FHIR::Identifier
|
613
|
+
include_system ? element.value.present? && element.system.present? : element.value.present?
|
614
|
+
when FHIR::Coding
|
615
|
+
include_system ? element.code.present? && element.system.present? : element.code.present?
|
616
|
+
when FHIR::HumanName
|
617
|
+
(element.family || element.given&.first || element.text).present?
|
618
|
+
when FHIR::Address
|
619
|
+
(element.text || element.city || element.state || element.postalCode || element.country).present?
|
620
|
+
else
|
621
|
+
true
|
622
|
+
end
|
623
|
+
end
|
624
|
+
|
581
625
|
def save_resource_reference(resource_type, reference)
|
582
626
|
scratch[:references] ||= {}
|
583
627
|
scratch[:references][resource_type] ||= Set.new
|
@@ -647,9 +691,9 @@ module USCoreTestKit
|
|
647
691
|
address&.country&.downcase&.start_with?(search_value_downcase)
|
648
692
|
end
|
649
693
|
when 'CodeableConcept'
|
650
|
-
# FHIR token search (https://www.hl7.org/fhir/search.html#token): "When in doubt, servers SHOULD
|
651
|
-
# treat tokens in a case-insensitive manner, on the grounds that including undesired data has
|
652
|
-
# less safety implications than excluding desired behavior".
|
694
|
+
# FHIR token search (https://www.hl7.org/fhir/search.html#token): "When in doubt, servers SHOULD
|
695
|
+
# treat tokens in a case-insensitive manner, on the grounds that including undesired data has
|
696
|
+
# less safety implications than excluding desired behavior".
|
653
697
|
codings = values_found.flat_map(&:coding)
|
654
698
|
if search_value.include? '|'
|
655
699
|
system = search_value.split('|').first
|
@@ -691,7 +735,7 @@ module USCoreTestKit
|
|
691
735
|
values_found.any? { |value_found| search_values.include? value_found }
|
692
736
|
end
|
693
737
|
end
|
694
|
-
|
738
|
+
|
695
739
|
break if match_found
|
696
740
|
end
|
697
741
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: us_core_test_kit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stephen MacVicar
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-07-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: inferno_core
|