Skip to content

Commit

Permalink
Merge branch 'master' into API-42932-vnp-ptcpnt-addrs-standardization
Browse files Browse the repository at this point in the history
  • Loading branch information
stiehlrod authored Dec 18, 2024
2 parents 3a3ec8f + 620033b commit cd28b62
Show file tree
Hide file tree
Showing 6 changed files with 167 additions and 20 deletions.
4 changes: 4 additions & 0 deletions config/features.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1964,3 +1964,7 @@ features:
benefits_non_disability_ch31_v2:
actor_type: user
description: If enabled, use new form and api endpoint for Ch31 VR&E form
is_updated_gi:
actor_type: user
description: If enabled, use updated gi design

7 changes: 6 additions & 1 deletion config/settings.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1856,10 +1856,15 @@ vaos:
base_path: "care-navigation/v1"
scopes: "care-nav"

ogc:
form21a_service_url:
url: http://localhost:5000/api/v1/accreditation/applications/form21a
api_key: fake_key

accredited_representative_portal:
pilot_users_email_poa_codes: ~

banners:
drupal_username: banners_api
drupal_password: test
drupal_url: https://test.cms.va.gov/
drupal_url: https://test.cms.va.gov/
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ class AccreditationService
def self.submit_form21a(parsed_body, user_uuid)
Rails.logger.info("Accreditation Service attempting submit_form21a with service_url: #{service_url}")
connection.post do |req|
req.headers['x-api-key'] = Settings.ogc.form21a_service_url.api_key
req.body = parsed_body.to_json
end
rescue Faraday::ConnectionFailed => e
Expand All @@ -34,22 +35,8 @@ def self.connection
end
end

# NOTE: The interface between GCLAWS/OGC and vets-api is not yet established due to ongoing ESECC and MOU requests.
# TODO: Update the service URL based on the actual production and QA URLs once the below issue is resolved. See:
# https://github.com/department-of-veterans-affairs/va.gov-team/issues/85933
# https://dsva.slack.com/archives/C06ABHUNBRS/p1721769692072489
# self.service_url: Determines and returns the service URL based on the current environment.
def self.service_url
case Rails.env
when 'development', 'test'
# NOTE: the below is a temporary URL for development purposes only.
# TODO: Update this once ESECC request goes through. See: https://github.com/department-of-veterans-affairs/va.gov-team/issues/88288
'http://localhost:5000/api/v1/accreditation/applications/form21a'
when 'production'
# TODO: Update this once MOU has been signed and the ESECC request has gone through. See:
# https://dsva.slack.com/archives/C06ABHUNBRS/p1721769692072489
# https://github.com/department-of-veterans-affairs/va.gov-team/issues/85933
raise 'Accreditation service URL not configured for production'
end
Settings.ogc.form21a_service_url.url
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
describe '#submit_form21a' do
context 'when the request is successful' do
it 'returns a successful response' do
stub_request(:post, 'http://localhost:5000/api/v1/accreditation/applications/form21a')
stub_request(:post, Settings.ogc.form21a_service_url.url)
.to_return(status: 200, body: parsed_body.to_json, headers: { 'Content-Type' => 'application/json' })

response = described_class.submit_form21a(parsed_body, user_uuid)
Expand All @@ -23,12 +23,12 @@

context 'when the connection fails' do
it 'logs the error and returns a service unavailable status' do
stub_request(:post, 'http://localhost:5000/api/v1/accreditation/applications/form21a')
stub_request(:post, Settings.ogc.form21a_service_url.url)
.to_raise(Faraday::ConnectionFailed.new('Accreditation Service connection failed'))

expect(Rails.logger).to receive(:error).with(
"Accreditation Service connection failed for user with user_uuid=#{user_uuid}: " \
'Accreditation Service connection failed, URL: http://localhost:5000/api/v1/accreditation/applications/form21a'
"Accreditation Service connection failed, URL: #{Settings.ogc.form21a_service_url.url}"
)

response = described_class.submit_form21a(parsed_body, user_uuid)
Expand All @@ -40,7 +40,7 @@

context 'when the request times out' do
it 'logs the error and returns a request timeout status' do
stub_request(:post, 'http://localhost:5000/api/v1/accreditation/applications/form21a')
stub_request(:post, Settings.ogc.form21a_service_url.url)
.to_raise(Faraday::TimeoutError.new('Request timed out'))

expect(Rails.logger).to receive(:error).with(
Expand Down
35 changes: 35 additions & 0 deletions modules/vaos/app/services/eps/provider_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,40 @@ def get_networks

OpenStruct.new(response.body)
end

# Retrieves available slots for a specific provider.
#
# @param provider_id [String] The unique identifier of the provider
# @param opts [Hash] Optional parameters for the request
# @option opts [String] :nextToken Token for pagination of results
# @option opts [String] :appointmentTypeId Required if nextToken is not provided. The type of appointment
# @option opts [String] :startOnOrAfter Required if nextToken is not provided. Start of the time range
# (ISO 8601 format)
# @option opts [String] :startBefore Required if nextToken is not provided. End of the time range
# (ISO 8601 format)
# @option opts [Hash] Additional optional parameters will be passed through to the request
#
# @raise [ArgumentError] If nextToken is not provided and any of appointmentTypeId, startOnOrAfter, or
# startBefore are missing
#
# @return [OpenStruct] Response containing available slots
#
def get_provider_slots(provider_id, opts = {})
raise ArgumentError, 'provider_id is required and cannot be blank' if provider_id.blank?

params = if opts[:nextToken]
{ nextToken: opts[:nextToken] }
else
required_params = %i[appointmentTypeId startOnOrAfter startBefore]
missing_params = required_params - opts.keys

raise ArgumentError, "Missing required parameters: #{missing_params.join(', ')}" if missing_params.any?

opts
end

response = perform(:get, "/#{config.base_path}/provider-services/#{provider_id}/slots", params, headers)
OpenStruct.new(response.body)
end
end
end
116 changes: 116 additions & 0 deletions modules/vaos/spec/services/eps/provider_service_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -125,4 +125,120 @@
end
end
end

describe '#get_provider_slots' do
let(:provider_id) { '9mN718pH' }
let(:required_params) do
{
appointmentTypeId: 'type123',
startOnOrAfter: '2024-01-01T00:00:00Z',
startBefore: '2024-01-02T00:00:00Z'
}
end
let(:valid_response) do
double('Response', status: 200, body: { count: 1,
slots: [
{ id: 'slot1', providerServiceId: '9mN718pH' },
{ id: 'slot2', providerServiceId: '9mN718pH' }
] })
end

context 'when provider_id is invalid' do
it 'raises ArgumentError when provider_id is nil' do
expect do
service.get_provider_slots(nil, nextToken: 'token123')
end.to raise_error(ArgumentError, 'provider_id is required and cannot be blank')
end

it 'raises ArgumentError when provider_id is empty' do
expect do
service.get_provider_slots('', nextToken: 'token123')
end.to raise_error(ArgumentError, 'provider_id is required and cannot be blank')
end

it 'raises ArgumentError when provider_id is blank' do
expect do
service.get_provider_slots(' ', nextToken: 'token123')
end.to raise_error(ArgumentError, 'provider_id is required and cannot be blank')
end
end

context 'when nextToken is provided' do
it 'makes request with nextToken parameter' do
next_token = 'token123'
expect_any_instance_of(VAOS::SessionService).to receive(:perform)
.with(:get, "/#{config.base_path}/provider-services/#{provider_id}/slots", { nextToken: next_token }, headers)
.and_return(OpenStruct.new(valid_response.body))

service.get_provider_slots(provider_id, nextToken: next_token)
end
end

context 'when required and additional parameters are provided' do
it 'makes request with all parameters' do
params_with_extra = required_params.merge(appointmentId: 'id123')

expect_any_instance_of(VAOS::SessionService).to receive(:perform)
.with(:get, "/#{config.base_path}/provider-services/#{provider_id}/slots", params_with_extra, headers)
.and_return(valid_response)

service.get_provider_slots(provider_id, params_with_extra)
end
end

context 'when required parameters are missing' do
it 'raises ArgumentError when appointmentTypeId is missing' do
expect do
service.get_provider_slots(provider_id, required_params.except(:appointmentTypeId))
end.to raise_error(ArgumentError, /Missing required parameters: appointmentTypeId/)
end

it 'raises ArgumentError when startOnOrAfter is missing' do
expect do
service.get_provider_slots(provider_id, required_params.except(:startOnOrAfter))
end.to raise_error(ArgumentError, /Missing required parameters: startOnOrAfter/)
end

it 'raises ArgumentError when startBefore is missing' do
expect do
service.get_provider_slots(provider_id, required_params.except(:startBefore))
end.to raise_error(ArgumentError, /Missing required parameters: startBefore/)
end

it 'raises ArgumentError when multiple required parameters are missing' do
expect do
service.get_provider_slots(provider_id, required_params.except(:startOnOrAfter, :startBefore))
end.to raise_error(ArgumentError, /Missing required parameters: startOnOrAfter, startBefore/)
end
end

context 'when required parameters are provided and request is successful' do
before do
allow_any_instance_of(VAOS::SessionService).to receive(:perform).and_return(valid_response)
end

it 'returns an OpenStruct with the response body' do
result = service.get_provider_slots(provider_id, required_params)

expect(result).to eq(OpenStruct.new(valid_response.body))
end
end

context 'when the request fails' do
let(:response) { double('Response', status: 500, body: 'Unknown service exception') }
let(:exception) do
Common::Exceptions::BackendServiceException.new(nil, {}, response.status, response.body)
end

before do
allow_any_instance_of(VAOS::SessionService).to receive(:perform).and_raise(exception)
end

it 'raises an error' do
expect do
service.get_provider_slots(provider_id, required_params)
end.to raise_error(Common::Exceptions::BackendServiceException, /VA900/)
end
end
end
end

0 comments on commit cd28b62

Please sign in to comment.