davinci_pas_test_kit 0.9.0
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 +7 -0
- data/LICENSE +201 -0
- data/lib/davinci_pas_test_kit/client_suite.rb +289 -0
- data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/claim_status/pas_claim_status_test.rb +109 -0
- data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/client_tests/pas_client_approval_submit_response_attest.rb +39 -0
- data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/client_tests/pas_client_approval_submit_test.rb +38 -0
- data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/client_tests/pas_client_denial_submit_response_attest.rb +38 -0
- data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/client_tests/pas_client_denial_submit_test.rb +43 -0
- data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/client_tests/pas_client_inquire_must_support_test.rb +51 -0
- data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/client_tests/pas_client_pended_inquire_response_attest.rb +39 -0
- data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/client_tests/pas_client_pended_inquire_test.rb +35 -0
- data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/client_tests/pas_client_pended_submit_response_attest.rb +39 -0
- data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/client_tests/pas_client_pended_submit_test.rb +43 -0
- data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/client_tests/pas_client_submit_must_support_test.rb +57 -0
- data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/client_tests/pas_client_token_request_test.rb +31 -0
- data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/client_tests/pas_client_token_validation_test.rb +18 -0
- data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/error_tests/nonconformant_pas_bundle.json +16 -0
- data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/error_tests/pas_inquiry_error_test.rb +38 -0
- data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/error_tests/pas_submission_error_test.rb +56 -0
- data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/must_support/device_request_metadata.yml +112 -0
- data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/must_support/medication_request_metadata.yml +183 -0
- data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/must_support/nutrition_order_metadata.yml +109 -0
- data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/must_support/pas_client_must_support_requirement_test.rb +117 -0
- data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/must_support/pas_server_must_support_requirement_test.rb +116 -0
- data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/must_support/service_request_metadata.yml +148 -0
- data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/pas_client_approval_group.rb +26 -0
- data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/pas_client_authentication_group.rb +49 -0
- data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/pas_client_denial_group.rb +41 -0
- data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/pas_client_pended_group.rb +56 -0
- data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/pas_error_group.rb +20 -0
- data/lib/davinci_pas_test_kit/ext/inferno_core/record_response_route.rb +98 -0
- data/lib/davinci_pas_test_kit/ext/inferno_core/request.rb +19 -0
- data/lib/davinci_pas_test_kit/ext/inferno_core/runnable.rb +18 -0
- data/lib/davinci_pas_test_kit/fhir_resource_navigation.rb +72 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/beneficiary/client_inquiry_request_beneficiary_must_support_test.rb +75 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/beneficiary/client_submit_request_beneficiary_must_support_test.rb +75 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/beneficiary/metadata.yml +162 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/beneficiary/server_inquiry_request_beneficiary_must_support_test.rb +75 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/beneficiary/server_inquiry_response_beneficiary_must_support_test.rb +75 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/beneficiary/server_submit_request_beneficiary_must_support_test.rb +75 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/beneficiary/server_submit_response_beneficiary_must_support_test.rb +75 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/claim/claim_operation_test.rb +67 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/claim/metadata.yml +577 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/claim_inquiry/claim_inquiry_operation_test.rb +57 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/claim_inquiry/client_inquiry_request_claim_inquiry_must_support_test.rb +95 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/claim_inquiry/metadata.yml +516 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/claim_inquiry/server_inquiry_request_claim_inquiry_must_support_test.rb +95 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/claim_update/client_submit_request_claim_update_must_support_test.rb +102 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/claim_update/metadata.yml +591 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/claim_update/server_submit_request_claim_update_must_support_test.rb +102 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/claiminquiryresponse/metadata.yml +311 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/claiminquiryresponse/server_inquiry_response_claiminquiryresponse_must_support_test.rb +73 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/claimresponse/metadata.yml +318 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/claimresponse/server_submit_response_claimresponse_must_support_test.rb +75 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/client_tests/client_denial_pas_response_bundle_validation_test.rb +53 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/client_tests/client_pas_request_bundle_validation_test.rb +55 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/client_tests/client_pended_pas_inquiry_request_bundle_validation_test.rb +55 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/client_tests/client_pended_pas_response_bundle_validation_test.rb +53 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/communication_request/metadata.yml +130 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/communication_request/server_submit_response_communication_request_must_support_test.rb +58 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/coverage/client_inquiry_request_coverage_must_support_test.rb +55 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/coverage/client_submit_request_coverage_must_support_test.rb +55 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/coverage/metadata.yml +111 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/coverage/server_inquiry_request_coverage_must_support_test.rb +55 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/coverage/server_submit_request_coverage_must_support_test.rb +55 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/device_request/client_submit_request_device_request_must_support_test.rb +51 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/device_request/metadata.yml +112 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/device_request/server_submit_request_device_request_must_support_test.rb +51 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/encounter/client_submit_request_encounter_must_support_test.rb +67 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/encounter/metadata.yml +213 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/encounter/server_submit_request_encounter_must_support_test.rb +67 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/insurer/client_inquiry_request_insurer_must_support_test.rb +60 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/insurer/client_submit_request_insurer_must_support_test.rb +60 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/insurer/metadata.yml +104 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/insurer/server_inquiry_request_insurer_must_support_test.rb +60 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/insurer/server_inquiry_response_insurer_must_support_test.rb +60 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/insurer/server_submit_request_insurer_must_support_test.rb +60 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/insurer/server_submit_response_insurer_must_support_test.rb +60 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/medication_request/client_submit_request_medication_request_must_support_test.rb +61 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/medication_request/metadata.yml +183 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/medication_request/server_submit_request_medication_request_must_support_test.rb +61 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/metadata.yml +5253 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/nutrition_order/client_submit_request_nutrition_order_must_support_test.rb +53 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/nutrition_order/metadata.yml +109 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/nutrition_order/server_submit_request_nutrition_order_must_support_test.rb +53 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_client_inquiry_must_support_use_case_group.rb +51 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_client_submit_must_support_use_case_group.rb +61 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_inquiry_request_bundle/client_inquiry_request_pas_inquiry_request_bundle_must_support_test.rb +53 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_inquiry_request_bundle/metadata.yml +77 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_inquiry_request_bundle/server_inquiry_request_pas_inquiry_request_bundle_must_support_test.rb +53 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_inquiry_request_bundle/server_pas_inquiry_request_bundle_validation_test.rb +83 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_inquiry_response_bundle/metadata.yml +67 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_inquiry_response_bundle/server_inquiry_response_pas_inquiry_response_bundle_must_support_test.rb +52 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_inquiry_response_bundle/server_pas_inquiry_response_bundle_validation_test.rb +80 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_request_bundle/client_submit_request_pas_request_bundle_must_support_test.rb +53 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_request_bundle/metadata.yml +77 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_request_bundle/server_pas_request_bundle_validation_test.rb +83 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_request_bundle/server_submit_request_pas_request_bundle_must_support_test.rb +53 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_response_bundle/metadata.yml +71 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_response_bundle/server_pas_response_bundle_validation_test.rb +80 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_response_bundle/server_submit_response_pas_response_bundle_must_support_test.rb +52 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_server_approval_use_case_group.rb +59 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_server_denial_use_case_group.rb +59 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_server_must_support_use_case_group.rb +265 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_server_pended_use_case_group.rb +84 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/practitioner/client_inquiry_request_practitioner_must_support_test.rb +53 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/practitioner/client_submit_request_practitioner_must_support_test.rb +53 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/practitioner/metadata.yml +74 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/practitioner/server_inquiry_request_practitioner_must_support_test.rb +53 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/practitioner/server_inquiry_response_practitioner_must_support_test.rb +53 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/practitioner/server_submit_request_practitioner_must_support_test.rb +53 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/practitioner/server_submit_response_practitioner_must_support_test.rb +53 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/practitioner_role/client_inquiry_request_practitioner_role_must_support_test.rb +49 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/practitioner_role/client_submit_request_practitioner_role_must_support_test.rb +49 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/practitioner_role/metadata.yml +81 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/practitioner_role/server_inquiry_request_practitioner_role_must_support_test.rb +49 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/practitioner_role/server_inquiry_response_practitioner_role_must_support_test.rb +49 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/practitioner_role/server_submit_request_practitioner_role_must_support_test.rb +49 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/practitioner_role/server_submit_response_practitioner_role_must_support_test.rb +49 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/requestor/client_inquiry_request_requestor_must_support_test.rb +63 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/requestor/client_submit_request_requestor_must_support_test.rb +63 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/requestor/metadata.yml +107 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/requestor/server_inquiry_request_requestor_must_support_test.rb +63 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/requestor/server_inquiry_response_requestor_must_support_test.rb +63 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/requestor/server_submit_request_requestor_must_support_test.rb +63 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/requestor/server_submit_response_requestor_must_support_test.rb +63 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/resource_list.rb +54 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/server_suite.rb +236 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/service_request/client_submit_request_service_request_must_support_test.rb +53 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/service_request/metadata.yml +148 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/service_request/server_submit_request_service_request_must_support_test.rb +53 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/subscriber/client_inquiry_request_subscriber_must_support_test.rb +74 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/subscriber/client_submit_request_subscriber_must_support_test.rb +74 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/subscriber/metadata.yml +159 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/subscriber/server_inquiry_request_subscriber_must_support_test.rb +74 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/subscriber/server_submit_request_subscriber_must_support_test.rb +74 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/task/metadata.yml +192 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/task/server_inquiry_response_task_must_support_test.rb +61 -0
- data/lib/davinci_pas_test_kit/generated/v2.0.1/task/server_submit_response_task_must_support_test.rb +61 -0
- data/lib/davinci_pas_test_kit/generator/group_generator.rb +440 -0
- data/lib/davinci_pas_test_kit/generator/group_metadata.rb +73 -0
- data/lib/davinci_pas_test_kit/generator/group_metadata_extractor.rb +244 -0
- data/lib/davinci_pas_test_kit/generator/ig_loader.rb +78 -0
- data/lib/davinci_pas_test_kit/generator/ig_metadata.rb +66 -0
- data/lib/davinci_pas_test_kit/generator/ig_metadata_extractor.rb +54 -0
- data/lib/davinci_pas_test_kit/generator/ig_resources.rb +74 -0
- data/lib/davinci_pas_test_kit/generator/must_support_check_profiles.rb +86 -0
- data/lib/davinci_pas_test_kit/generator/must_support_metadata_extractor.rb +327 -0
- data/lib/davinci_pas_test_kit/generator/must_support_test_generator.rb +155 -0
- data/lib/davinci_pas_test_kit/generator/naming.rb +50 -0
- data/lib/davinci_pas_test_kit/generator/operation_test_generator.rb +136 -0
- data/lib/davinci_pas_test_kit/generator/resource_list_generator.rb +59 -0
- data/lib/davinci_pas_test_kit/generator/suite_generator.rb +94 -0
- data/lib/davinci_pas_test_kit/generator/terminology_binding_metadata_extractor.rb +108 -0
- data/lib/davinci_pas_test_kit/generator/validation_test_generator.rb +181 -0
- data/lib/davinci_pas_test_kit/generator/value_extractor.rb +48 -0
- data/lib/davinci_pas_test_kit/generator.rb +80 -0
- data/lib/davinci_pas_test_kit/mock_server.rb +189 -0
- data/lib/davinci_pas_test_kit/must_support_test.rb +267 -0
- data/lib/davinci_pas_test_kit/pas_bundle_validation.rb +568 -0
- data/lib/davinci_pas_test_kit/tags.rb +7 -0
- data/lib/davinci_pas_test_kit/urls.rb +39 -0
- data/lib/davinci_pas_test_kit/user_input_response.rb +32 -0
- data/lib/davinci_pas_test_kit/validation_test.rb +58 -0
- data/lib/davinci_pas_test_kit/validator_suppressions.rb +143 -0
- data/lib/davinci_pas_test_kit/version.rb +5 -0
- data/lib/davinci_pas_test_kit.rb +2 -0
- metadata +281 -0
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
require_relative 'group_metadata'
|
|
2
|
+
require_relative 'ig_metadata'
|
|
3
|
+
require_relative 'must_support_metadata_extractor'
|
|
4
|
+
require_relative 'terminology_binding_metadata_extractor'
|
|
5
|
+
|
|
6
|
+
module DaVinciPASTestKit
|
|
7
|
+
class Generator
|
|
8
|
+
class GroupMetadataExtractor
|
|
9
|
+
attr_accessor :resource_capabilities, :profile_url, :ig_metadata, :ig_resources
|
|
10
|
+
|
|
11
|
+
def initialize(resource_capabilities, profile_url, ig_metadata, ig_resources)
|
|
12
|
+
self.resource_capabilities = resource_capabilities
|
|
13
|
+
self.profile_url = profile_url
|
|
14
|
+
self.ig_metadata = ig_metadata
|
|
15
|
+
self.ig_resources = ig_resources
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def group_metadata
|
|
19
|
+
@group_metadata ||=
|
|
20
|
+
GroupMetadata.new(group_metadata_hash)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def group_metadata_hash
|
|
24
|
+
@group_metadata_hash ||=
|
|
25
|
+
{
|
|
26
|
+
name:,
|
|
27
|
+
class_name:,
|
|
28
|
+
version:,
|
|
29
|
+
reformatted_version:,
|
|
30
|
+
resource:,
|
|
31
|
+
conformance_expectation:,
|
|
32
|
+
profile_url:,
|
|
33
|
+
profile_name:,
|
|
34
|
+
profile_version:,
|
|
35
|
+
title:,
|
|
36
|
+
short_description:,
|
|
37
|
+
interactions:,
|
|
38
|
+
operations:,
|
|
39
|
+
# searches:,
|
|
40
|
+
# search_definitions:,
|
|
41
|
+
# include_params:,
|
|
42
|
+
# revincludes:,
|
|
43
|
+
required_concepts:,
|
|
44
|
+
must_supports:,
|
|
45
|
+
mandatory_elements:,
|
|
46
|
+
bindings:,
|
|
47
|
+
references:
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
# mark_mandatory_and_must_support_searches
|
|
51
|
+
|
|
52
|
+
@group_metadata_hash
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# def mark_mandatory_and_must_support_searches
|
|
56
|
+
# searches.each do |search|
|
|
57
|
+
# search[:names_not_must_support_or_mandatory] = search[:names].reject do |name|
|
|
58
|
+
# full_paths = search_definitions[name.to_sym][:full_paths]
|
|
59
|
+
# any_must_support_elements = must_supports[:elements].any? do |element|
|
|
60
|
+
# full_must_support_paths = ["#{resource}.#{element[:original_path]}", "#{resource}.#{element[:path]}"]
|
|
61
|
+
|
|
62
|
+
# full_paths.any? do |path|
|
|
63
|
+
# # allow for non-choice, choice types, and _id
|
|
64
|
+
# name == '_id' ||
|
|
65
|
+
# full_must_support_paths.include?(path) ||
|
|
66
|
+
# full_must_support_paths.include?("#{path}[x]")
|
|
67
|
+
# end
|
|
68
|
+
# end
|
|
69
|
+
|
|
70
|
+
# any_must_support_slices = must_supports[:slices].any? do |slice|
|
|
71
|
+
# # only handle type slices because that is all we need for now
|
|
72
|
+
# # for a slice like Observation.effective[x]:effectiveDateTime, the search parameter's expression could
|
|
73
|
+
# # be either Observation.effective or Observation.effectiveDateTime.
|
|
74
|
+
# if slice[:discriminator] && slice[:discriminator][:type] == 'type'
|
|
75
|
+
# full_must_support_path = "#{resource}.#{slice[:path].sub('[x]', slice[:discriminator][:code])}"
|
|
76
|
+
# base_must_support_path = "#{resource}.#{slice[:path].sub('[x]', '')}"
|
|
77
|
+
|
|
78
|
+
# full_paths.intersection([full_must_support_path, base_must_support_path]).present?
|
|
79
|
+
# else
|
|
80
|
+
# false
|
|
81
|
+
# end
|
|
82
|
+
# end
|
|
83
|
+
|
|
84
|
+
# any_mandatory_elements = mandatory_elements.any? do |element|
|
|
85
|
+
# full_paths.include?(element)
|
|
86
|
+
# end
|
|
87
|
+
|
|
88
|
+
# any_must_support_elements || any_must_support_slices || any_mandatory_elements
|
|
89
|
+
# end
|
|
90
|
+
|
|
91
|
+
# search[:must_support_or_mandatory] = search[:names_not_must_support_or_mandatory].empty?
|
|
92
|
+
# end
|
|
93
|
+
# end
|
|
94
|
+
|
|
95
|
+
def profile
|
|
96
|
+
@profile ||= ig_resources.profile_by_url(profile_url)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def profile_elements
|
|
100
|
+
@profile_elements ||= profile.snapshot.element
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def base_name
|
|
104
|
+
profile_url.split('StructureDefinition/').last
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def name
|
|
108
|
+
base_name.tr('-', '_')
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def class_name
|
|
112
|
+
base_name
|
|
113
|
+
.split('-')
|
|
114
|
+
.map(&:capitalize)
|
|
115
|
+
.join
|
|
116
|
+
.gsub('PAS', "PAS#{ig_metadata.reformatted_version}")
|
|
117
|
+
.concat('Sequence')
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def version
|
|
121
|
+
ig_metadata.ig_version
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def reformatted_version
|
|
125
|
+
ig_metadata.reformatted_version
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def resource
|
|
129
|
+
profile.type
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def conformance_expectation
|
|
133
|
+
resource_capabilities&.extension&.first&.valueCode
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def profile_name
|
|
137
|
+
profile.title.gsub(' ', ' ')
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def profile_version
|
|
141
|
+
profile.version
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def title
|
|
145
|
+
puts profile.title
|
|
146
|
+
profile.title.gsub(/PAS\s*/, '').gsub(/\s*Profile/, '').strip
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def short_description
|
|
150
|
+
"Verify support for the server capabilities required by the #{profile_name}."
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def interactions
|
|
154
|
+
@interactions ||=
|
|
155
|
+
resource_capabilities.interaction.map do |interaction|
|
|
156
|
+
{
|
|
157
|
+
code: interaction.code,
|
|
158
|
+
expectation: interaction&.extension&.first&.valueCode # TODO: fix expectation extension finding
|
|
159
|
+
}
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def operations
|
|
164
|
+
@operations ||=
|
|
165
|
+
resource_capabilities.operation.map do |operation|
|
|
166
|
+
{
|
|
167
|
+
code: operation.name,
|
|
168
|
+
expectation: operation&.extension&.first&.valueCode # TODO: fix expectation extension finding
|
|
169
|
+
}
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
# def search_metadata_extractor
|
|
174
|
+
# @search_metadata_extractor ||=
|
|
175
|
+
# SearchMetadataExtractor.new(resource_capabilities, ig_resources, resource, profile_elements)
|
|
176
|
+
# end
|
|
177
|
+
|
|
178
|
+
# def searches
|
|
179
|
+
# @searches ||= search_metadata_extractor.searches
|
|
180
|
+
# end
|
|
181
|
+
|
|
182
|
+
# def search_definitions
|
|
183
|
+
# @search_definitions ||= search_metadata_extractor.search_definitions
|
|
184
|
+
# end
|
|
185
|
+
|
|
186
|
+
# def include_params
|
|
187
|
+
# resource_capabilities.searchInclude || []
|
|
188
|
+
# end
|
|
189
|
+
|
|
190
|
+
# def revincludes
|
|
191
|
+
# resource_capabilities.searchRevInclude || []
|
|
192
|
+
# end
|
|
193
|
+
|
|
194
|
+
def required_concepts
|
|
195
|
+
return [] if resource == 'Observation'
|
|
196
|
+
|
|
197
|
+
profile_elements
|
|
198
|
+
.select { |element| element.type&.any? { |type| type.code == 'CodeableConcept' } }
|
|
199
|
+
.select { |element| element.binding&.strength == 'required' }
|
|
200
|
+
.map { |element| element.path.gsub("#{resource}.", '').gsub('[x]', 'CodeableConcept') }
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
def terminology_binding_metadata_extractor
|
|
204
|
+
@terminology_binding_metadata_extractor ||=
|
|
205
|
+
TerminologyBindingMetadataExtractor.new(profile_elements, ig_resources, resource)
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
def bindings
|
|
209
|
+
@bindings ||=
|
|
210
|
+
terminology_binding_metadata_extractor.terminology_bindings
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
def must_support_metadata_extractor
|
|
214
|
+
@must_support_metadata_extractor ||=
|
|
215
|
+
MustSupportMetadataExtractor.new(profile_elements, profile, resource, ig_resources)
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
def must_supports
|
|
219
|
+
@must_supports ||=
|
|
220
|
+
must_support_metadata_extractor.must_supports
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
def mandatory_elements
|
|
224
|
+
@mandatory_elements ||=
|
|
225
|
+
profile_elements
|
|
226
|
+
.select { |element| element.min.positive? }
|
|
227
|
+
.map(&:path)
|
|
228
|
+
.uniq
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
def references
|
|
232
|
+
@references ||=
|
|
233
|
+
profile_elements
|
|
234
|
+
.select { |element| element.type&.first&.code == 'Reference' }
|
|
235
|
+
.map do |reference_definition|
|
|
236
|
+
{
|
|
237
|
+
path: reference_definition.path,
|
|
238
|
+
profiles: reference_definition.type.first.targetProfile
|
|
239
|
+
}
|
|
240
|
+
end
|
|
241
|
+
end
|
|
242
|
+
end
|
|
243
|
+
end
|
|
244
|
+
end
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
require 'active_support/all'
|
|
2
|
+
require 'fhir_models'
|
|
3
|
+
require 'pathname'
|
|
4
|
+
require 'rubygems/package'
|
|
5
|
+
require 'zlib'
|
|
6
|
+
require 'pry'
|
|
7
|
+
require_relative 'ig_resources'
|
|
8
|
+
|
|
9
|
+
module DaVinciPASTestKit
|
|
10
|
+
class Generator
|
|
11
|
+
class IGLoader
|
|
12
|
+
attr_accessor :ig_file_name
|
|
13
|
+
|
|
14
|
+
def initialize(ig_file_name)
|
|
15
|
+
self.ig_file_name = ig_file_name
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def ig_resources
|
|
19
|
+
@ig_resources ||= IGResources.new
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def load
|
|
23
|
+
load_ig
|
|
24
|
+
load_standalone_resources
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def load_ig
|
|
28
|
+
tar = Gem::Package::TarReader.new(
|
|
29
|
+
Zlib::GzipReader.open(ig_file_name)
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
tar.each do |entry|
|
|
33
|
+
next if entry.directory?
|
|
34
|
+
|
|
35
|
+
file_name = entry.full_name.split('/').last
|
|
36
|
+
|
|
37
|
+
next unless file_name.end_with? '.json'
|
|
38
|
+
|
|
39
|
+
next unless entry.full_name.start_with? 'package/'
|
|
40
|
+
|
|
41
|
+
begin
|
|
42
|
+
resource = FHIR.from_contents(entry.read)
|
|
43
|
+
next if resource.nil?
|
|
44
|
+
rescue StandardError
|
|
45
|
+
puts "#{file_name} does not appear to be a FHIR resource."
|
|
46
|
+
next
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
ig_resources.add(resource)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
ig_resources
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def load_standalone_resources
|
|
56
|
+
ig_directory = ig_file_name.chomp('.tgz')
|
|
57
|
+
|
|
58
|
+
return ig_resources unless File.exist? ig_directory
|
|
59
|
+
|
|
60
|
+
Dir.glob(File.join(ig_directory, '*.json')).each do |file_path|
|
|
61
|
+
begin
|
|
62
|
+
resource = FHIR.from_contents(File.read(file_path))
|
|
63
|
+
|
|
64
|
+
next if resource.nil?
|
|
65
|
+
rescue StandardError
|
|
66
|
+
file_name = file_path.split('/').last
|
|
67
|
+
puts "#{file_name} does not appear to be a FHIR resource."
|
|
68
|
+
next
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
ig_resources.add(resource)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
ig_resources
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
module DaVinciPASTestKit
|
|
2
|
+
class Generator
|
|
3
|
+
class IGMetadata
|
|
4
|
+
attr_accessor :ig_version, :groups, :use_case_groups
|
|
5
|
+
|
|
6
|
+
def reformatted_version
|
|
7
|
+
@reformatted_version ||= ig_version.delete('.-')
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def ordered_groups
|
|
11
|
+
@ordered_groups ||=
|
|
12
|
+
[patient_group] + non_delayed_groups + delayed_groups
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def patient_group
|
|
16
|
+
@patient_group ||=
|
|
17
|
+
groups.find { |group| group.resource == 'Patient' }
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def delayed_groups
|
|
21
|
+
@delayed_groups ||=
|
|
22
|
+
groups.select(&:delayed?)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def non_delayed_groups
|
|
26
|
+
@non_delayed_groups ||=
|
|
27
|
+
groups.reject(&:delayed?) - [patient_group]
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def delayed_profiles
|
|
31
|
+
@delayed_profiles ||=
|
|
32
|
+
delayed_groups.map(&:profile_url)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def add_use_case_groups(id, file_name)
|
|
36
|
+
@use_case_groups ||= []
|
|
37
|
+
@use_case_groups << { id:, file_name: }
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def bundle_groups
|
|
41
|
+
@bundle_groups ||=
|
|
42
|
+
groups.select { |group| group.resource == 'Bundle' }
|
|
43
|
+
.reject { |group| group.profile_name.include?('Base') }
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def claim_groups
|
|
47
|
+
@claim_groups ||=
|
|
48
|
+
groups.select { |group| group.resource == 'Claim' }
|
|
49
|
+
.reject { |group| group.profile_name.include?('Base') }
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def postprocess_groups(ig_resources)
|
|
53
|
+
groups.each do |group|
|
|
54
|
+
group.add_delayed_references(delayed_profiles, ig_resources)
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def to_hash
|
|
59
|
+
{
|
|
60
|
+
ig_version:,
|
|
61
|
+
groups: groups.map(&:to_hash)
|
|
62
|
+
}
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
require_relative 'ig_metadata'
|
|
2
|
+
require_relative 'group_metadata_extractor'
|
|
3
|
+
require 'pry'
|
|
4
|
+
module DaVinciPASTestKit
|
|
5
|
+
class Generator
|
|
6
|
+
class IGMetadataExtractor
|
|
7
|
+
attr_accessor :ig_resources, :metadata
|
|
8
|
+
|
|
9
|
+
def initialize(ig_resources)
|
|
10
|
+
self.ig_resources = ig_resources
|
|
11
|
+
self.metadata = IGMetadata.new
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def extract
|
|
15
|
+
add_metadata_from_ig
|
|
16
|
+
add_metadata_from_resources
|
|
17
|
+
metadata
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def add_metadata_from_ig
|
|
21
|
+
metadata.ig_version = "v#{ig_resources.ig.version}"
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def resources_in_capability_statement
|
|
25
|
+
# TODO: uncomment bellow when PAS IG will have a solid capability statement.
|
|
26
|
+
# ig_resources.capability_statement.rest.first.resource
|
|
27
|
+
|
|
28
|
+
# Work around for the code above to extract the IG supported profiles/resources
|
|
29
|
+
resources = []
|
|
30
|
+
ig_resources.base_resources_and_supported_profiles.each do |k, v|
|
|
31
|
+
resource = FHIR::CapabilityStatement::Rest::Resource.new(
|
|
32
|
+
type: k,
|
|
33
|
+
supportedProfile: v,
|
|
34
|
+
operation: k == 'Claim' ? [{ name: '$submit' }, { name: '$inquire' }] : []
|
|
35
|
+
)
|
|
36
|
+
resources << resource
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
resources
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def add_metadata_from_resources
|
|
43
|
+
metadata.groups =
|
|
44
|
+
resources_in_capability_statement.flat_map do |resource|
|
|
45
|
+
resource.supportedProfile&.map do |supported_profile|
|
|
46
|
+
GroupMetadataExtractor.new(resource, supported_profile, metadata, ig_resources).group_metadata
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
metadata.postprocess_groups(ig_resources)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
module DaVinciPASTestKit
|
|
2
|
+
class Generator
|
|
3
|
+
class IGResources
|
|
4
|
+
def add(resource)
|
|
5
|
+
resources_by_type[resource.resourceType] << resource
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def capability_statement(mode = 'server')
|
|
9
|
+
resources_by_type['CapabilityStatement'].find do |capability_statement_resource|
|
|
10
|
+
capability_statement_resource.rest.any? { |r| r.mode == mode }
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def base_resources_and_supported_profiles
|
|
15
|
+
definitions = [
|
|
16
|
+
'ImplementationGuide',
|
|
17
|
+
'CapabilityStatement',
|
|
18
|
+
'CodeSystem',
|
|
19
|
+
'OperationDefinition',
|
|
20
|
+
'StructureDefinition',
|
|
21
|
+
'ValueSet'
|
|
22
|
+
]
|
|
23
|
+
base_resources = resources_by_type.keys.reject { |k| definitions.include?(k) }
|
|
24
|
+
resource_profiles = {}
|
|
25
|
+
base_resources.each do |res|
|
|
26
|
+
profile_urls = resources_by_type['StructureDefinition'].find_all { |p| p.type == res }.map(&:url)
|
|
27
|
+
resource_profiles[res] = profile_urls
|
|
28
|
+
end
|
|
29
|
+
resource_profiles
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def ig
|
|
33
|
+
resources_by_type['ImplementationGuide'].first
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def inspect
|
|
37
|
+
'IGResources'
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def profile_by_url(url)
|
|
41
|
+
resources_by_type['StructureDefinition'].find { |profile| profile.url == url }
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def resource_type_for_profile(url)
|
|
45
|
+
profile_by_url(url).type
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def value_set_by_url(url)
|
|
49
|
+
resources_by_type['ValueSet'].find { |profile| profile.url == url }
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# def search_param_by_resource_and_name(resource, name)
|
|
53
|
+
# # remove '_' from search parameter name, such as _id or _tag
|
|
54
|
+
# normalized_name = normalized_name = name.to_s.delete_prefix('_')
|
|
55
|
+
|
|
56
|
+
# param = resources_by_type['SearchParameter']
|
|
57
|
+
# .find { |param| param.id == "#{resource.downcase}-#{normalized_name}" }
|
|
58
|
+
|
|
59
|
+
# if param.nil?
|
|
60
|
+
# param = resources_by_type['SearchParameter']
|
|
61
|
+
# .find { |param| param.id == "Resource-#{normalized_name}" }
|
|
62
|
+
# end
|
|
63
|
+
|
|
64
|
+
# return param
|
|
65
|
+
# end
|
|
66
|
+
|
|
67
|
+
private
|
|
68
|
+
|
|
69
|
+
def resources_by_type
|
|
70
|
+
@resources_by_type ||= Hash.new { |hash, key| hash[key] = [] }
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
module DaVinciPASTestKit
|
|
2
|
+
class Generator
|
|
3
|
+
module MustSupportCheckProfiles
|
|
4
|
+
SUBMIT_REQUEST_REQUIRED_PROFILES = [
|
|
5
|
+
'PAS Request Bundle',
|
|
6
|
+
'PAS Beneficiary Patient',
|
|
7
|
+
'PAS Claim Update',
|
|
8
|
+
'PAS Coverage',
|
|
9
|
+
'PAS Device Request',
|
|
10
|
+
'PAS Encounter',
|
|
11
|
+
'PAS Insurer Organization',
|
|
12
|
+
'PAS Medication Request',
|
|
13
|
+
'PAS Nutrition Order',
|
|
14
|
+
'PAS Practitioner',
|
|
15
|
+
'PAS PractitionerRole',
|
|
16
|
+
'PAS Requestor Organization',
|
|
17
|
+
'PAS Service Request',
|
|
18
|
+
'PAS Subscriber Patient'
|
|
19
|
+
].freeze
|
|
20
|
+
|
|
21
|
+
SUBMIT_RESPONSE_REQUIRED_PROFILES = [
|
|
22
|
+
'PAS Beneficiary Patient',
|
|
23
|
+
'PAS Claim Response',
|
|
24
|
+
'PAS CommunicationRequest',
|
|
25
|
+
'PAS Insurer Organization',
|
|
26
|
+
'PAS Practitioner',
|
|
27
|
+
'PAS PractitionerRole',
|
|
28
|
+
'PAS Requestor Organization',
|
|
29
|
+
'PAS Response Bundle',
|
|
30
|
+
'PAS Task'
|
|
31
|
+
].freeze
|
|
32
|
+
|
|
33
|
+
INQUIRY_REQUEST_REQUIRED_PROFILES = [
|
|
34
|
+
'PAS Beneficiary Patient',
|
|
35
|
+
'PAS Claim Inquiry',
|
|
36
|
+
'PAS Coverage',
|
|
37
|
+
'PAS Inquiry Request Bundle',
|
|
38
|
+
'PAS Insurer Organization',
|
|
39
|
+
'PAS Practitioner',
|
|
40
|
+
'PAS PractitionerRole',
|
|
41
|
+
'PAS Requestor Organization',
|
|
42
|
+
'PAS Subscriber Patient'
|
|
43
|
+
].freeze
|
|
44
|
+
|
|
45
|
+
INQUIRY_RESPONSE_REQUIRED_PROFILES = [
|
|
46
|
+
'PAS Beneficiary Patient',
|
|
47
|
+
'PAS Claim Inquiry Response',
|
|
48
|
+
'PAS Inquiry Response Bundle',
|
|
49
|
+
'PAS Insurer Organization',
|
|
50
|
+
'PAS Practitioner',
|
|
51
|
+
'PAS PractitionerRole',
|
|
52
|
+
'PAS Requestor Organization',
|
|
53
|
+
'PAS Task'
|
|
54
|
+
].freeze
|
|
55
|
+
|
|
56
|
+
OPTIONAL_PROFILES = [
|
|
57
|
+
'PAS Medication Request',
|
|
58
|
+
'PAS Service Request',
|
|
59
|
+
'PAS Device Request',
|
|
60
|
+
'PAS Nutrition Order'
|
|
61
|
+
].freeze
|
|
62
|
+
|
|
63
|
+
class << self
|
|
64
|
+
def submit_request_group?(group)
|
|
65
|
+
SUBMIT_REQUEST_REQUIRED_PROFILES.include?(group.profile_name)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def submit_response_group?(group)
|
|
69
|
+
SUBMIT_RESPONSE_REQUIRED_PROFILES.include?(group.profile_name)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def inquiry_request_group?(group)
|
|
73
|
+
INQUIRY_REQUEST_REQUIRED_PROFILES.include?(group.profile_name)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def inquiry_response_group?(group)
|
|
77
|
+
INQUIRY_RESPONSE_REQUIRED_PROFILES.include?(group.profile_name)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def optional_group?(group)
|
|
81
|
+
OPTIONAL_PROFILES.include?(group.profile_name)
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|