us_core_test_kit 0.2.2 → 0.2.3
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.
- 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
|