usps-imis-api 0.15.3 → 1.0.0.pre.rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/main.yml +57 -0
- data/.gitignore +4 -0
- data/.rspec +2 -0
- data/.rubocop.yml +88 -0
- data/.ruby-version +1 -0
- data/.simplecov +8 -0
- data/Gemfile +12 -0
- data/Gemfile.lock +95 -0
- data/Rakefile +12 -0
- data/Readme.md +193 -25
- data/bin/console +21 -0
- data/bin/setup +8 -0
- data/lib/ext/hash.rb +10 -0
- data/lib/usps/imis/api.rb +135 -245
- data/lib/usps/imis/config.rb +10 -156
- data/lib/usps/imis/error/api.rb +26 -0
- data/lib/usps/imis/error/mapper.rb +9 -0
- data/lib/usps/imis/error/response.rb +75 -0
- data/lib/usps/imis/mapper.rb +21 -91
- data/lib/usps/imis/panel/base_panel.rb +42 -0
- data/lib/usps/imis/panel/education.rb +111 -0
- data/lib/usps/imis/panel/vsc.rb +109 -0
- data/lib/usps/imis/version.rb +1 -1
- data/lib/usps/imis.rb +23 -33
- data/spec/lib/usps/imis/api_spec.rb +143 -0
- data/spec/lib/usps/imis/config_spec.rb +33 -0
- data/spec/lib/usps/imis/error/api_spec.rb +17 -0
- data/spec/lib/usps/imis/error/response_spec.rb +107 -0
- data/spec/lib/usps/imis/mapper_spec.rb +31 -0
- data/spec/lib/usps/imis/panel/base_panel_spec.rb +32 -0
- data/spec/lib/usps/imis/panel/education_spec.rb +55 -0
- data/spec/lib/usps/imis/panel/vsc_spec.rb +38 -0
- data/spec/lib/usps/imis_spec.rb +11 -0
- data/spec/spec_helper.rb +35 -0
- data/usps-imis-api.gemspec +18 -0
- metadata +34 -596
- data/bin/imis +0 -8
- data/lib/usps/imis/base_data.rb +0 -87
- data/lib/usps/imis/blank_object.rb +0 -62
- data/lib/usps/imis/business_object.rb +0 -252
- data/lib/usps/imis/command_line/formatters.rb +0 -101
- data/lib/usps/imis/command_line/help.rb +0 -204
- data/lib/usps/imis/command_line/interface.rb +0 -186
- data/lib/usps/imis/command_line/options.yml +0 -167
- data/lib/usps/imis/command_line/options_parser.rb +0 -158
- data/lib/usps/imis/command_line/options_parser_config.rb +0 -82
- data/lib/usps/imis/command_line/performers.rb +0 -90
- data/lib/usps/imis/command_line.rb +0 -18
- data/lib/usps/imis/data.rb +0 -60
- data/lib/usps/imis/dependencies.rb +0 -33
- data/lib/usps/imis/error.rb +0 -53
- data/lib/usps/imis/errors/ambiguous_certificate_error.rb +0 -21
- data/lib/usps/imis/errors/api_error.rb +0 -11
- data/lib/usps/imis/errors/command_line_error.rb +0 -11
- data/lib/usps/imis/errors/config_error.rb +0 -11
- data/lib/usps/imis/errors/embedded_model_find_error.rb +0 -20
- data/lib/usps/imis/errors/empty_payload_error.rb +0 -23
- data/lib/usps/imis/errors/locked_id_error.rb +0 -15
- data/lib/usps/imis/errors/mapper_error.rb +0 -29
- data/lib/usps/imis/errors/missing_id_error.rb +0 -15
- data/lib/usps/imis/errors/missing_party_field_error.rb +0 -24
- data/lib/usps/imis/errors/not_found_error.rb +0 -11
- data/lib/usps/imis/errors/panel_unimplemented_error.rb +0 -34
- data/lib/usps/imis/errors/pattern_matching_error.rb +0 -23
- data/lib/usps/imis/errors/response_error.rb +0 -104
- data/lib/usps/imis/errors/unexpected_property_type_error.rb +0 -31
- data/lib/usps/imis/helpers.rb +0 -23
- data/lib/usps/imis/logger.rb +0 -40
- data/lib/usps/imis/logger_formatter.rb +0 -39
- data/lib/usps/imis/logger_helpers.rb +0 -39
- data/lib/usps/imis/mocks/business_object.rb +0 -47
- data/lib/usps/imis/mocks.rb +0 -11
- data/lib/usps/imis/models/associations/individual_demog.rb +0 -11
- data/lib/usps/imis/models/base/finders.rb +0 -80
- data/lib/usps/imis/models/base/persistence.rb +0 -110
- data/lib/usps/imis/models/base.rb +0 -279
- data/lib/usps/imis/models/education.rb +0 -25
- data/lib/usps/imis/models/generated/abc_cs_contact.rb +0 -91
- data/lib/usps/imis/models/generated/abc_fed990.rb +0 -17
- data/lib/usps/imis/models/generated/abc_ps_volunteer_skills.rb +0 -16
- data/lib/usps/imis/models/generated/access_area.rb +0 -22
- data/lib/usps/imis/models/generated/access_item.rb +0 -18
- data/lib/usps/imis/models/generated/access_main.rb +0 -18
- data/lib/usps/imis/models/generated/action_plan.rb +0 -21
- data/lib/usps/imis/models/generated/activity.rb +0 -57
- data/lib/usps/imis/models/generated/activity_ldao.rb +0 -58
- data/lib/usps/imis/models/generated/activity_ldcdr.rb +0 -57
- data/lib/usps/imis/models/generated/activity_ldxo.rb +0 -57
- data/lib/usps/imis/models/generated/add_family.rb +0 -13
- data/lib/usps/imis/models/generated/advanced_email_twelve_months_delivered_by_date.rb +0 -16
- data/lib/usps/imis/models/generated/advanced_email_twelve_months_totals.rb +0 -16
- data/lib/usps/imis/models/generated/aec_chapter_events.rb +0 -28
- data/lib/usps/imis/models/generated/aec_chapter_link_all_events.rb +0 -18
- data/lib/usps/imis/models/generated/aec_district_administrators.rb +0 -19
- data/lib/usps/imis/models/generated/aec_district_squadron_admins.rb +0 -14
- data/lib/usps/imis/models/generated/aec_district_squadron_events.rb +0 -15
- data/lib/usps/imis/models/generated/aec_si_r_charge_fee_percentages.rb +0 -14
- data/lib/usps/imis/models/generated/aec_si_r_charge_params.rb +0 -16
- data/lib/usps/imis/models/generated/appeal.rb +0 -39
- data/lib/usps/imis/models/generated/appeal_status_ref.rb +0 -15
- data/lib/usps/imis/models/generated/asc_ps_abc_squadron_price.rb +0 -25
- data/lib/usps/imis/models/generated/atom_panel_purpose.rb +0 -15
- data/lib/usps/imis/models/generated/auto_pay_instruction_detail.rb +0 -22
- data/lib/usps/imis/models/generated/auto_pay_invoices.rb +0 -24
- data/lib/usps/imis/models/generated/auto_pay_invoices_dues.rb +0 -29
- data/lib/usps/imis/models/generated/auto_pay_member_instruction_detail.rb +0 -22
- data/lib/usps/imis/models/generated/auto_pay_membership_invoices_base.rb +0 -28
- data/lib/usps/imis/models/generated/bad_address_reason_ref.rb +0 -18
- data/lib/usps/imis/models/generated/batch_line_status_ref.rb +0 -14
- data/lib/usps/imis/models/generated/billing_cycles.rb +0 -50
- data/lib/usps/imis/models/generated/billing_fees.rb +0 -61
- data/lib/usps/imis/models/generated/billing_fees_by_bill_to_party.rb +0 -20
- data/lib/usps/imis/models/generated/billing_issue_notification_by_bill_run.rb +0 -20
- data/lib/usps/imis/models/generated/billing_issue_notification_by_party.rb +0 -30
- data/lib/usps/imis/models/generated/billing_log_by_bill_cycle_data.rb +0 -28
- data/lib/usps/imis/models/generated/billing_log_by_party.rb +0 -29
- data/lib/usps/imis/models/generated/billing_product.rb +0 -30
- data/lib/usps/imis/models/generated/bo_district_dues.rb +0 -26
- data/lib/usps/imis/models/generated/bo_dues_fees.rb +0 -21
- data/lib/usps/imis/models/generated/bo_dues_pricing.rb +0 -18
- data/lib/usps/imis/models/generated/bo_national_dues.rb +0 -84
- data/lib/usps/imis/models/generated/bo_no_natl_dist_dues.rb +0 -135
- data/lib/usps/imis/models/generated/bo_squadron_dues.rb +0 -26
- data/lib/usps/imis/models/generated/bo_total.rb +0 -17
- data/lib/usps/imis/models/generated/campaign.rb +0 -42
- data/lib/usps/imis/models/generated/campaign_status_ref.rb +0 -15
- data/lib/usps/imis/models/generated/campaign_type_ref.rb +0 -15
- data/lib/usps/imis/models/generated/certification_module_status.rb +0 -14
- data/lib/usps/imis/models/generated/change_log_report.rb +0 -25
- data/lib/usps/imis/models/generated/change_property.rb +0 -18
- data/lib/usps/imis/models/generated/chapt_subscriptions.rb +0 -14
- data/lib/usps/imis/models/generated/chapter.rb +0 -15
- data/lib/usps/imis/models/generated/chapter_events.rb +0 -30
- data/lib/usps/imis/models/generated/commerce_product.rb +0 -47
- data/lib/usps/imis/models/generated/commission_rate_type_ref.rb +0 -14
- data/lib/usps/imis/models/generated/committee.rb +0 -16
- data/lib/usps/imis/models/generated/committee_districts_org_id.rb +0 -16
- data/lib/usps/imis/models/generated/committee_i_ds_temp.rb +0 -13
- data/lib/usps/imis/models/generated/committee_squadrons_org_id.rb +0 -16
- data/lib/usps/imis/models/generated/communication_log_summary_for_charts.rb +0 -15
- data/lib/usps/imis/models/generated/communication_message_type_ref.rb +0 -14
- data/lib/usps/imis/models/generated/communication_reason_ref.rb +0 -22
- data/lib/usps/imis/models/generated/community_items.rb +0 -25
- data/lib/usps/imis/models/generated/community_subscriptions.rb +0 -25
- data/lib/usps/imis/models/generated/comparison_ref.rb +0 -14
- data/lib/usps/imis/models/generated/component_registry.rb +0 -28
- data/lib/usps/imis/models/generated/contact.rb +0 -32
- data/lib/usps/imis/models/generated/contact_birthday_info.rb +0 -20
- data/lib/usps/imis/models/generated/contact_communication_reason_preferences.rb +0 -25
- data/lib/usps/imis/models/generated/contact_detail_report.rb +0 -49
- data/lib/usps/imis/models/generated/contact_offering_ref.rb +0 -14
- data/lib/usps/imis/models/generated/contact_profile_image.rb +0 -22
- data/lib/usps/imis/models/generated/contact_report.rb +0 -23
- data/lib/usps/imis/models/generated/contact_salutation.rb +0 -18
- data/lib/usps/imis/models/generated/contact_skill_ref.rb +0 -14
- data/lib/usps/imis/models/generated/contact_social_network.rb +0 -19
- data/lib/usps/imis/models/generated/contact_status_ref.rb +0 -15
- data/lib/usps/imis/models/generated/contact_type_ref.rb +0 -16
- data/lib/usps/imis/models/generated/content_filter.rb +0 -18
- data/lib/usps/imis/models/generated/content_manager_authority_group.rb +0 -14
- data/lib/usps/imis/models/generated/cost_method_ref.rb +0 -15
- data/lib/usps/imis/models/generated/country_ref.rb +0 -27
- data/lib/usps/imis/models/generated/credit_type_ref.rb +0 -14
- data/lib/usps/imis/models/generated/cs_activity.rb +0 -50
- data/lib/usps/imis/models/generated/cs_activity_basic.rb +0 -51
- data/lib/usps/imis/models/generated/cs_activity_forms.rb +0 -38
- data/lib/usps/imis/models/generated/cs_activity_types.rb +0 -16
- data/lib/usps/imis/models/generated/cs_address.rb +0 -40
- data/lib/usps/imis/models/generated/cs_address_formats.rb +0 -15
- data/lib/usps/imis/models/generated/cs_appeal.rb +0 -23
- data/lib/usps/imis/models/generated/cs_calls.rb +0 -20
- data/lib/usps/imis/models/generated/cs_campaign.rb +0 -20
- data/lib/usps/imis/models/generated/cs_committee.rb +0 -23
- data/lib/usps/imis/models/generated/cs_committee_code.rb +0 -20
- data/lib/usps/imis/models/generated/cs_committee_member.rb +0 -38
- data/lib/usps/imis/models/generated/cs_committee_member_group.rb +0 -15
- data/lib/usps/imis/models/generated/cs_committee_position.rb +0 -16
- data/lib/usps/imis/models/generated/cs_contact.rb +0 -91
- data/lib/usps/imis/models/generated/cs_contact_basic.rb +0 -79
- data/lib/usps/imis/models/generated/cs_country_names.rb +0 -19
- data/lib/usps/imis/models/generated/cs_donations.rb +0 -31
- data/lib/usps/imis/models/generated/cs_donations_detail.rb +0 -33
- data/lib/usps/imis/models/generated/cs_donor_data.rb +0 -21
- data/lib/usps/imis/models/generated/cs_dues_history.rb +0 -22
- data/lib/usps/imis/models/generated/cs_event.rb +0 -92
- data/lib/usps/imis/models/generated/cs_event_history.rb +0 -20
- data/lib/usps/imis/models/generated/cs_exchange_rate.rb +0 -14
- data/lib/usps/imis/models/generated/cs_freight_dollar.rb +0 -14
- data/lib/usps/imis/models/generated/cs_function.rb +0 -57
- data/lib/usps/imis/models/generated/cs_function_fees.rb +0 -20
- data/lib/usps/imis/models/generated/cs_gen_tables_union.rb +0 -15
- data/lib/usps/imis/models/generated/cs_general_lookup_tables.rb +0 -17
- data/lib/usps/imis/models/generated/cs_inventory.rb +0 -37
- data/lib/usps/imis/models/generated/cs_invoice.rb +0 -51
- data/lib/usps/imis/models/generated/cs_iso_currency_codes.rb +0 -14
- data/lib/usps/imis/models/generated/cs_member_type.rb +0 -18
- data/lib/usps/imis/models/generated/cs_name_fin.rb +0 -27
- data/lib/usps/imis/models/generated/cs_name_fr.rb +0 -27
- data/lib/usps/imis/models/generated/cs_name_log.rb +0 -17
- data/lib/usps/imis/models/generated/cs_name_note.rb +0 -18
- data/lib/usps/imis/models/generated/cs_name_picture.rb +0 -19
- data/lib/usps/imis/models/generated/cs_name_user.rb +0 -18
- data/lib/usps/imis/models/generated/cs_order_history.rb +0 -22
- data/lib/usps/imis/models/generated/cs_order_lines.rb +0 -54
- data/lib/usps/imis/models/generated/cs_order_type.rb +0 -15
- data/lib/usps/imis/models/generated/cs_orders.rb +0 -85
- data/lib/usps/imis/models/generated/cs_org_control.rb +0 -47
- data/lib/usps/imis/models/generated/cs_product.rb +0 -49
- data/lib/usps/imis/models/generated/cs_product_category.rb +0 -18
- data/lib/usps/imis/models/generated/cs_product_fundraising.rb +0 -22
- data/lib/usps/imis/models/generated/cs_product_location.rb +0 -14
- data/lib/usps/imis/models/generated/cs_product_type.rb +0 -14
- data/lib/usps/imis/models/generated/cs_reg_functions.rb +0 -36
- data/lib/usps/imis/models/generated/cs_registrant_classes.rb +0 -15
- data/lib/usps/imis/models/generated/cs_registration.rb +0 -39
- data/lib/usps/imis/models/generated/cs_relationship.rb +0 -25
- data/lib/usps/imis/models/generated/cs_relationship_types.rb +0 -17
- data/lib/usps/imis/models/generated/cs_salutations.rb +0 -14
- data/lib/usps/imis/models/generated/cs_staff_user.rb +0 -34
- data/lib/usps/imis/models/generated/cs_state_province_codes.rb +0 -15
- data/lib/usps/imis/models/generated/cs_subscriptions.rb +0 -58
- data/lib/usps/imis/models/generated/cs_subscriptions_chapters.rb +0 -15
- data/lib/usps/imis/models/generated/cs_system_params.rb +0 -15
- data/lib/usps/imis/models/generated/cs_terms.rb +0 -17
- data/lib/usps/imis/models/generated/cs_trans_notify.rb +0 -16
- data/lib/usps/imis/models/generated/cs_web_security_group.rb +0 -14
- data/lib/usps/imis/models/generated/cs_web_user.rb +0 -18
- data/lib/usps/imis/models/generated/culture_ref.rb +0 -14
- data/lib/usps/imis/models/generated/customer_experience_status.rb +0 -14
- data/lib/usps/imis/models/generated/data_type.rb +0 -16
- data/lib/usps/imis/models/generated/data_vault_attempt_settlement_status_ref.rb +0 -15
- data/lib/usps/imis/models/generated/data_vault_attempt_status_ref.rb +0 -14
- data/lib/usps/imis/models/generated/data_vault_attempt_summary.rb +0 -39
- data/lib/usps/imis/models/generated/data_vault_batch_summary.rb +0 -21
- data/lib/usps/imis/models/generated/data_vault_log_attempt.rb +0 -25
- data/lib/usps/imis/models/generated/data_vault_status_ref.rb +0 -14
- data/lib/usps/imis/models/generated/data_vault_status_summary.rb +0 -15
- data/lib/usps/imis/models/generated/data_vault_status_summary_detail.rb +0 -19
- data/lib/usps/imis/models/generated/date_dimension.rb +0 -24
- data/lib/usps/imis/models/generated/day_of_the_week_ref.rb +0 -14
- data/lib/usps/imis/models/generated/discountable_item.rb +0 -20
- data/lib/usps/imis/models/generated/discountable_item_class.rb +0 -15
- data/lib/usps/imis/models/generated/distinct_user_defined_multi_select_properties.rb +0 -17
- data/lib/usps/imis/models/generated/districts_and_primary_members.rb +0 -15
- data/lib/usps/imis/models/generated/document_path.rb +0 -14
- data/lib/usps/imis/models/generated/document_storage.rb +0 -23
- data/lib/usps/imis/models/generated/document_system_size_info.rb +0 -36
- data/lib/usps/imis/models/generated/document_system_size_info_by_type.rb +0 -37
- data/lib/usps/imis/models/generated/document_system_status_count_info.rb +0 -14
- data/lib/usps/imis/models/generated/document_system_status_size_info.rb +0 -15
- data/lib/usps/imis/models/generated/document_system_type_count_info.rb +0 -14
- data/lib/usps/imis/models/generated/document_system_type_size_info.rb +0 -15
- data/lib/usps/imis/models/generated/document_type.rb +0 -34
- data/lib/usps/imis/models/generated/document_type_status_path_info.rb +0 -28
- data/lib/usps/imis/models/generated/donation.rb +0 -31
- data/lib/usps/imis/models/generated/donation_performance.rb +0 -19
- data/lib/usps/imis/models/generated/donation_summary.rb +0 -36
- data/lib/usps/imis/models/generated/dynamic_group.rb +0 -18
- data/lib/usps/imis/models/generated/educ_abc.rb +0 -21
- data/lib/usps/imis/models/generated/educ_boc.rb +0 -21
- data/lib/usps/imis/models/generated/educ_crs.rb +0 -21
- data/lib/usps/imis/models/generated/educ_id.rb +0 -21
- data/lib/usps/imis/models/generated/educ_ot.rb +0 -21
- data/lib/usps/imis/models/generated/educ_sem.rb +0 -21
- data/lib/usps/imis/models/generated/education_in_progress.rb +0 -16
- data/lib/usps/imis/models/generated/education_level_ref.rb +0 -15
- data/lib/usps/imis/models/generated/effective_contact_communication_preferences_data.rb +0 -23
- data/lib/usps/imis/models/generated/effective_fundraising_preferences_data.rb +0 -18
- data/lib/usps/imis/models/generated/engagement_category.rb +0 -23
- data/lib/usps/imis/models/generated/engagement_measure.rb +0 -24
- data/lib/usps/imis/models/generated/engagement_score_current_data.rb +0 -21
- data/lib/usps/imis/models/generated/engagement_score_formula.rb +0 -19
- data/lib/usps/imis/models/generated/engagement_score_monthly_data.rb +0 -22
- data/lib/usps/imis/models/generated/engagement_score_result.rb +0 -21
- data/lib/usps/imis/models/generated/engagement_score_yearly_data.rb +0 -21
- data/lib/usps/imis/models/generated/event_category_list.rb +0 -16
- data/lib/usps/imis/models/generated/event_function_resource_data.rb +0 -22
- data/lib/usps/imis/models/generated/event_question.rb +0 -24
- data/lib/usps/imis/models/generated/event_question_response.rb +0 -25
- data/lib/usps/imis/models/generated/event_registrants_report.rb +0 -45
- data/lib/usps/imis/models/generated/execution_mode_ref.rb +0 -15
- data/lib/usps/imis/models/generated/experience_definition_status.rb +0 -14
- data/lib/usps/imis/models/generated/expired_member_update_detail_log.rb +0 -19
- data/lib/usps/imis/models/generated/family_add_contact.rb +0 -91
- data/lib/usps/imis/models/generated/family_member_count.rb +0 -37
- data/lib/usps/imis/models/generated/file_type_ref.rb +0 -16
- data/lib/usps/imis/models/generated/first_notify_contact_per_gift.rb +0 -14
- data/lib/usps/imis/models/generated/first_payment_date_type_ref.rb +0 -15
- data/lib/usps/imis/models/generated/form_definition_field_data.rb +0 -19
- data/lib/usps/imis/models/generated/form_field_response_data.rb +0 -22
- data/lib/usps/imis/models/generated/fundraising_preference_ref.rb +0 -15
- data/lib/usps/imis/models/generated/fundraising_profile_donor_data.rb +0 -18
- data/lib/usps/imis/models/generated/gateway_result_ref.rb +0 -14
- data/lib/usps/imis/models/generated/gateway_transaction_data.rb +0 -35
- data/lib/usps/imis/models/generated/gateway_transaction_ref.rb +0 -15
- data/lib/usps/imis/models/generated/gateway_type_ref.rb +0 -17
- data/lib/usps/imis/models/generated/gift.rb +0 -41
- data/lib/usps/imis/models/generated/gift_adjustment_log_summary.rb +0 -25
- data/lib/usps/imis/models/generated/gift_aid_claim_status_ref.rb +0 -14
- data/lib/usps/imis/models/generated/gift_array.rb +0 -16
- data/lib/usps/imis/models/generated/gift_detail.rb +0 -29
- data/lib/usps/imis/models/generated/gift_history.rb +0 -45
- data/lib/usps/imis/models/generated/gift_history_summary.rb +0 -33
- data/lib/usps/imis/models/generated/gift_history_summary_basic.rb +0 -33
- data/lib/usps/imis/models/generated/gift_summary.rb +0 -16
- data/lib/usps/imis/models/generated/gift_totals_by_date.rb +0 -15
- data/lib/usps/imis/models/generated/gift_transaction.rb +0 -43
- data/lib/usps/imis/models/generated/gifts_received.rb +0 -32
- data/lib/usps/imis/models/generated/gifts_received_for_receipting.rb +0 -44
- data/lib/usps/imis/models/generated/gifts_received_summary.rb +0 -33
- data/lib/usps/imis/models/generated/gifts_with_void_and_replaced_receipts.rb +0 -43
- data/lib/usps/imis/models/generated/gl_batch_transaction_data.rb +0 -30
- data/lib/usps/imis/models/generated/gl_daily_transaction_data.rb +0 -30
- data/lib/usps/imis/models/generated/gl_detail_due_to_due_from_transaction_data.rb +0 -17
- data/lib/usps/imis/models/generated/gl_detail_transaction_data.rb +0 -36
- data/lib/usps/imis/models/generated/gl_detail_transaction_data_full.rb +0 -36
- data/lib/usps/imis/models/generated/gl_due_to_due_from_transaction_data.rb +0 -18
- data/lib/usps/imis/models/generated/gl_entry_type_ref.rb +0 -14
- data/lib/usps/imis/models/generated/gl_export_format_type_ref.rb +0 -14
- data/lib/usps/imis/models/generated/gl_export_log_detail.rb +0 -15
- data/lib/usps/imis/models/generated/gl_export_log_summary.rb +0 -26
- data/lib/usps/imis/models/generated/gl_export_multiple.rb +0 -15
- data/lib/usps/imis/models/generated/gl_export_summary_level_ref.rb +0 -15
- data/lib/usps/imis/models/generated/gl_monthly_due_to_due_from_transaction_data.rb +0 -18
- data/lib/usps/imis/models/generated/gl_monthly_transaction_data.rb +0 -29
- data/lib/usps/imis/models/generated/gl_source_item_type_ref.rb +0 -14
- data/lib/usps/imis/models/generated/gl_transaction_data.rb +0 -41
- data/lib/usps/imis/models/generated/grade.rb +0 -14
- data/lib/usps/imis/models/generated/group_info.rb +0 -28
- data/lib/usps/imis/models/generated/group_member_administrator_type_ref.rb +0 -15
- data/lib/usps/imis/models/generated/group_member_detail.rb +0 -29
- data/lib/usps/imis/models/generated/group_member_status_ref.rb +0 -15
- data/lib/usps/imis/models/generated/group_perspective.rb +0 -16
- data/lib/usps/imis/models/generated/group_price_sheet.rb +0 -17
- data/lib/usps/imis/models/generated/group_role_ref.rb +0 -17
- data/lib/usps/imis/models/generated/group_status_ref.rb +0 -16
- data/lib/usps/imis/models/generated/group_type_member_status.rb +0 -17
- data/lib/usps/imis/models/generated/group_type_ref.rb +0 -33
- data/lib/usps/imis/models/generated/group_type_role.rb +0 -22
- data/lib/usps/imis/models/generated/handling_price_ref.rb +0 -15
- data/lib/usps/imis/models/generated/hierarchy.rb +0 -21
- data/lib/usps/imis/models/generated/hierarchy_root.rb +0 -22
- data/lib/usps/imis/models/generated/i_series_data.rb +0 -15
- data/lib/usps/imis/models/generated/individual_demog.rb +0 -34
- data/lib/usps/imis/models/generated/institute_type_code_ref.rb +0 -16
- data/lib/usps/imis/models/generated/interaction_log.rb +0 -35
- data/lib/usps/imis/models/generated/interaction_log_event.rb +0 -24
- data/lib/usps/imis/models/generated/interaction_log_event_summary.rb +0 -30
- data/lib/usps/imis/models/generated/interval_type_ref.rb +0 -15
- data/lib/usps/imis/models/generated/invoice_line_data.rb +0 -39
- data/lib/usps/imis/models/generated/invoice_lines.rb +0 -42
- data/lib/usps/imis/models/generated/invoice_number.rb +0 -16
- data/lib/usps/imis/models/generated/invoice_payment_summary.rb +0 -14
- data/lib/usps/imis/models/generated/invoice_purpose.rb +0 -15
- data/lib/usps/imis/models/generated/invoice_source_system_ref.rb +0 -13
- data/lib/usps/imis/models/generated/invoice_type_ref.rb +0 -14
- data/lib/usps/imis/models/generated/journal_entry_type_ref.rb +0 -14
- data/lib/usps/imis/models/generated/license_ref.rb +0 -15
- data/lib/usps/imis/models/generated/line_pricing_ref.rb +0 -15
- data/lib/usps/imis/models/generated/list_entity.rb +0 -14
- data/lib/usps/imis/models/generated/locale_ref.rb +0 -14
- data/lib/usps/imis/models/generated/location_status.rb +0 -14
- data/lib/usps/imis/models/generated/mail_code_ref.rb +0 -16
- data/lib/usps/imis/models/generated/matching_gift_plan_type_ref.rb +0 -15
- data/lib/usps/imis/models/generated/matching_mode_ref.rb +0 -15
- data/lib/usps/imis/models/generated/matching_period_ref.rb +0 -15
- data/lib/usps/imis/models/generated/memorial_tribute_type_ref.rb +0 -14
- data/lib/usps/imis/models/generated/method_set_type_ref.rb +0 -14
- data/lib/usps/imis/models/generated/month_ref.rb +0 -18
- data/lib/usps/imis/models/generated/name_prefixes.rb +0 -15
- data/lib/usps/imis/models/generated/name_suffixes.rb +0 -13
- data/lib/usps/imis/models/generated/navigation_pane.rb +0 -18
- data/lib/usps/imis/models/generated/net_contact.rb +0 -99
- data/lib/usps/imis/models/generated/net_contact_basic.rb +0 -88
- data/lib/usps/imis/models/generated/net_contact_data.rb +0 -88
- data/lib/usps/imis/models/generated/note_purpose_ref.rb +0 -14
- data/lib/usps/imis/models/generated/offering_status.rb +0 -14
- data/lib/usps/imis/models/generated/opportunity_class_ref.rb +0 -15
- data/lib/usps/imis/models/generated/opportunity_default_status_ref.rb +0 -15
- data/lib/usps/imis/models/generated/opportunity_status_ref.rb +0 -15
- data/lib/usps/imis/models/generated/opportunity_task_user.rb +0 -20
- data/lib/usps/imis/models/generated/opportunity_type.rb +0 -29
- data/lib/usps/imis/models/generated/order_category.rb +0 -14
- data/lib/usps/imis/models/generated/order_fulfillment_status_ref.rb +0 -14
- data/lib/usps/imis/models/generated/order_invoice.rb +0 -14
- data/lib/usps/imis/models/generated/order_state_ref.rb +0 -14
- data/lib/usps/imis/models/generated/order_type_detail.rb +0 -17
- data/lib/usps/imis/models/generated/org_demog.rb +0 -28
- data/lib/usps/imis/models/generated/organization_demo.rb +0 -18
- data/lib/usps/imis/models/generated/organization_hierarchy.rb +0 -19
- data/lib/usps/imis/models/generated/package.rb +0 -25
- data/lib/usps/imis/models/generated/package_item.rb +0 -19
- data/lib/usps/imis/models/generated/package_status_ref.rb +0 -14
- data/lib/usps/imis/models/generated/payment_application.rb +0 -31
- data/lib/usps/imis/models/generated/payment_application_detail.rb +0 -35
- data/lib/usps/imis/models/generated/payment_application_restriction_ref.rb +0 -14
- data/lib/usps/imis/models/generated/payment_application_summary.rb +0 -18
- data/lib/usps/imis/models/generated/payment_application_type.rb +0 -14
- data/lib/usps/imis/models/generated/payment_category_ref.rb +0 -14
- data/lib/usps/imis/models/generated/payment_detail_status_ref.rb +0 -15
- data/lib/usps/imis/models/generated/payment_method_data.rb +0 -20
- data/lib/usps/imis/models/generated/payment_reconciliation.rb +0 -26
- data/lib/usps/imis/models/generated/payment_status_ref.rb +0 -14
- data/lib/usps/imis/models/generated/percentile_ranking.rb +0 -20
- data/lib/usps/imis/models/generated/picture_purpose_ref.rb +0 -14
- data/lib/usps/imis/models/generated/pin_update.rb +0 -13
- data/lib/usps/imis/models/generated/pipeline.rb +0 -15
- data/lib/usps/imis/models/generated/pipeline_stage.rb +0 -17
- data/lib/usps/imis/models/generated/postal_code_ref.rb +0 -26
- data/lib/usps/imis/models/generated/prefix_ref.rb +0 -17
- data/lib/usps/imis/models/generated/price_basis_ref.rb +0 -15
- data/lib/usps/imis/models/generated/pricing_type_ref.rb +0 -15
- data/lib/usps/imis/models/generated/primary_fam_members.rb +0 -14
- data/lib/usps/imis/models/generated/process_type_default_owner_all_users.rb +0 -15
- data/lib/usps/imis/models/generated/product_price_sheet.rb +0 -20
- data/lib/usps/imis/models/generated/product_status_ref.rb +0 -15
- data/lib/usps/imis/models/generated/product_trans.rb +0 -31
- data/lib/usps/imis/models/generated/product_trans_detail.rb +0 -17
- data/lib/usps/imis/models/generated/profile_documents.rb +0 -15
- data/lib/usps/imis/models/generated/profile_page.rb +0 -36
- data/lib/usps/imis/models/generated/program_group_status.rb +0 -14
- data/lib/usps/imis/models/generated/program_status.rb +0 -14
- data/lib/usps/imis/models/generated/promotion_rule_ref.rb +0 -15
- data/lib/usps/imis/models/generated/property_definition.rb +0 -33
- data/lib/usps/imis/models/generated/prospect.rb +0 -38
- data/lib/usps/imis/models/generated/publish_priority.rb +0 -14
- data/lib/usps/imis/models/generated/publish_request.rb +0 -18
- data/lib/usps/imis/models/generated/publish_request_detail.rb +0 -22
- data/lib/usps/imis/models/generated/publish_request_status.rb +0 -15
- data/lib/usps/imis/models/generated/publish_server.rb +0 -29
- data/lib/usps/imis/models/generated/quality_ref.rb +0 -15
- data/lib/usps/imis/models/generated/rank.rb +0 -21
- data/lib/usps/imis/models/generated/receipt_report.rb +0 -24
- data/lib/usps/imis/models/generated/receipt_status_ref.rb +0 -15
- data/lib/usps/imis/models/generated/recurring_donation_expected_payment_set.rb +0 -19
- data/lib/usps/imis/models/generated/recurring_donation_expected_payment_set_list.rb +0 -20
- data/lib/usps/imis/models/generated/recurring_donation_expected_payment_set_status.rb +0 -15
- data/lib/usps/imis/models/generated/recurring_donation_expected_payment_status.rb +0 -15
- data/lib/usps/imis/models/generated/recurring_donation_frequency_ref.rb +0 -15
- data/lib/usps/imis/models/generated/reference_date.rb +0 -13
- data/lib/usps/imis/models/generated/registered_component.rb +0 -27
- data/lib/usps/imis/models/generated/registration_status.rb +0 -14
- data/lib/usps/imis/models/generated/relationship.rb +0 -18
- data/lib/usps/imis/models/generated/relationship_category.rb +0 -17
- data/lib/usps/imis/models/generated/relationship_type_category.rb +0 -17
- data/lib/usps/imis/models/generated/relationship_type_ref.rb +0 -16
- data/lib/usps/imis/models/generated/relationship_update.rb +0 -16
- data/lib/usps/imis/models/generated/relationship_update_contact_panel.rb +0 -16
- data/lib/usps/imis/models/generated/remove_district_org_committee_terms.rb +0 -28
- data/lib/usps/imis/models/generated/remove_squadron_org_committee_terms.rb +0 -28
- data/lib/usps/imis/models/generated/reporting_group_user.rb +0 -14
- data/lib/usps/imis/models/generated/response_media_ref.rb +0 -14
- data/lib/usps/imis/models/generated/response_type_ref.rb +0 -15
- data/lib/usps/imis/models/generated/restock_price_ref.rb +0 -15
- data/lib/usps/imis/models/generated/sales_location_status_ref.rb +0 -15
- data/lib/usps/imis/models/generated/salutation_ref.rb +0 -22
- data/lib/usps/imis/models/generated/sbuddy_answers.rb +0 -23
- data/lib/usps/imis/models/generated/sbuddy_definition.rb +0 -28
- data/lib/usps/imis/models/generated/schedule_frequency_ref.rb +0 -14
- data/lib/usps/imis/models/generated/segmentation_job_status_ref.rb +0 -15
- data/lib/usps/imis/models/generated/sequence_counter.rb +0 -16
- data/lib/usps/imis/models/generated/set_district_org_committee_terms.rb +0 -28
- data/lib/usps/imis/models/generated/set_squadron_org_committee_terms.rb +0 -28
- data/lib/usps/imis/models/generated/ship_price_ref.rb +0 -15
- data/lib/usps/imis/models/generated/soa_group.rb +0 -21
- data/lib/usps/imis/models/generated/soa_group_member.rb +0 -19
- data/lib/usps/imis/models/generated/soa_group_member_detail.rb +0 -28
- data/lib/usps/imis/models/generated/social_network_ref.rb +0 -15
- data/lib/usps/imis/models/generated/solicitation.rb +0 -40
- data/lib/usps/imis/models/generated/solicitation_status_ref.rb +0 -15
- data/lib/usps/imis/models/generated/source_code.rb +0 -43
- data/lib/usps/imis/models/generated/source_code_status_ref.rb +0 -15
- data/lib/usps/imis/models/generated/source_code_type_ref.rb +0 -15
- data/lib/usps/imis/models/generated/squad_form_add_fam.rb +0 -23
- data/lib/usps/imis/models/generated/squad_form_add_individual.rb +0 -31
- data/lib/usps/imis/models/generated/squad_leader_add_individual_contact.rb +0 -28
- data/lib/usps/imis/models/generated/squad_note.rb +0 -13
- data/lib/usps/imis/models/generated/squad_to_district.rb +0 -18
- data/lib/usps/imis/models/generated/squadron_chap_com.rb +0 -16
- data/lib/usps/imis/models/generated/squadron_district_lookup.rb +0 -18
- data/lib/usps/imis/models/generated/squadrons_and_primary_members.rb +0 -15
- data/lib/usps/imis/models/generated/standard_page.rb +0 -15
- data/lib/usps/imis/models/generated/state_province_ref.rb +0 -21
- data/lib/usps/imis/models/generated/suffix_ref.rb +0 -16
- data/lib/usps/imis/models/generated/supplement.rb +0 -27
- data/lib/usps/imis/models/generated/supplement_status_ref.rb +0 -15
- data/lib/usps/imis/models/generated/supplement_type_ref.rb +0 -15
- data/lib/usps/imis/models/generated/system_config_xml.rb +0 -14
- data/lib/usps/imis/models/generated/system_param_int.rb +0 -23
- data/lib/usps/imis/models/generated/tag_hierarchy.rb +0 -32
- data/lib/usps/imis/models/generated/tag_relationship_type.rb +0 -16
- data/lib/usps/imis/models/generated/task_item.rb +0 -32
- data/lib/usps/imis/models/generated/task_item_status_ref.rb +0 -15
- data/lib/usps/imis/models/generated/task_latest_log.rb +0 -15
- data/lib/usps/imis/models/generated/task_notify_creator_ref.rb +0 -15
- data/lib/usps/imis/models/generated/task_priority.rb +0 -15
- data/lib/usps/imis/models/generated/task_status.rb +0 -16
- data/lib/usps/imis/models/generated/task_type.rb +0 -15
- data/lib/usps/imis/models/generated/tax_authority_level_ref.rb +0 -15
- data/lib/usps/imis/models/generated/time_zone_ref.rb +0 -20
- data/lib/usps/imis/models/generated/top_level_parent_organization.rb +0 -20
- data/lib/usps/imis/models/generated/transaction_detail.rb +0 -56
- data/lib/usps/imis/models/generated/transaction_summary_large_batch.rb +0 -44
- data/lib/usps/imis/models/generated/uniform_registry.rb +0 -14
- data/lib/usps/imis/models/generated/uniform_tag.rb +0 -17
- data/lib/usps/imis/models/generated/upgrade_log_detail.rb +0 -19
- data/lib/usps/imis/models/generated/url_mapping_type_ref.rb +0 -15
- data/lib/usps/imis/models/generated/user_data.rb +0 -33
- data/lib/usps/imis/models/generated/user_role.rb +0 -14
- data/lib/usps/imis/models/generated/user_token.rb +0 -14
- data/lib/usps/imis/models/generated/vertical_alignment_ref.rb +0 -15
- data/lib/usps/imis/models/generated/vessels.rb +0 -18
- data/lib/usps/imis/models/generated/volunteer_information.rb +0 -22
- data/lib/usps/imis/models/generated/warehouse_status_ref.rb +0 -14
- data/lib/usps/imis/models/generated/warehouse_type_ref.rb +0 -14
- data/lib/usps/imis/models/generated/web_user_control_ref.rb +0 -15
- data/lib/usps/imis/models/generated/workflow_queue_item.rb +0 -25
- data/lib/usps/imis/models/generated/workflow_queue_item_with_status.rb +0 -25
- data/lib/usps/imis/models/generated/workflow_queue_status_ref.rb +0 -15
- data/lib/usps/imis/models/generated/workflow_status_ref.rb +0 -15
- data/lib/usps/imis/models/party/address.rb +0 -32
- data/lib/usps/imis/models/party/alternate_id.rb +0 -16
- data/lib/usps/imis/models/party/email.rb +0 -17
- data/lib/usps/imis/models/party/phone.rb +0 -17
- data/lib/usps/imis/models/party/salutation.rb +0 -18
- data/lib/usps/imis/models/party.rb +0 -131
- data/lib/usps/imis/models/types/upcase_string.rb +0 -18
- data/lib/usps/imis/models/vessel_safety_checks.rb +0 -20
- data/lib/usps/imis/models.rb +0 -92
- data/lib/usps/imis/panels/base_panel.rb +0 -136
- data/lib/usps/imis/panels/education.rb +0 -29
- data/lib/usps/imis/panels/vsc.rb +0 -28
- data/lib/usps/imis/panels.rb +0 -25
- data/lib/usps/imis/party_data.rb +0 -76
- data/lib/usps/imis/properties.rb +0 -74
- data/lib/usps/imis/query.rb +0 -163
- data/lib/usps/imis/requests.rb +0 -67
- data/spec/support/usps/simple_cov_uncovered_lines_formatter.rb +0 -53
- data/spec/support/usps/vcr/config.rb +0 -47
- data/spec/support/usps/vcr/filters.rb +0 -89
- data/spec/support/usps/vcr.rb +0 -8
data/lib/usps/imis/api.rb
CHANGED
|
@@ -1,317 +1,207 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative 'business_object'
|
|
4
|
-
require_relative 'mapper'
|
|
5
|
-
require_relative 'query'
|
|
6
|
-
|
|
7
3
|
module Usps
|
|
8
4
|
module Imis
|
|
9
|
-
# The core API wrapper
|
|
10
|
-
#
|
|
11
5
|
class Api
|
|
12
|
-
include Requests
|
|
13
|
-
include Imis::Helpers
|
|
14
|
-
|
|
15
|
-
NAME = 'USPS iMIS API - Ruby'
|
|
16
|
-
|
|
17
|
-
# Endpoint for (re-)authentication requests
|
|
18
|
-
#
|
|
19
6
|
AUTHENTICATION_PATH = 'Token'
|
|
7
|
+
API_PATH = 'api'
|
|
8
|
+
QUERY_PATH = 'api/Query'
|
|
9
|
+
PANELS = Struct.new(:vsc, :education)
|
|
20
10
|
|
|
21
|
-
|
|
22
|
-
#
|
|
23
|
-
attr_reader :token
|
|
24
|
-
|
|
25
|
-
# Expiration time for the API bearer token
|
|
26
|
-
#
|
|
27
|
-
# Used to automatically re-authenticate as needed
|
|
28
|
-
#
|
|
29
|
-
attr_reader :token_expiration
|
|
30
|
-
|
|
31
|
-
# Currently selected iMIS ID for API requests
|
|
32
|
-
#
|
|
33
|
-
attr_reader :imis_id
|
|
34
|
-
|
|
35
|
-
# Whether to lock changes to the selected iMIS ID
|
|
36
|
-
#
|
|
37
|
-
attr_reader :lock_imis_id
|
|
38
|
-
|
|
39
|
-
# Tagged logger
|
|
40
|
-
#
|
|
41
|
-
attr_reader :logger
|
|
42
|
-
|
|
43
|
-
# Name and version of the API
|
|
44
|
-
#
|
|
45
|
-
def self.version = "#{NAME} (v#{Imis::VERSION})"
|
|
46
|
-
|
|
47
|
-
# Create a new instance of +Api+ and provide an existing auth token
|
|
48
|
-
#
|
|
49
|
-
# @param token [String] Auth token
|
|
50
|
-
#
|
|
51
|
-
def self.with_token(token)
|
|
52
|
-
new.tap do |api|
|
|
53
|
-
api.instance_variable_set(:@token, token)
|
|
54
|
-
api.instance_variable_set(:@token_expiration, Time.now + 3600) # Greater than the actual lifetime of the token
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
# A new instance of +Api+
|
|
59
|
-
#
|
|
60
|
-
# @param imis_id [Integer, String] iMIS ID to select immediately on initialization
|
|
61
|
-
# @param record_id [Integer, String] iMIS ID to select immediately on initialization
|
|
62
|
-
# @param certificate [String] Certificate to convert to iMIS ID immediately on initialization
|
|
63
|
-
#
|
|
64
|
-
def initialize(imis_id: nil, record_id: nil, certificate: nil)
|
|
65
|
-
raise ArgumentError, 'Cannot provide both imis_id and certificate' if imis_id && certificate
|
|
66
|
-
|
|
67
|
-
@logger = Imis.logger('Api')
|
|
68
|
-
Imis.config.validate!
|
|
11
|
+
attr_reader :token, :token_expiration, :imis_id
|
|
69
12
|
|
|
13
|
+
def initialize(skip_authentication: false, imis_id: nil)
|
|
14
|
+
authenticate unless skip_authentication
|
|
70
15
|
self.imis_id = imis_id if imis_id
|
|
71
|
-
self.record_id = record_id if record_id
|
|
72
|
-
imis_id_for(certificate) if certificate
|
|
73
16
|
end
|
|
74
17
|
|
|
75
18
|
# Manually set the current ID, if you already have it for a given member
|
|
76
19
|
#
|
|
77
|
-
# Supports integer ID and UUID string
|
|
78
|
-
#
|
|
79
|
-
# @param id [Integer, String] iMIS ID to select for future requests
|
|
80
|
-
#
|
|
81
|
-
# @return [Integer, String] iMIS ID
|
|
82
|
-
#
|
|
83
20
|
def imis_id=(id)
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
@imis_id = format_id(id)
|
|
21
|
+
@imis_id = id.to_i.to_s
|
|
87
22
|
end
|
|
88
23
|
|
|
89
|
-
# Manually set the current record ID
|
|
90
|
-
#
|
|
91
|
-
# @param id [Integer, String] Record ID to select for future requests
|
|
92
|
-
#
|
|
93
|
-
# @return [Integer] Record ID
|
|
94
|
-
#
|
|
95
|
-
def record_id=(id)
|
|
96
|
-
return if id.nil?
|
|
97
|
-
|
|
98
|
-
raise Errors::LockedIdError if lock_imis_id
|
|
99
|
-
|
|
100
|
-
@record_id = format_id(id)
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
# Currently selected Record ID for API requests
|
|
104
|
-
#
|
|
105
|
-
# Defaults to the iMIS ID
|
|
106
|
-
#
|
|
107
|
-
def record_id = @record_id || imis_id
|
|
108
|
-
|
|
109
24
|
# Convert a member's certificate number into an iMIS ID number
|
|
110
25
|
#
|
|
111
|
-
# @param certificate [String] Certificate number to lookup the corresponding iMIS ID for
|
|
112
|
-
#
|
|
113
|
-
# @return [Integer] Corresponding iMIS ID
|
|
114
|
-
#
|
|
115
|
-
# @raise [Errors::AmbiguousCertificateError] If the certificate matches more than one person
|
|
116
|
-
#
|
|
117
26
|
def imis_id_for(certificate)
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
# Family records can share their member's MajorKey, so only people are candidates
|
|
123
|
-
people = query('NetContactData', MajorKey: certificate).page.reject { it['IsCompany'] }
|
|
124
|
-
raise Errors::NotFoundError, 'Member not found' if people.empty?
|
|
125
|
-
raise Errors::AmbiguousCertificateError, certificate if people.many?
|
|
126
|
-
|
|
127
|
-
party = query('Party', UniformId: people.first.id).one
|
|
128
|
-
raise Errors::NotFoundError, 'Member not found' if party.nil?
|
|
129
|
-
|
|
130
|
-
self.imis_id = party.imis_id
|
|
131
|
-
rescue Errors::ResponseError
|
|
132
|
-
raise Errors::NotFoundError, 'Member not found'
|
|
27
|
+
result = query(Imis.configuration.imis_id_query_name, { certificate: })
|
|
28
|
+
@imis_id = result['Items']['$values'][0]['ID']
|
|
29
|
+
rescue StandardError
|
|
30
|
+
raise Error::Api, 'Member not found'
|
|
133
31
|
end
|
|
134
32
|
|
|
135
33
|
# Run requests as DSL, with specific iMIS ID only maintained for this scope
|
|
136
34
|
#
|
|
137
|
-
#
|
|
138
|
-
#
|
|
139
|
-
# While in this block, changes to the value of +imis_id+ are not allowed
|
|
35
|
+
# This should be used with methods that do not change the value of `imis_id`
|
|
140
36
|
#
|
|
141
|
-
|
|
142
|
-
#
|
|
143
|
-
# @param id [Integer, String] iMIS ID to select for requests within the block
|
|
144
|
-
# @param certificate [String] Certificate number to convert to iMIS ID and select for requests within the block
|
|
145
|
-
# @param record_id [Integer] Record ID to select for requests within the block
|
|
146
|
-
# @yield Block context to run requests with a specific iMIS ID
|
|
147
|
-
# @yieldparam [Api]
|
|
148
|
-
#
|
|
149
|
-
# @example
|
|
150
|
-
# with(12345) do
|
|
151
|
-
# update(mm: 15)
|
|
152
|
-
# end
|
|
153
|
-
#
|
|
154
|
-
# @return [Usps::Imis::Api]
|
|
155
|
-
#
|
|
156
|
-
def with(id = nil, certificate: nil, record_id: nil, &)
|
|
157
|
-
raise ArgumentError, 'Must provide id or certificate' unless id || certificate
|
|
158
|
-
|
|
37
|
+
def with(id, &)
|
|
159
38
|
old_id = imis_id
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
id.nil? ? imis_id_for(certificate) : self.imis_id = id
|
|
163
|
-
self.record_id = record_id
|
|
164
|
-
return self unless block_given?
|
|
165
|
-
|
|
166
|
-
@lock_imis_id = true
|
|
39
|
+
self.imis_id = id
|
|
167
40
|
instance_eval(&)
|
|
168
41
|
ensure
|
|
169
|
-
|
|
170
|
-
@lock_imis_id = false
|
|
171
|
-
self.imis_id = old_id
|
|
172
|
-
self.record_id = old_record_id
|
|
173
|
-
end
|
|
42
|
+
self.imis_id = old_id
|
|
174
43
|
end
|
|
175
44
|
|
|
176
|
-
#
|
|
177
|
-
#
|
|
178
|
-
# Works with IQA queries and Business Objects
|
|
179
|
-
#
|
|
180
|
-
# @param query_name [String] Full path of the query, e.g. +$/_ABC/Fiander/iMIS_ID+
|
|
181
|
-
# @query_params [Hash] Conforms to pattern +{ param_name => param_value }+
|
|
45
|
+
# Get a business object for the current member
|
|
182
46
|
#
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
47
|
+
def get(business_object_name, url_id: nil)
|
|
48
|
+
uri = uri_for(business_object_name, url_id:)
|
|
49
|
+
request = Net::HTTP::Get.new(uri)
|
|
50
|
+
result = submit(uri, authorize(request))
|
|
51
|
+
JSON.parse(result.body)
|
|
52
|
+
end
|
|
186
53
|
|
|
187
|
-
#
|
|
188
|
-
#
|
|
189
|
-
# If no block is given, this returns the specified +BusinessObject+.
|
|
54
|
+
# Update only specific fields on a business object for the current member
|
|
190
55
|
#
|
|
191
|
-
#
|
|
192
|
-
# @param ordinal [Integer] Ordinal to build override ID param of the URL (e.g. used for Panels)
|
|
193
|
-
# @yield Block context to run requests on a specific +BusinessObject+
|
|
194
|
-
# @yieldparam [Api]
|
|
56
|
+
# fields - hash of shape: { field_name => new_value }
|
|
195
57
|
#
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
object = BusinessObject.new(self, business_object_name, ordinal:)
|
|
200
|
-
return object unless block_given?
|
|
201
|
-
|
|
202
|
-
object.instance_eval(&)
|
|
58
|
+
def put_fields(business_object_name, fields, url_id: nil)
|
|
59
|
+
updated = filter_fields(business_object_name, fields)
|
|
60
|
+
put(business_object_name, updated, url_id:)
|
|
203
61
|
end
|
|
204
62
|
|
|
205
|
-
#
|
|
63
|
+
# Update a business object for the current member
|
|
206
64
|
#
|
|
207
|
-
def
|
|
208
|
-
|
|
65
|
+
def put(business_object_name, body, url_id: nil)
|
|
66
|
+
uri = uri_for(business_object_name, url_id:)
|
|
67
|
+
request = Net::HTTP::Put.new(uri)
|
|
68
|
+
request.body = JSON.dump(body)
|
|
69
|
+
result = submit(uri, authorize(request))
|
|
70
|
+
JSON.parse(result.body)
|
|
209
71
|
end
|
|
210
72
|
|
|
211
|
-
#
|
|
212
|
-
#
|
|
213
|
-
# @return Value of the specified field
|
|
214
|
-
#
|
|
215
|
-
delegate :fetch, to: :mapper
|
|
216
|
-
alias [] fetch
|
|
217
|
-
|
|
218
|
-
# Convenience alias for reading multiple mapped fields
|
|
219
|
-
#
|
|
220
|
-
# @return [Array] Values of the specified fields
|
|
221
|
-
#
|
|
222
|
-
delegate :fetch_all, to: :mapper
|
|
223
|
-
|
|
224
|
-
# Convenience alias for updating mapped fields
|
|
73
|
+
# Create a business object for the current member
|
|
225
74
|
#
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
75
|
+
def post(business_object_name, body, url_id: nil)
|
|
76
|
+
uri = uri_for(business_object_name, url_id:)
|
|
77
|
+
request = Net::HTTP::Post.new(uri)
|
|
78
|
+
request.body = JSON.dump(body)
|
|
79
|
+
result = submit(uri, authorize(request))
|
|
80
|
+
JSON.parse(result.body)
|
|
81
|
+
end
|
|
230
82
|
|
|
231
|
-
#
|
|
83
|
+
# Remove a business object for the current member
|
|
232
84
|
#
|
|
233
|
-
#
|
|
85
|
+
# Returns empty string on success
|
|
234
86
|
#
|
|
235
|
-
|
|
87
|
+
def delete(business_object_name, url_id: nil)
|
|
88
|
+
uri = uri_for(business_object_name, url_id:)
|
|
89
|
+
request = Net::HTTP::Delete.new(uri)
|
|
90
|
+
result = submit(uri, authorize(request))
|
|
91
|
+
result.body
|
|
92
|
+
end
|
|
236
93
|
|
|
237
|
-
#
|
|
238
|
-
# wrapper, partitioned by whether the name carries an +ABC+ prefix.
|
|
239
|
-
# Sourced from the in-process registry — no HTTP — so this answers
|
|
240
|
-
# "what does the gem know how to wrap?", not "what does the server
|
|
241
|
-
# expose?". Anything not listed still round-trips as raw +Data+.
|
|
94
|
+
# Run an IQA Query
|
|
242
95
|
#
|
|
243
|
-
#
|
|
96
|
+
# query_name - the full path of the query in IQA, e.g. `$/_ABC/Fiander/iMIS_ID`
|
|
97
|
+
# query_params - hash of shape: { param_name => param_value }
|
|
244
98
|
#
|
|
245
|
-
def
|
|
246
|
-
|
|
99
|
+
def query(query_name, query_params = {})
|
|
100
|
+
query_params[:QueryName] = query_name
|
|
101
|
+
path = "#{QUERY_PATH}?#{query_params.to_query}"
|
|
102
|
+
uri = URI(File.join(imis_hostname, path))
|
|
103
|
+
request = Net::HTTP::Get.new(uri)
|
|
104
|
+
result = submit(uri, authorize(request))
|
|
105
|
+
JSON.parse(result.body)
|
|
106
|
+
end
|
|
247
107
|
|
|
248
|
-
|
|
108
|
+
def mapper
|
|
109
|
+
@mapper ||= Mapper.new(self)
|
|
249
110
|
end
|
|
250
111
|
|
|
251
|
-
# Convenience accessor for available Panel objects, each using this instance as its parent
|
|
252
|
-
# +Api+
|
|
253
|
-
#
|
|
254
112
|
def panels
|
|
255
|
-
@panels ||=
|
|
113
|
+
@panels ||= PANELS.new(
|
|
114
|
+
Panel::Vsc.new(self),
|
|
115
|
+
Panel::Education.new(self)
|
|
116
|
+
)
|
|
256
117
|
end
|
|
257
118
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
def auth_token
|
|
261
|
-
authenticate
|
|
262
|
-
|
|
263
|
-
{ token: @token, token_expiration: @token_expiration }
|
|
119
|
+
def update(data)
|
|
120
|
+
mapper.update(data)
|
|
264
121
|
end
|
|
265
122
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
return @http_connection if @http_connection&.started?
|
|
123
|
+
def instance_variables_to_inspect = %i[@token_expiration @imis_id]
|
|
124
|
+
|
|
125
|
+
private
|
|
270
126
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
@http_connection = Net::HTTP.new(hostname.host, hostname.port).tap do |http|
|
|
127
|
+
def client(uri)
|
|
128
|
+
Net::HTTP.new(uri.host, uri.port).tap do |http|
|
|
274
129
|
http.use_ssl = true
|
|
275
130
|
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
|
276
|
-
http.open_timeout = config.open_timeout
|
|
277
|
-
http.read_timeout = config.read_timeout
|
|
278
|
-
http.write_timeout = config.write_timeout
|
|
279
|
-
http.keep_alive_timeout = 30
|
|
280
|
-
http.start
|
|
281
131
|
end
|
|
282
132
|
end
|
|
283
133
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
134
|
+
def imis_hostname
|
|
135
|
+
Imis.configuration.hostname
|
|
136
|
+
end
|
|
287
137
|
|
|
288
|
-
#
|
|
138
|
+
# Authorize a request prior to submitting
|
|
289
139
|
#
|
|
290
|
-
|
|
291
|
-
|
|
140
|
+
# If the current token is missing/expired, request a new one
|
|
141
|
+
#
|
|
142
|
+
def authorize(request)
|
|
143
|
+
authenticate if token_expiration < Time.now
|
|
144
|
+
request.tap { |r| r.add_field('Authorization', "Bearer #{token}") }
|
|
145
|
+
end
|
|
292
146
|
|
|
293
|
-
|
|
294
|
-
|
|
147
|
+
# Construct a business object API endpoint address
|
|
148
|
+
#
|
|
149
|
+
def uri_for(business_object_name, url_id: nil)
|
|
150
|
+
url_id ||= imis_id
|
|
151
|
+
url_id = CGI.escape(url_id)
|
|
152
|
+
URI(File.join(imis_hostname, "#{API_PATH}/#{business_object_name}/#{url_id}"))
|
|
153
|
+
end
|
|
295
154
|
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
username: Imis.configuration.username,
|
|
300
|
-
password: Imis.configuration.password
|
|
301
|
-
)
|
|
302
|
-
result = submit(request)
|
|
303
|
-
json = JSON.parse(result.body)
|
|
155
|
+
def submit(uri, request)
|
|
156
|
+
client(uri).request(request).tap do |result|
|
|
157
|
+
raise Error::Response.from(result) unless result.is_a?(Net::HTTPSuccess)
|
|
304
158
|
end
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
# Authenticate to the iMIS API, and store the access token and expiration time
|
|
162
|
+
#
|
|
163
|
+
def authenticate
|
|
164
|
+
uri = URI(File.join(imis_hostname, AUTHENTICATION_PATH))
|
|
165
|
+
req = Net::HTTP::Post.new(uri)
|
|
166
|
+
authentication_data = {
|
|
167
|
+
grant_type: 'password',
|
|
168
|
+
username: Imis.configuration.username,
|
|
169
|
+
password: Imis.configuration.password
|
|
170
|
+
}
|
|
171
|
+
req.body = URI.encode_www_form(authentication_data)
|
|
172
|
+
result = submit(uri, req)
|
|
173
|
+
json = JSON.parse(result.body)
|
|
305
174
|
|
|
306
175
|
@token = json['access_token']
|
|
307
|
-
@token_expiration = Time.
|
|
176
|
+
@token_expiration = Time.parse(json['.expires'])
|
|
308
177
|
end
|
|
309
178
|
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
# URI for the authentication endpoint
|
|
179
|
+
# Manually assemble the matching data structure, with fields in the correct order
|
|
313
180
|
#
|
|
314
|
-
def
|
|
181
|
+
def filter_fields(business_object_name, fields)
|
|
182
|
+
existing = get(business_object_name)
|
|
183
|
+
|
|
184
|
+
JSON.parse(JSON.dump(existing)).tap do |updated|
|
|
185
|
+
# The first property is always the iMIS ID again
|
|
186
|
+
updated['Properties']['$values'] = [existing['Properties']['$values'][0]]
|
|
187
|
+
|
|
188
|
+
# Iterate through all existing fields
|
|
189
|
+
existing['Properties']['$values'].each do |value|
|
|
190
|
+
next unless fields.keys.include?(value['Name'])
|
|
191
|
+
|
|
192
|
+
# Strings are not wrapped in the type definition structure
|
|
193
|
+
new_value = fields[value['Name']]
|
|
194
|
+
if new_value.is_a?(String)
|
|
195
|
+
value['Value'] = new_value
|
|
196
|
+
else
|
|
197
|
+
value['Value']['$value'] = new_value
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
# Add the completed field with the updated value
|
|
201
|
+
updated['Properties']['$values'] << value
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
end
|
|
315
205
|
end
|
|
316
206
|
end
|
|
317
207
|
end
|
data/lib/usps/imis/config.rb
CHANGED
|
@@ -1,175 +1,29 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative 'logger'
|
|
4
|
-
|
|
5
3
|
module Usps
|
|
6
4
|
module Imis
|
|
7
|
-
# API Configuration
|
|
8
|
-
#
|
|
9
5
|
class Config
|
|
10
6
|
IMIS_ROOT_URL_PROD = 'https://portal.americasboatingclub.org'
|
|
11
7
|
IMIS_ROOT_URL_DEV = 'https://abcdev.imiscloud.com'
|
|
12
|
-
DEFAULT_GLOBAL_LOG_PATH = '/var/log/imis/imis.log'
|
|
13
|
-
|
|
14
|
-
# Net::HTTP timeouts for the API connection (seconds). open_timeout governs connection
|
|
15
|
-
# establishment (TCP connect + TLS handshake) — the phase that stalls when iMIS is unreachable,
|
|
16
|
-
# so it defaults low to fail fast rather than pin the caller.
|
|
17
|
-
DEFAULT_OPEN_TIMEOUT = 3
|
|
18
|
-
DEFAULT_READ_TIMEOUT = 30
|
|
19
|
-
DEFAULT_WRITE_TIMEOUT = 30
|
|
20
|
-
|
|
21
|
-
REQUIRED = %w[username password].freeze
|
|
22
|
-
OPTIONAL = %w[
|
|
23
|
-
environment logger_file global_log_path pretty_print_api
|
|
24
|
-
open_timeout read_timeout write_timeout
|
|
25
|
-
].freeze
|
|
26
|
-
SETTABLE = (REQUIRED + OPTIONAL).freeze
|
|
27
|
-
|
|
28
|
-
class << self
|
|
29
|
-
# Opt-in +.env+ loader. The gem no longer auto-loads dotenv on require —
|
|
30
|
-
# call this from your app boot (or before +Imis.configure+) if you want
|
|
31
|
-
# +ENV+ populated from +.env+. Idempotent.
|
|
32
|
-
#
|
|
33
|
-
def load_dotenv!
|
|
34
|
-
Dotenv.load
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
8
|
|
|
38
|
-
attr_accessor :
|
|
39
|
-
attr_reader :environment, :logger, :logger_level, :logger_file
|
|
9
|
+
attr_accessor :environment, :imis_id_query_name, :username, :password
|
|
40
10
|
|
|
41
11
|
def initialize
|
|
42
|
-
@environment = default_environment
|
|
43
|
-
@username = ENV.fetch('IMIS_USERNAME', nil)
|
|
44
|
-
@password = ENV.fetch('IMIS_PASSWORD', nil)
|
|
45
|
-
@open_timeout = Integer(ENV.fetch('IMIS_OPEN_TIMEOUT', DEFAULT_OPEN_TIMEOUT).to_s, 10)
|
|
46
|
-
@read_timeout = Integer(ENV.fetch('IMIS_READ_TIMEOUT', DEFAULT_READ_TIMEOUT).to_s, 10)
|
|
47
|
-
@write_timeout = Integer(ENV.fetch('IMIS_WRITE_TIMEOUT', DEFAULT_WRITE_TIMEOUT).to_s, 10)
|
|
48
|
-
@base_logger = Logger.new($stdout, level: :info)
|
|
49
|
-
@logger = ActiveSupport::TaggedLogging.new(@base_logger)
|
|
50
|
-
|
|
51
12
|
yield self if block_given?
|
|
52
|
-
|
|
53
|
-
@logger_level = logger.class::SEV_LABEL[logger.level].downcase.to_sym
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
# Define the API environment
|
|
57
|
-
#
|
|
58
|
-
# @param env [String] Environment to use
|
|
59
|
-
#
|
|
60
|
-
def environment=(env)
|
|
61
|
-
@environment = ActiveSupport::StringInquirer.new(env.to_s)
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
# Override the main logger
|
|
65
|
-
#
|
|
66
|
-
# @param logger [Logger] Configured logging object
|
|
67
|
-
#
|
|
68
|
-
def logger=(logger)
|
|
69
|
-
@base_logger = logger.tap { it.formatter = LoggerFormatter.new }
|
|
70
|
-
@base_logger.singleton_class.include(LoggerHelpers)
|
|
71
|
-
@logger = ActiveSupport::TaggedLogging.new(@base_logger)
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
# Define the main logger
|
|
75
|
-
#
|
|
76
|
-
# @param path [path, nil] Path to write log to, or +nil+ to log to +STDOUT+
|
|
77
|
-
#
|
|
78
|
-
def logger_file=(path)
|
|
79
|
-
@logger_file = path
|
|
80
|
-
@base_logger = Logger.new(@logger_file.nil? ? $stdout : @logger_file, level: logger.level)
|
|
81
|
-
@logger = ActiveSupport::TaggedLogging.new(@base_logger)
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
# Current global mirror debug logger
|
|
85
|
-
#
|
|
86
|
-
def global_logger
|
|
87
|
-
return @global_logger if @global_logger
|
|
88
|
-
|
|
89
|
-
global_log_path
|
|
90
|
-
@global_logger
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
# Current path for the global mirror debug logger
|
|
94
|
-
#
|
|
95
|
-
def global_log_path
|
|
96
|
-
return @global_log_path if defined?(@global_log_path)
|
|
97
|
-
|
|
98
|
-
self.global_log_path = DEFAULT_GLOBAL_LOG_PATH
|
|
99
13
|
end
|
|
100
14
|
|
|
101
|
-
# Define the global mirror debug logger
|
|
102
|
-
#
|
|
103
|
-
# @param path [path, nil] Path to write log to, or +nil+ to disable
|
|
104
|
-
#
|
|
105
|
-
def global_log_path=(path)
|
|
106
|
-
@global_log_path = path
|
|
107
|
-
@global_logger = build_global_logger
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
# Whether the global mirror debug logger writes anywhere. Disabled or unwritable, it is a null
|
|
111
|
-
# logger, and nothing needs to be mirrored to it.
|
|
112
|
-
#
|
|
113
|
-
def global_logging?
|
|
114
|
-
global_logger
|
|
115
|
-
@global_logging
|
|
116
|
-
end
|
|
117
|
-
|
|
118
|
-
def silence!
|
|
119
|
-
self.logger = Logger.new(nil)
|
|
120
|
-
end
|
|
121
|
-
|
|
122
|
-
# Environment-specific API endpoint hostname
|
|
123
|
-
#
|
|
124
|
-
# @return The API hostname for the current environment
|
|
125
|
-
#
|
|
126
15
|
def hostname
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
def instance_variables_to_inspect = instance_variables - %i[@password @base_logger @logger @global_logger]
|
|
136
|
-
|
|
137
|
-
# Parameters to filter out of logging
|
|
138
|
-
#
|
|
139
|
-
def filtered_parameters = %i[password]
|
|
140
|
-
|
|
141
|
-
def validate!
|
|
142
|
-
missing_config = REQUIRED.filter_map { it if public_send(it).nil? }
|
|
143
|
-
return if missing_config.empty?
|
|
144
|
-
|
|
145
|
-
raise Errors::ConfigError, "Missing required configuration: #{missing_config.join(', ')}"
|
|
146
|
-
end
|
|
147
|
-
|
|
148
|
-
private
|
|
149
|
-
|
|
150
|
-
def default_environment
|
|
151
|
-
return ::Rails.env if defined?(::Rails)
|
|
152
|
-
|
|
153
|
-
ActiveSupport::StringInquirer.new(ENV.fetch('IMIS_ENVIRONMENT', 'development'))
|
|
16
|
+
case environment.to_sym
|
|
17
|
+
when :production
|
|
18
|
+
IMIS_ROOT_URL_PROD
|
|
19
|
+
when :development
|
|
20
|
+
IMIS_ROOT_URL_DEV
|
|
21
|
+
else
|
|
22
|
+
raise Error::Api, "Unexpected API environment: #{environment}"
|
|
23
|
+
end
|
|
154
24
|
end
|
|
155
25
|
|
|
156
|
-
def
|
|
157
|
-
writable =
|
|
158
|
-
begin
|
|
159
|
-
FileUtils.mkdir_p(File.dirname(global_log_path))
|
|
160
|
-
File.writable?(global_log_path) || File.writable?(File.dirname(global_log_path))
|
|
161
|
-
rescue StandardError
|
|
162
|
-
false
|
|
163
|
-
end
|
|
164
|
-
@global_logging = writable
|
|
165
|
-
return ActiveSupport::TaggedLogging.new(::Logger.new(nil)) unless writable
|
|
166
|
-
|
|
167
|
-
ActiveSupport::TaggedLogging.new(
|
|
168
|
-
::Logger
|
|
169
|
-
.new(File.open(global_log_path, 'a'), level: :debug)
|
|
170
|
-
.tap { it.formatter = LoggerFormatter.new }
|
|
171
|
-
)
|
|
172
|
-
end
|
|
26
|
+
def instance_variables_to_inspect = %i[@environment @imis_id_query_name @username]
|
|
173
27
|
end
|
|
174
28
|
end
|
|
175
29
|
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Usps
|
|
4
|
+
module Imis
|
|
5
|
+
module Error
|
|
6
|
+
class Api < StandardError
|
|
7
|
+
attr_accessor :metadata
|
|
8
|
+
|
|
9
|
+
def initialize(message, metadata = {})
|
|
10
|
+
super(message)
|
|
11
|
+
@metadata = metadata
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def bugsnag_meta_data
|
|
15
|
+
metadata == {} ? {} : base_metadata
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
private
|
|
19
|
+
|
|
20
|
+
def base_metadata
|
|
21
|
+
{ api: metadata }
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|