Module: DaVinciPASTestKit::PasBundleValidation
- Includes:
- ValidationTest
- Included in:
- DaVinciPASV201::PASClientPendedSubmitTest, DaVinciPASV201::PasClientInquireRequestBundleValidationTest, DaVinciPASV201::PasClientInquireResponseBundleValidationTest, DaVinciPASV201::PasClientRequestBundleValidationTest, DaVinciPASV201::PasClientResponseBundleValidationTest, DaVinciPASV201::ServerPasInquiryRequestBundleValidationTest, DaVinciPASV201::ServerPasInquiryResponseBundleValidationTest, DaVinciPASV201::ServerPasRequestBundleValidationTest, DaVinciPASV201::ServerPasResponseBundleValidationTest
- Defined in:
- lib/davinci_pas_test_kit/pas_bundle_validation.rb
Constant Summary collapse
- CLAIM_PROFILE =
'http://hl7.org/fhir/us/davinci-pas/StructureDefinition/profile-claim-update'- CLAIM_RESPONSE_PROFILE =
'http://hl7.org/fhir/us/davinci-pas/StructureDefinition/profile-claimresponse'- CLAIM_INQUIRY_PROFILE =
'http://hl7.org/fhir/us/davinci-pas/StructureDefinition/profile-claim-inquiry'- CLAIM_INQUIRY_RESPONSE_PROFILE =
'http://hl7.org/fhir/us/davinci-pas/StructureDefinition/profile-claiminquiryresponse'
Constants included from ValidationTest
ValidationTest::DAR_CODE_SYSTEM_URL, ValidationTest::DAR_EXTENSION_URL
Instance Method Summary collapse
- #absolute_url(reference, base_url) ⇒ Object
-
#add_declared_profiles(instance, bundle_entry, version) ⇒ Object
Adds declared profiles from an instance (meta.profile) to the resource target profile map.
-
#add_profile_to_instance(instance, profile_url, bundle_entry, version) ⇒ Object
Adds a specific profile URL to an instance in the resource target profile map.
-
#add_resource_target_profile_to_map(resource_full_url, resource, profile_url = nil) ⇒ Object
Adds a resource and its associated profile URL to the resource target profile map.
- #all_scratch_resources ⇒ Object
- #bundle_entry_map(bundle_entry) ⇒ Object
-
#bundle_resources_target_profile_map ⇒ Hash
Returns a hash map where the keys are resource full URLs and the values are a hash containing the resource object and an array of associated profile URLs.
-
#check_presence_of_referenced_resources(target_resource, base_url, resources_to_match) ⇒ Object
This method traverses references within a FHIR resource, ensuring that referenced resources are populated in the bundle.
-
#extract_base_url(absolute_url) ⇒ String
Extracts the base URL from an absolute URL by removing the resource type and ID.
-
#extract_profiles_to_validate_each_entry(bundle_entry, current_entry, current_entry_profile_url, version) ⇒ Object
Processes each entry in a FHIR bundle to extract resource and possible profiles to validate against.
-
#extract_resources_from_bundle(bundle: nil, response: nil, reply_handler: nil, max_pages: 20) ⇒ Object
Extracts resources from a bundle while following “next” links.
-
#find_profile_url(request_type) ⇒ Object
Resource Types to validate in request/ response bundle.
-
#find_referenced_instance_in_bundle(reference, enclosing_entry_fullurl, bundle_map) ⇒ Object
Finds a referenced instance in a FHIR bundle based on a reference and the full URL of the enclosing entry.
- #generate_non_conformance_message(item) ⇒ Object
-
#handle_claim_profile(reference_elements, current_entry_profile_url) ⇒ Object
Handles the special case for the Claim profile in a FHIR bundle.
-
#metadata_map(version) ⇒ Object
Mapping profile url to metadata.
- #perform_request_validation(bundle, profile_url, version, request_type) ⇒ Object
- #perform_response_validation(response_bundle, profile_url, version, request_type, request_bundle = nil) ⇒ Object
-
#process_instance_profiles(instance, bundle_entry, reference_element, version) ⇒ Object
Processes the profiles associated with a given instance in a FHIR bundle.
-
#process_reference_element(reference_element, current_entry, bundle_entry, bundle_map, version) ⇒ Object
Processes a given reference element definition from a FHIR bundle entry.
-
#resource_present_in_pa_request_and_response_msg(resource) ⇒ Object
Generates a message for a resource present in both the PA request and response bundles.
-
#resource_shall_appear_once_message(absolute_ref, total_matches) ⇒ Object
Generates a message for a resource that appears more than once in a bundle.
- #save_bundles_and_entries_to_scratch(bundles) ⇒ Object
-
#valid_url_or_urn_uuid?(string) ⇒ Boolean
Checks if a string is a valid url or in the form “urn:uuid:[some guid]”.
-
#validate_bundle_entries_against_profiles(version) ⇒ Object
Validates bundle resource and each entry in the bundle against its target profiles.
- #validate_bundle_entries_full_url(bundle) ⇒ Object
-
#validate_pa_request_payload_structure(bundle, request_type) ⇒ Object
Validates the structure of a Prior Authorization (PA) request Bundle.
-
#validate_pa_response_body_structure(pa_response_bundle, pa_request_bundle) ⇒ Object
Validates the response body structure of a Prior Authorization (PA) response.
- #validate_pas_bundle_json(json, profile_url, version, request_type, bundle_type, skips: false, message: '') ⇒ Object
-
#validate_resources_conformance_against_profile(bundle, profile_url, version, request_type) ⇒ Object
Profile conformance of Prior Authorization (PA) resources.
-
#validate_uniqueness_of_supporting_info_sequences(claim) ⇒ Object
Checks the following requirement: The Claim.supportingInfo.sequence for each entry SHALL be unique within the Claim.
- #validation_error_messages ⇒ Object
Methods included from ValidationTest
#check_for_dar, #check_for_dar_code, #check_for_dar_extension, #perform_validation_test
Instance Method Details
#absolute_url(reference, base_url) ⇒ Object
384 385 386 387 388 389 |
# File 'lib/davinci_pas_test_kit/pas_bundle_validation.rb', line 384 def absolute_url(reference, base_url) return if reference.blank? return reference if base_url.blank? || reference.starts_with?('urn:uuid:') || URI(reference).absolute? "#{base_url}/#{reference}" end |
#add_declared_profiles(instance, bundle_entry, version) ⇒ Object
Adds declared profiles from an instance (meta.profile) to the resource target profile map. It recursively processes each entry for further profile extraction.
333 334 335 336 337 338 339 340 341 342 |
# File 'lib/davinci_pas_test_kit/pas_bundle_validation.rb', line 333 def add_declared_profiles(instance, bundle_entry, version) return unless instance.resource.present? instance.resource.&.profile&.each do |url| next if bundle_resources_target_profile_map[instance.fullUrl][:profile_urls].include?(url) bundle_resources_target_profile_map[instance.fullUrl][:profile_urls] << url extract_profiles_to_validate_each_entry(bundle_entry, instance, url, version) end end |
#add_profile_to_instance(instance, profile_url, bundle_entry, version) ⇒ Object
Adds a specific profile URL to an instance in the resource target profile map. It recursively processes the instance for further profile extraction.
350 351 352 353 354 355 |
# File 'lib/davinci_pas_test_kit/pas_bundle_validation.rb', line 350 def add_profile_to_instance(instance, profile_url, bundle_entry, version) return if bundle_resources_target_profile_map[instance.fullUrl][:profile_urls].include?(profile_url) bundle_resources_target_profile_map[instance.fullUrl][:profile_urls] << profile_url extract_profiles_to_validate_each_entry(bundle_entry, instance, profile_url, version) end |
#add_resource_target_profile_to_map(resource_full_url, resource, profile_url = nil) ⇒ Object
Adds a resource and its associated profile URL to the resource target profile map. If the resource is already in the map, it adds the profile URL to the resource’s list of profile URLs.
199 200 201 202 203 204 205 |
# File 'lib/davinci_pas_test_kit/pas_bundle_validation.rb', line 199 def add_resource_target_profile_to_map(resource_full_url, resource, profile_url = nil) entry = bundle_resources_target_profile_map[resource_full_url] ||= { resource:, profile_urls: [] } return if profile_url.blank? || entry[:profile_urls].include?(profile_url) entry[:profile_urls] << profile_url end |
#all_scratch_resources ⇒ Object
14 15 16 |
# File 'lib/davinci_pas_test_kit/pas_bundle_validation.rb', line 14 def all_scratch_resources scratch_resources[:all] ||= [] end |
#bundle_entry_map(bundle_entry) ⇒ Object
366 367 368 369 370 |
# File 'lib/davinci_pas_test_kit/pas_bundle_validation.rb', line 366 def bundle_entry_map(bundle_entry) @bundle_entry_map ||= bundle_entry.each_with_object({}) do |entry, obj| obj[entry.fullUrl] = entry end end |
#bundle_resources_target_profile_map ⇒ Hash
Returns a hash map where the keys are resource full URLs and the values are a hash containing the resource object and an array of associated profile URLs.
190 191 192 |
# File 'lib/davinci_pas_test_kit/pas_bundle_validation.rb', line 190 def bundle_resources_target_profile_map @bundle_resources_target_profile_map ||= {} end |
#check_presence_of_referenced_resources(target_resource, base_url, resources_to_match) ⇒ Object
This method traverses references within a FHIR resource, ensuring that referenced resources are populated in the bundle. It also enforces that a referenced resource appears only once in the bundle, as required by the PAS IG.
459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 |
# File 'lib/davinci_pas_test_kit/pas_bundle_validation.rb', line 459 def check_presence_of_referenced_resources(target_resource, base_url, resources_to_match) return if target_resource.blank? if target_resource.is_a?(FHIR::Reference) && target_resource.reference.present? ref = target_resource.reference return if ref.blank? absolute_ref = absolute_url(ref, base_url) matching_resources = resources_to_match.find_all { |res| res.fullUrl == absolute_ref } if matching_resources.length != 1 << (absolute_ref, matching_resources.length) end if matching_resources.length.positive? check_presence_of_referenced_resources(matching_resources.first, base_url, resources_to_match) end else target_resource.source_hash.each_key do |attr| value = target_resource.send(attr.to_sym) if value.is_a?(FHIR::Model) check_presence_of_referenced_resources(value, base_url, resources_to_match) elsif value.is_a?(Array) && value.all? { |elmt| elmt.is_a?(FHIR::Model) } value.each { |elmt| check_presence_of_referenced_resources(elmt, base_url, resources_to_match) } end end end end |
#extract_base_url(absolute_url) ⇒ String
Extracts the base URL from an absolute URL by removing the resource type and ID.
394 395 396 397 398 399 400 401 402 403 404 405 |
# File 'lib/davinci_pas_test_kit/pas_bundle_validation.rb', line 394 def extract_base_url(absolute_url) return '' if absolute_url.blank? uri = URI(absolute_url) return '' unless uri.scheme && uri.host # Split the path segments and remove the last two segments (resource type and id) path_segments = uri.path.split('/') base_path = path_segments[0...-2].join('/') "#{uri.scheme}://#{uri.host}#{base_path}" end |
#extract_profiles_to_validate_each_entry(bundle_entry, current_entry, current_entry_profile_url, version) ⇒ Object
Processes each entry in a FHIR bundle to extract resource and possible profiles to validate against. It recursively evaluates referenced instances and their profiles, expanding the validation scope.
235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 |
# File 'lib/davinci_pas_test_kit/pas_bundle_validation.rb', line 235 def extract_profiles_to_validate_each_entry(bundle_entry, current_entry, current_entry_profile_url, version) return if current_entry.blank? # NOTE: the IG does not have the metadata for us-core profiles. = ("v#{version}")[current_entry_profile_url] return if .blank? bundle_map = bundle_entry_map(bundle_entry) reference_elements = .references # Special handling for Claim submit profile if current_entry_profile_url == CLAIM_PROFILE handle_claim_profile(reference_elements, current_entry_profile_url) end reference_elements.each do |reference_element| process_reference_element(reference_element, current_entry, bundle_entry, bundle_map, version) end end |
#extract_resources_from_bundle(bundle: nil, response: nil, reply_handler: nil, max_pages: 20) ⇒ Object
Extracts resources from a bundle while following “next” links.
This method extracts resources from a FHIR bundle, following “next” links in the bundle until the specified maximum number of pages is reached. It collects resources and invokes the reply_handler for each response.
499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 |
# File 'lib/davinci_pas_test_kit/pas_bundle_validation.rb', line 499 def extract_resources_from_bundle( bundle: nil, response: nil, reply_handler: nil, max_pages: 20 ) page_count = 1 resources = [] until bundle.nil? || page_count == max_pages resources += bundle&.entry&.map { |entry| entry&.resource } next_bundle_link = bundle&.link&.find { |link| link.relation == 'next' }&.url reply_handler&.call(response) break if next_bundle_link.blank? page_count += 1 end resources end |
#find_profile_url(request_type) ⇒ Object
Resource Types to validate in request/ response bundle
408 409 410 411 412 413 |
# File 'lib/davinci_pas_test_kit/pas_bundle_validation.rb', line 408 def find_profile_url(request_type) { 'Claim' => request_type == 'submit' ? CLAIM_PROFILE : CLAIM_INQUIRY_PROFILE, 'ClaimResponse' => request_type == 'submit' ? CLAIM_RESPONSE_PROFILE : CLAIM_INQUIRY_RESPONSE_PROFILE } end |
#find_referenced_instance_in_bundle(reference, enclosing_entry_fullurl, bundle_map) ⇒ Object
Finds a referenced instance in a FHIR bundle based on a reference and the full URL of the enclosing entry.
377 378 379 380 381 382 |
# File 'lib/davinci_pas_test_kit/pas_bundle_validation.rb', line 377 def find_referenced_instance_in_bundle(reference, enclosing_entry_fullurl, bundle_map) base_url = extract_base_url(enclosing_entry_fullurl) key = absolute_url(reference, base_url) bundle_map[key] end |
#generate_non_conformance_message(item) ⇒ Object
224 225 226 227 |
# File 'lib/davinci_pas_test_kit/pas_bundle_validation.rb', line 224 def (item) "#{item[:resource].resourceType}/#{item[:resource].id} is not conformant to any of the " \ "target profiles: #{item[:profile_urls]}." end |
#handle_claim_profile(reference_elements, current_entry_profile_url) ⇒ Object
Handles the special case for the Claim profile in a FHIR bundle. It adds missing reference elements for the Claim profile. Claim.item.extension:requestedService value is a reference, but somehow not included in the metadata references.
261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 |
# File 'lib/davinci_pas_test_kit/pas_bundle_validation.rb', line 261 def handle_claim_profile(reference_elements, current_entry_profile_url) return unless current_entry_profile_url == CLAIM_PROFILE claim_ref_element = { path: 'Claim.item.extension.value', profiles: [ 'http://hl7.org/fhir/us/davinci-pas/StructureDefinition/profile-medicationrequest', 'http://hl7.org/fhir/us/davinci-pas/StructureDefinition/profile-servicerequest', 'http://hl7.org/fhir/us/davinci-pas/StructureDefinition/profile-devicerequest', 'http://hl7.org/fhir/us/davinci-pas/StructureDefinition/profile-nutritionorder' ] } reference_elements << claim_ref_element end |
#metadata_map(version) ⇒ Object
Mapping profile url to metadata
358 359 360 361 362 363 364 |
# File 'lib/davinci_pas_test_kit/pas_bundle_validation.rb', line 358 def (version) ||= YAML.load_file(File.join(__dir__, "generated/#{version}/metadata.yml"), aliases: true) ||= [:groups].each_with_object({}) do |group, obj| obj[group[:profile_url]] = Generator::GroupMetadata.new(group) end end |
#perform_request_validation(bundle, profile_url, version, request_type) ⇒ Object
30 31 32 33 |
# File 'lib/davinci_pas_test_kit/pas_bundle_validation.rb', line 30 def perform_request_validation(bundle, profile_url, version, request_type) validate_pa_request_payload_structure(bundle, request_type) validate_resources_conformance_against_profile(bundle, profile_url, version, request_type) end |
#perform_response_validation(response_bundle, profile_url, version, request_type, request_bundle = nil) ⇒ Object
35 36 37 38 |
# File 'lib/davinci_pas_test_kit/pas_bundle_validation.rb', line 35 def perform_response_validation(response_bundle, profile_url, version, request_type, request_bundle = nil) validate_pa_response_body_structure(response_bundle, request_bundle) if request_type == 'submit' validate_resources_conformance_against_profile(response_bundle, profile_url, version, request_type) end |
#process_instance_profiles(instance, bundle_entry, reference_element, version) ⇒ Object
Processes the profiles associated with a given instance in a FHIR bundle. It adds the instance’s profiles to the resource target profile map and handles recursive profile extraction. The profiles collected here are possible profiles the given instance may conform to. The conformance validation will ensure that the resource is conformant to at least one of the target profiles.
307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 |
# File 'lib/davinci_pas_test_kit/pas_bundle_validation.rb', line 307 def process_instance_profiles(instance, bundle_entry, reference_element, version) add_resource_target_profile_to_map(instance.fullUrl, instance.resource) # Add the declared profile conformance add_declared_profiles(instance, bundle_entry, version) reference_element[:profiles].each do |profile_url| # NOTE: the IG does not have the metadata for us-core profiles. = ("v#{version}")[profile_url] resource_type = instance.resource.resourceType next unless &.resource == resource_type || profile_url.include?(resource_type) add_profile_to_instance(instance, profile_url, bundle_entry, version) # NOTE: The algorithm assumes OR semantics for profile conformance, where the resource needs to conform to # at least one of the collected profiles. However, it may not cover all scenarios, such as cases # where AND semantics are required for multiple profile conformance. Also, it does not address complex # situations where profile requirements may conflict or have dependencies across referenced instances. # Therefore, this algorithm may not provide complete validation for all scenarios, and additional checks may be # necessary depending on the use case. end end |
#process_reference_element(reference_element, current_entry, bundle_entry, bundle_map, version) ⇒ Object
Processes a given reference element definition from a FHIR bundle entry. It evaluates FHIRPath expressions and processes each referenced instance and its profiles.
284 285 286 287 288 289 290 291 292 293 294 295 296 297 |
# File 'lib/davinci_pas_test_kit/pas_bundle_validation.rb', line 284 def process_reference_element(reference_element, current_entry, bundle_entry, bundle_map, version) fhirpath_result = evaluate_fhirpath(resource: current_entry.resource, path: reference_element[:path]) reference_element_values = fhirpath_result.filter_map do |entry| entry['element']&.reference if entry['type'] == 'Reference' end referenced_instances = reference_element_values.filter_map do |value| find_referenced_instance_in_bundle(value, current_entry.fullUrl, bundle_map) end referenced_instances.each do |instance| process_instance_profiles(instance, bundle_entry, reference_element, version) end end |
#resource_present_in_pa_request_and_response_msg(resource) ⇒ Object
Generates a message for a resource present in both the PA request and response bundles.
This method generates an error message when a resource appears in both the PA request and response bundles but does not have the same fullUrl or identifiers.
542 543 544 545 546 547 |
# File 'lib/davinci_pas_test_kit/pas_bundle_validation.rb', line 542 def resource_present_in_pa_request_and_response_msg(resource) " Resource #{resource.resourceType}/#{resource.id} is an entry in both the PA Request Bundle and the Response Bundle, but they do not have the same fullUrl or identifiers " end |
#resource_shall_appear_once_message(absolute_ref, total_matches) ⇒ Object
Generates a message for a resource that appears more than once in a bundle.
This method generates an error message when a referenced resource appears more than once in a FHIR bundle, which is not allowed.
529 530 531 532 533 534 |
# File 'lib/davinci_pas_test_kit/pas_bundle_validation.rb', line 529 def (absolute_ref, total_matches) " The referenced #{absolute_ref} resource SHALL appear exactly once in the Bundle, but found #{total_matches}. " end |
#save_bundles_and_entries_to_scratch(bundles) ⇒ Object
18 19 20 21 22 23 24 |
# File 'lib/davinci_pas_test_kit/pas_bundle_validation.rb', line 18 def save_bundles_and_entries_to_scratch(bundles) bundles.each do |bundle| all_scratch_resources << bundle all_scratch_resources.concat(bundle.entry.map(&:resource)) all_scratch_resources.uniq! end end |
#valid_url_or_urn_uuid?(string) ⇒ Boolean
Checks if a string is a valid url or in the form “urn:uuid:[some guid]”
446 447 448 449 450 451 |
# File 'lib/davinci_pas_test_kit/pas_bundle_validation.rb', line 446 def valid_url_or_urn_uuid?(string) url_regex = /\A#{URI::DEFAULT_PARSER.make_regexp(%w[http https])}\z/ urn_uuid_regex = /\Aurn:uuid:[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}\z/i string&.match?(url_regex) || string&.match?(urn_uuid_regex) end |
#validate_bundle_entries_against_profiles(version) ⇒ Object
Validates bundle resource and each entry in the bundle against its target profiles. It logs a message for each conformant entry and collects error messages for non-conformant entries. Asserts that there are no validation errors.
211 212 213 214 215 216 217 218 219 220 221 222 |
# File 'lib/davinci_pas_test_kit/pas_bundle_validation.rb', line 211 def validate_bundle_entries_against_profiles(version) bundle_resources_target_profile_map.each_value do |item| resource = item[:resource] base_profile = FHIR::Definitions.resource_definition(resource.resourceType).url success_profile = item[:profile_urls].find do |url| profile_to_validate = url == base_profile ? url : "#{url}|#{version}" resource_is_valid?(resource:, profile_url: profile_to_validate) end << (item) unless success_profile end end |
#validate_bundle_entries_full_url(bundle) ⇒ Object
435 436 437 438 439 440 441 |
# File 'lib/davinci_pas_test_kit/pas_bundle_validation.rb', line 435 def validate_bundle_entries_full_url(bundle) msg = "[Bundle/#{bundle.id}]: Bundle.entry.fullUrl values SHALL be a valid url or in the form " \ "'urn:uuid:[some guid]'." bundle.entry.each do |entry| << msg unless valid_url_or_urn_uuid?(entry.fullUrl) end end |
#validate_pa_request_payload_structure(bundle, request_type) ⇒ Object
Validates the structure of a Prior Authorization (PA) request Bundle.
This method performs various checks on the PA request payload, including validating the FHIR bundle structure, checking the resource type, and validating the resources referenced in the Claim resource are included in the bundle. It ensures that the first entry in the Bundle is a Claim resource and additional entries are populated with referenced resources, following the traversal of references. Duplicate resources are handled as required (appearing only once in the bundle entry).
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 |
# File 'lib/davinci_pas_test_kit/pas_bundle_validation.rb', line 75 def validate_pa_request_payload_structure(bundle, request_type) bundle_entry_resources = bundle.entry.map(&:resource) first_entry = bundle_entry_resources.first base_url = extract_base_url(bundle.entry.first&.fullUrl) check_presence_of_referenced_resources(first_entry, base_url, bundle.entry) if request_type == 'submit' unless first_entry.is_a?(FHIR::Claim) << "[Bundle/#{bundle.id}]: The first bundle entry must be a Claim" end validate_uniqueness_of_supporting_info_sequences(first_entry) validate_bundle_entries_full_url(bundle) else claim_resource = bundle_entry_resources.find { |resource| resource.resourceType == 'Claim' } if claim_resource.blank? << "[Bundle/#{bundle.id}]: Claim must be present for inquiry request" end # The inquiry operation must contain a requesting provider organization, # a payer organization, and a patient for the inquiry patient_reference = claim_resource&.patient&.reference provider_reference = claim_resource&.provider&.reference payer_reference = claim_resource&.insurer&.reference if patient_reference.blank? << "[Bundle/#{bundle.id}]: The Claim for inquiry operation must reference a patient." end if provider_reference.blank? << "[Bundle/#{bundle.id}]: The claim for inquiry operation must reference " \ 'a requesting provider organization.' end if payer_reference.blank? << "[Bundle/#{bundle.id}]: The Claim for inquiry operation must contain " \ 'a payer organization.' end end end |
#validate_pa_response_body_structure(pa_response_bundle, pa_request_bundle) ⇒ Object
Validates the response body structure of a Prior Authorization (PA) response.
This method performs validation of the PA response bundle structure. It follows the PAS IG requirement that the FHIR Bundle generated from the response starts with a ClaimResponse entry. For response of $submit request: Additional Bundle entries are populated with resources referenced by the ClaimResponse or descendant references, ensuring that only one resource is created for a given combination of content. Resources echoed back from the request are validated to ensure the same fullUrl and resource identifiers as in the request are used.
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
# File 'lib/davinci_pas_test_kit/pas_bundle_validation.rb', line 130 def validate_pa_response_body_structure(pa_response_bundle, pa_request_bundle) first_entry = pa_response_bundle.entry.first.resource unless first_entry.is_a?(FHIR::ClaimResponse) << "[Bundle/#{pa_response_bundle.id}]: The first bundle entry must be a ClaimResponse" end base_url = extract_base_url(pa_response_bundle.entry.last&.fullUrl) check_presence_of_referenced_resources(first_entry, base_url, pa_response_bundle.entry) # Testing: When echoing back resources that are the same as were present in the prior authorization request, # the system SHALL ensure that the same fullUrl and resource identifiers are used in the response as appeared # in the request # pa_request_bundle = FHIR.from_contents(pa_request_bundle) # pa_response_bundle.entry.each do |entry| # res = entry.resource # request_entry = pa_request_bundle.entry.find do |ent| # ent.resource.resourceType == res.resourceType && ent.resource.id == res.id # end # next unless request_entry.present? # assert( # request_entry.fullUrl == entry.fullUrl && request_entry.resource.identifier == res.identifier, # resource_present_in_pa_request_and_response_msg(res) # ) # end end |
#validate_pas_bundle_json(json, profile_url, version, request_type, bundle_type, skips: false, message: '') ⇒ Object
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
# File 'lib/davinci_pas_test_kit/pas_bundle_validation.rb', line 40 def validate_pas_bundle_json(json, profile_url, version, request_type, bundle_type, skips: false, message: '') assert_valid_json(json) bundle = FHIR.from_contents(json) assert bundle.present?, 'Not a FHIR resource' assert_resource_type(:bundle, resource: bundle) if bundle_type == 'request_bundle' perform_request_validation(bundle, profile_url, version, request_type) else perform_response_validation(bundle, profile_url, version, request_type) end .each do |msg| << { type: 'error', message: msg } end msg = 'Bundle response returned and/or entry resources are not conformant. Check messages for issues found.' assert .blank?, msg rescue Inferno::Exceptions::AssertionException => e msg = "#{message} #{e.message}".strip raise e.class, msg unless skips skip msg end |
#validate_resources_conformance_against_profile(bundle, profile_url, version, request_type) ⇒ Object
Profile conformance of Prior Authorization (PA) resources.
This method performs conformance validation on the PA bundle and bundle entries. The request/response bundle and includes resources are validated against their respective profile.
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 |
# File 'lib/davinci_pas_test_kit/pas_bundle_validation.rb', line 168 def validate_resources_conformance_against_profile(bundle, profile_url, version, request_type) add_resource_target_profile_to_map('bundle', bundle, profile_url) bundle_entry = bundle.entry root_entry = bundle_entry.find do |entry| ['Claim', 'ClaimResponse'].include?(entry.resource.resourceType) end if root_entry.present? root_resource_profile_url = find_profile_url(request_type)[root_entry.resource.resourceType] add_resource_target_profile_to_map(root_entry.fullUrl, root_entry.resource, root_resource_profile_url) extract_profiles_to_validate_each_entry(bundle_entry, root_entry, root_resource_profile_url, version) end validate_bundle_entries_against_profiles(version) end |
#validate_uniqueness_of_supporting_info_sequences(claim) ⇒ Object
Checks the following requirement: The Claim.supportingInfo.sequence for each entry SHALL be unique within the Claim.
Since the cardinality for Claim.supportingInfo is 0..*, we will check the uniqueness if Array not empty.
421 422 423 424 425 426 427 428 429 430 431 432 433 |
# File 'lib/davinci_pas_test_kit/pas_bundle_validation.rb', line 421 def validate_uniqueness_of_supporting_info_sequences(claim) return unless claim.is_a?(FHIR::Claim) supporting_info = claim.supportingInfo return unless supporting_info.present? sequences = supporting_info.map(&:sequence) is_unique = sequences.uniq.length == sequences.length return if is_unique << "[Claim/#{claim.id}]: The sequence element for each supportingInfo entry SHALL be " \ 'unique within the Claim.' end |
#validation_error_messages ⇒ Object
26 27 28 |
# File 'lib/davinci_pas_test_kit/pas_bundle_validation.rb', line 26 def ||= [] end |