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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ed2e43ac18efc613d5e8e4deaa2e27c90b3d14956676be3009cfcaf023316bfc
4
- data.tar.gz: 602336f9a94c5ba3c89d0a6295543e9fccace4fd1ed96f8e296aca2c83bb4a2c
3
+ metadata.gz: 423a133232c347722fccf2898b4ad15c164310066ee3490b21f597fbc71f9687
4
+ data.tar.gz: d6976a899786dd91a28e63671f4e94bb8062e743be466b72db5c1fc037cee661
5
5
  SHA512:
6
- metadata.gz: 6664094195116bde7e6483e0e6baf23f93e3515607502b74c94b18608e675925002a506ba29e31c8252b6ea583a499fb922f9b7352b604ce4569522cd8fbbfa8
7
- data.tar.gz: 9f52ccb0ac909060103b5e568f480f71ae40ba4d07affbcdd7bf175532e1b359be3152b87edd538d3bc8be7bdb2f8ae580629474e6c3f4293e1cccf09bc37a60
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
- - :path: telecom
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
- - :path: telecom
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
@@ -64,7 +64,6 @@
64
64
  - Reference
65
65
  :target_profiles:
66
66
  - http://hl7.org/fhir/us/core/StructureDefinition/us-core-practitioner
67
- - http://hl7.org/fhir/us/core/StructureDefinition/us-core-organization
68
67
  - :path: agent.onBehalfOf
69
68
  :types:
70
69
  - Reference
@@ -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: 'telecom'
398
+ path: 'name.suffix',
399
+ uscdi_only: true
392
400
  }
393
401
  @must_supports[:elements] << {
394
- path: 'name.suffix'
402
+ path: 'name.use',
403
+ fixed_value: 'old',
404
+ uscdi_only: true
395
405
  }
396
406
  @must_supports[:elements] << {
397
- path: 'name.use',
398
- fixed_value: 'old'
407
+ path: 'name.period.end',
408
+ uscdi_only: true
399
409
  }
400
- end
401
- end
402
-
403
- def add_provenance_agent_who
404
- # FHIR-36344 US Core 4.0.0 mistakenly not lable us-core-organization as MS for Provenance.agent.who
405
- # This will be fixed in US Core 5.0.0
406
- if profile.type == 'Provenance'
407
- target_element = @must_supports[:elements].find { |element| element[:path] == 'agent.who'}
408
- target_element[:target_profiles] << 'http://hl7.org/fhir/us/core/StructureDefinition/us-core-organization'
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
- slice_names = group_metadata.must_supports[:slices].map { |slice| slice[:name] }
72
- element_names = group_metadata.must_supports[:elements].map { |slice| "#{resource_type}.#{slice[:path]}" }
73
- extension_names = group_metadata.must_supports[:extensions].map { |slice| slice[:id] }
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
- metadata.must_supports[:extensions]
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
- metadata.must_supports[:elements]
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
- metadata.must_supports[:slices]
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
- new_resource_count =
244
- fetch_all_bundled_resources
245
- .select { |resource| resource.resourceType == resource_type }
246
- .count
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.each_with_object({}) do |name, 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(',')] : [definition[:values]]
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
- search_param_names.each_with_object({}) do |name, params|
428
- value = patient_id_param?(name) ? patient_id : search_param_value(name, patient_id)
429
- params[name] = value
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
- "Please use patients with more information"
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, patient_id, include_system: false)
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(scratch_resources_for_patient(patient_id), path)
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
- coding.present? ? "#{coding.system}|#{coding.code}" : nil
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
- if include_system
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
- if include_system
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
- element
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
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module USCoreTestKit
2
- VERSION = '0.2.2'
4
+ VERSION = '0.2.3'
3
5
  end
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.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-05-09 00:00:00.000000000 Z
11
+ date: 2022-07-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: inferno_core