Skip to content

Commit

Permalink
56197 Filter Out Service Type(s) on Non-health Non-CnP Appointments (#…
Browse files Browse the repository at this point in the history
…12845)

* feat(vaos): remove service types for non-medical for non-medical non-CnP
non-cc appointments

* test(vaos): fixed rspec tests that would intermittently fail
  • Loading branch information
ajmagdub authored May 31, 2023
1 parent 2e5fc61 commit 7ec7ae1
Show file tree
Hide file tree
Showing 5 changed files with 711 additions and 8 deletions.
62 changes: 60 additions & 2 deletions modules/vaos/app/services/vaos/v2/appointments_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ def get_appointments(start_date, end_date, statuses = nil, pagination_params = {
# for covid appointments set cancellable to false per GH#58690
set_cancellable_false(appt) if covid?(appt)

# remove service type(s) for non-medical non-CnP appointments per GH#56197
remove_service_type(appt) unless medical?(appt) || cnp?(appt) || no_service_cat?(appt)

log_telehealth_data(appt[:telehealth]&.[](:atlas)) unless appt[:telehealth]&.[](:atlas).nil?
convert_appointment_time(appt)
end
Expand All @@ -41,10 +44,17 @@ def get_appointment(appointment_id)
with_monitoring do
response = perform(:get, get_appointment_base_url(appointment_id), params, headers)
convert_appointment_time(response.body[:data])

# for CnP appointments set cancellable to false per GH#57824
set_cancellable_false(response.body[:data]) if cnp?(response.body[:data])
# for covid appointments set cancellable to false per GH#58690
set_cancellable_false(response.body[:data]) if covid?(response.body[:data])

# remove service type(s) for non-medical non-CnP appointments per GH#56197
unless medical?(response.body[:data]) || cnp?(response.body[:data]) || no_service_cat?(response.body[:data])
remove_service_type(response.body[:data])
end

OpenStruct.new(response.body[:data])
end
end
Expand Down Expand Up @@ -89,24 +99,72 @@ def codes(input)
input.flat_map { |codeable_concept| codeable_concept[:coding]&.pluck(:code) }.compact
end

# Returns true if the appointment is for compensation and pension, false otherwise.
# Determines if the appointment is for compensation and pension.
#
# @param appt [Hash] the appointment to check
# @return [Boolean] true if the appointment is for compensation and pension, false otherwise
#
# @raise [ArgumentError] if the appointment is nil
#
def cnp?(appt)
raise ArgumentError, 'Appointment cannot be nil' if appt.nil?

codes(appt[:service_category]).include? 'COMPENSATION & PENSION'
end

# Returns true if the appointment is for covid, false otherwise.
# Determines if the appointment is for covid.
#
# @param appt [Hash] the appointment to check
# @return [Boolean] true if the appointment is for covid, false otherwise
#
# @raise [ArgumentError] if the appointment is nil
#
def covid?(appt)
raise ArgumentError, 'Appointment cannot be nil' if appt.nil?

codes(appt[:service_types]).include?('covid') || appt[:service_type] == 'covid'
end

# Determines if the appointment is a medical appointment.
#
# @param appt [Hash] The hash object containing appointment details.
# @return [Boolean] true if the appointment is a medical appointment, false otherwise.
#
# @raise [ArgumentError] if the appointment is nil
#
def medical?(appt)
raise ArgumentError, 'Appointment cannot be nil' if appt.nil?

codes(appt[:service_category]).include?('REGULAR')
end

# Determines if the appointment does not have a service category.
#
# @param appt [Hash] The hash object containing appointment details.
# @return [Boolean] true if the appointment does not have a service category, false otherwise.
#
# @raise [ArgumentError] if the appointment is nil
#
def no_service_cat?(appt)
raise ArgumentError, 'Appointment cannot be nil' if appt.nil?

codes(appt[:service_category]).empty?
end

# Modifies the appointment removing the service types and service type elements.
#
# @param appt [Hash] The hash object containing appointment details.
#
# @raises [ArgumentError] if the given appointment is nil.
#
def remove_service_type(appt)
raise ArgumentError, 'Appointment cannot be nil' if appt.nil?

appt.delete(:service_type)
appt.delete(:service_types)
nil
end

# Entry point for processing appointment responses for converting their times from UTC to local.
# Uses the location_id from the appt body to fetch the facility's timezone that is then passed along
# with the appointment time to the convert_utc_to_local_time method which does the actual conversion.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,19 @@

require 'rails_helper'

RSpec.describe 'vaos scheduling/configurations', type: :request, skip_mvi: true do
RSpec.describe VAOS::V2::SchedulingController, type: :request, skip_mvi: true do
include SchemaMatchers

let(:inflection_header) { { 'X-Key-Inflection' => 'camel' } }
let(:current_user) { build(:user, :vaos) }

before do
Flipper.enable('va_online_scheduling')
sign_in_as(current_user)
allow_any_instance_of(VAOS::UserService).to receive(:session).and_return('stubbed_token')
end

let(:inflection_header) { { 'X-Key-Inflection' => 'camel' } }

context 'vaos user' do
let(:current_user) { build(:user, :vaos) }

context 'with vaos user' do
describe 'GET scheduling/configurations' do
context 'has access and is given single facility id' do
it 'returns a single scheduling configuration' do
Expand Down
95 changes: 95 additions & 0 deletions modules/vaos/spec/services/v2/appointment_service_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,21 @@
let(:id) { '202006031600983000030800000000000000' }
let(:appointment_id) { 123 }

let(:appt_med) do
{ kind: 'clinic', service_category: [{ coding:
[{ system: 'http://www.va.gov/terminology/vistadefinedterms/409_1', code: 'REGULAR' }] }] }
end
let(:appt_non) do
{ kind: 'clinic', service_category: [{ coding:
[{ system: 'http://www.va.gov/terminology/vistadefinedterms/409_1', code: 'SERVICE CONNECTED' }] }],
service_type: 'SERVICE CONNECTED', service_types: [{ coding: [{ system: 'http://www.va.gov/terminology/vistadefinedterms/409_1', code: 'SERVICE CONNECTED' }] }] }
end
let(:appt_cnp) do
{ kind: 'clinic', service_category: [{ coding:
[{ system: 'http://www.va.gov/terminology/vistadefinedterms/409_1', code: 'COMPENSATION & PENSION' }] }] }
end
let(:appt_no_service_cat) { { kind: 'clinic' } }

mock_facility = {
test: 'test',
timezone: {
Expand Down Expand Up @@ -199,6 +214,19 @@
end
end

context 'when requesting a list of appointments containing a non-Med non-CnP non-CC appointment' do
it 'removes the service type(s) from only the non-med non-cnp non-covid appointment' do
VCR.use_cassette('vaos/v2/appointments/get_appointments_non_med',
allow_playback_repeats: true, match_requests_on: %i[method path query], tag: :force_utf8) do
response = subject.get_appointments(start_date2, end_date2)
expect(response[:data][0][:service_type]).to be_nil
expect(response[:data][0][:service_types]).to be_nil
expect(response[:data][1][:service_type]).not_to be_nil
expect(response[:data][1][:service_types]).not_to be_nil
end
end
end

context '400' do
it 'raises a 400 error' do
VCR.use_cassette('vaos/v2/appointments/get_appointments_400', match_requests_on: %i[method path query]) do
Expand Down Expand Up @@ -269,6 +297,19 @@
end
end

context 'when requesting a non-Med non-CnP appointment' do
let(:user) { build(:user, :vaos) }

it 'removes the appointments service type and service types attributes' do
VCR.use_cassette('vaos/v2/appointments/get_appointment_200_non_med',
match_requests_on: %i[method path query]) do
response = subject.get_appointment('159472')
expect(response[:service_type]).to be_nil
expect(response[:service_types]).to be_nil
end
end
end

context 'when the upstream server returns a 500' do
it 'raises a backend exception' do
VCR.use_cassette('vaos/v2/appointments/get_appointment_500', match_requests_on: %i[method path query]) do
Expand Down Expand Up @@ -404,4 +445,58 @@
end
end
end

describe '#medical?' do
it 'raises an ArgumentError if appt is nil' do
expect { subject.send(:medical?, nil) }.to raise_error(ArgumentError, 'Appointment cannot be nil')
end

it 'returns true for medical appointments' do
expect(subject.send(:medical?, appt_med)).to eq(true)
end

it 'returns false for non-medical appointments' do
expect(subject.send(:medical?, appt_non)).to eq(false)
end
end

describe '#no_service_cat?' do
it 'raises an ArgumentError if appt is nil' do
expect { subject.send(:no_service_cat?, nil) }.to raise_error(ArgumentError, 'Appointment cannot be nil')
end

it 'returns true for appointments without a service category' do
expect(subject.send(:no_service_cat?, appt_no_service_cat)).to eq(true)
end

it 'returns false for appointments with a service category' do
expect(subject.send(:no_service_cat?, appt_non)).to eq(false)
end
end

describe '#cnp?' do
it 'raises an ArgumentError if appt is nil' do
expect { subject.send(:cnp?, nil) }.to raise_error(ArgumentError, 'Appointment cannot be nil')
end

it 'returns true for compensation and pension appointments' do
expect(subject.send(:cnp?, appt_cnp)).to eq(true)
end

it 'returns false for non compensation and pension appointments' do
expect(subject.send(:cnp?, appt_non)).to eq(false)
end
end

describe '#remove_service_type' do
it 'raises an ArgumentError if appt is nil' do
expect { subject.send(:remove_service_type, nil) }.to raise_error(ArgumentError, 'Appointment cannot be nil')
end

it 'Modifies the appointment with service type(s) removed from appointment' do
expect { subject.send(:remove_service_type, appt_non) }.to change(appt_non, :keys)
.from(%i[kind service_category service_type service_types])
.to(%i[kind service_category])
end
end
end

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 7ec7ae1

Please sign in to comment.