Skip to content

Commit

Permalink
Merge branch 'master' into dbex/80718-TE-transform-2
Browse files Browse the repository at this point in the history
  • Loading branch information
sethdarragile6 authored Apr 24, 2024
2 parents e7ce01b + 994c71f commit 41df9ff
Show file tree
Hide file tree
Showing 10 changed files with 200 additions and 3 deletions.
2 changes: 1 addition & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -692,7 +692,7 @@ GEM
os (1.1.4)
ox (2.14.18)
parallel (1.24.0)
parallel_tests (4.6.1)
parallel_tests (4.7.0)
parallel
parser (3.3.0.5)
ast (~> 2.4.1)
Expand Down
31 changes: 29 additions & 2 deletions app/models/form526_submission.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ class Form526Submission < ApplicationRecord
state :unprocessed, initial: true
state :delivered_to_primary, :failed_primary_delivery, :rejected_by_primary,
:delivered_to_backup, :failed_backup_delivery, :rejected_by_backup,
:in_remediation, :finalized_as_successful, :unprocessable
:in_remediation, :finalized_as_successful, :unprocessable,
:processed_in_batch_remediation, :ignorable_duplicate

# - a submission has been delivered to our happy path
# - requires polling to finalize
Expand Down Expand Up @@ -62,7 +63,6 @@ class Form526Submission < ApplicationRecord
transitions to: :in_remediation
end

# TODO: add this transition when we add 526 completion polling
# - The only state that means we no longer own completion of this submission
# - There is nothing more to do. E.G.
# - VBMS has accepted and returned the applicable status to us via
Expand All @@ -78,6 +78,33 @@ class Form526Submission < ApplicationRecord
event :mark_as_unprocessable do
transitions to: :unprocessable
end

# A special state to indicate this was part of our remediation 'batching'
# process in 2023. These were handled manually and are distinct from `in_remediation`
# in that they were not tracked at the time of remediation, but rather later in
# the 2024 526 State audit.
#
# This state is useful to us at the time of creation, but may be something
# to flatten to a simple `finalized_as_successful` in the future.
event :process_in_batch_remediation do
transitions to: :processed_in_batch_remediation
end

# A special state to indicate this was part of our remediation 'batching'
# process in 2023. These submissions may have been processed or not, but
# we don't care because they have an earlier, successful duplicate.
#
# Duplicates are identified by comparing form_json, using this script:
# https://github.com/department-of-veterans-affairs/va.gov-team-sensitive/blob/master/teams/benefits/scripts/526/submission_deduper.rb
# The result of this script can be evaluated by a qualified stakeholder to make
# a judgement call on whether or not a submission is a 'perfect' duplicate.
#
# IF a submission is found to be an exact duplicate of another
# AND its duplicate was previously submitted / remediated successfully
# THEN we can ignore it as a duplicate
event :ignore_as_duplicate do
transitions to: :ignorable_duplicate
end
end

wrap_with_logging(:start_evss_submission_job,
Expand Down
3 changes: 3 additions & 0 deletions config/features.yml
Original file line number Diff line number Diff line change
Expand Up @@ -730,6 +730,9 @@ features:
actor_type: user
description: Enables/disables refill-related content for Medications on VA.gov
enable_in_development: true
mhv_landing_page_enable_va_gov_health_tools_links:
actor_type: user
description: Enables VA.gov Health Tools links (Appts, SM, Rx, Records) on MHV-on-VA.gov Landing Page
mhv_to_logingov_account_transition:
actor_type: cookie_id
description: Enables/disables MHV to Login.gov account transfer experience (Identity)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# frozen_string_literal: true

require 'debts_api/v0/financial_status_report_service'
require 'debts_api/v0/fsr_rehydration_service'

module DebtsApi
module V0
Expand All @@ -23,6 +24,27 @@ def download_pdf
)
end

def submissions
submissions = DebtsApi::V0::Form5655Submission.where(user_uuid: current_user.uuid)
render json: { 'submissions' => submissions.map { |sub| { 'id' => sub.id } } }
end

def rehydrate
submission_id = params[:submission_id]

DebtsApi::V0::FsrRehydrationService.attempt_rehydration(user_uuid: current_user.uuid, submission_id:)

render json: { result: 'FSR rehydrated' }
rescue ActiveRecord::RecordNotFound
render json: { error: "Form5655Submission record #{submission_id} not found." }, status: :not_found
rescue DebtsApi::V0::FsrRehydrationService::UserDoesNotOwnsubmission
render json: { error: "User #{current_user.uuid} does not own submission #{submission_id}" },
status: :unauthorized
rescue DebtsApi::V0::FsrRehydrationService::NoInProgressFormDataStored
render json: { error: "Form5655Submission record #{submission_id} missing InProgressForm data",
status: :not_found }
end

private

def render_not_found
Expand Down
3 changes: 3 additions & 0 deletions modules/debts_api/config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@
resources :financial_status_reports, only: %i[create] do
collection do
get :download_pdf
get :submissions
end
end

get 'financial_status_reports/rehydrate_submission/:submission_id', to: 'financial_status_reports#rehydrate'

post 'calculate_total_assets', to: 'financial_status_reports_calculations#total_assets'
post 'calculate_monthly_expenses', to: 'financial_status_reports_calculations#monthly_expenses'
post 'calculate_all_expenses', to: 'financial_status_reports_calculations#all_expenses'
Expand Down
19 changes: 19 additions & 0 deletions modules/debts_api/lib/debts_api/v0/fsr_rehydration_service.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# frozen_string_literal: true

module DebtsApi
class V0::FsrRehydrationService
include SentryLogging

class UserDoesNotOwnsubmission < StandardError; end
class NoInProgressFormDataStored < StandardError; end

def self.attempt_rehydration(user_uuid:, submission_id:)
submission = DebtsApi::V0::Form5655Submission.find(submission_id)

raise NoInProgressFormDataStored unless submission.ipf_data
raise UserDoesNotOwnsubmission unless submission.user_uuid == user_uuid

submission.upsert_in_progress_form
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,39 @@ def mock_pdf_fill
expect(response.body).to eq(content)
end
end

describe '#rehydrate' do
context 'on a nonexistent submission' do
it 'renders a 404' do
get '/debts_api/v0/financial_status_reports/rehydrate_submission/1'
expect(response).to have_http_status(:not_found)
end
end

context 'on a submission you don\'t own' do
let(:form5655_submission) { create(:debts_api_form5655_submission) }

it 'renders a 404' do
form5655_submission
form5655_submission.update!(user_uuid: 'nottherightguy', ipf_data: '{"its":"me"}')
get "/debts_api/v0/financial_status_reports/rehydrate_submission/#{form5655_submission.id}"
expect(response.code).to eq('401')
body = "{\"error\":\"User #{user.uuid} does not own submission #{form5655_submission.id}\"}"
expect(response.body).to eq(body)
end
end

context 'on a submission you do own' do
let(:form5655_submission) do
create(:debts_api_form5655_submission, user_uuid: 'b2fab2b56af045e1a9e2394347af91ef')
end

it 'rehydrates In Progress Form' do
form5655_submission
form5655_submission.update!(user_uuid: user.uuid, ipf_data: '{"its":"me"}')
get "/debts_api/v0/financial_status_reports/rehydrate_submission/#{form5655_submission.id}"
expect(response.code).to eq('200')
end
end
end
end
22 changes: 22 additions & 0 deletions modules/vaos/app/services/vaos/v2/appointments_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class AppointmentsService < VAOS::SessionService
FACILITY_ERROR_MSG = 'Error fetching facility details'
AVS_ERROR_MESSAGE = 'Error retrieving AVS link'
AVS_APPT_TEST_ID = '192308'
MANILA_PHILIPPINES_FACILITY_ID = '358'

AVS_FLIPPER = :va_online_scheduling_after_visit_summary
ORACLE_HEALTH_CANCELLATIONS = :va_online_scheduling_enable_OH_cancellations
Expand Down Expand Up @@ -411,15 +412,36 @@ def convert_appointment_time(appt)
if !appt[:start].nil?
facility_timezone = get_facility_timezone_memoized(appt[:location_id])
appt[:local_start_time] = convert_utc_to_local_time(appt[:start], facility_timezone)

if appt[:location_id] == MANILA_PHILIPPINES_FACILITY_ID
log_timezone_info(appt[:location_id], facility_timezone, appt[:start], appt[:local_start_time])
end

elsif !appt.dig(:requested_periods, 0, :start).nil?
appt[:requested_periods].each do |period|
facility_timezone = get_facility_timezone_memoized(appt[:location_id])
period[:local_start_time] = convert_utc_to_local_time(period[:start], facility_timezone)

if appt[:location_id] == MANILA_PHILIPPINES_FACILITY_ID
log_timezone_info(appt[:location_id], facility_timezone, period[:start], period[:local_start_time])
end
end
end
appt
end

def log_timezone_info(appt_location_id, facility_timezone, appt_start_time_utc, appt_start_time_local)
Rails.logger.info(
"Timezone info for Manila Philippines location_id #{appt_location_id}",
{
location_id: appt_location_id,
facility_timezone:,
appt_start_time_utc:,
appt_start_time_local:
}.to_json
)
end

# Returns a local [DateTime] object converted from UTC using the facility's timezone offset.
# We'd like to perform this change only on the appointment responses to offer a consistently
# formatted local time to our consumers while not changing how we pass DateTimes to upstream services.
Expand Down
62 changes: 62 additions & 0 deletions modules/vaos/spec/services/v2/appointment_service_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -623,6 +623,68 @@
end
end

describe '#convert_appointment_time' do
let(:manila_appt) do
{
id: '12345',
location_id: '358',
start: '2024-12-20T00:00:00Z'
}
end

let(:manila_appt_req) do
{
id: '12345',
location_id: '358',
requested_periods: [{ start: '2024-12-20T00:00:00Z', end: '2024-12-20T11:59:59.999Z' }]
}
end

context 'when appt location id is 358' do
it 'logs the appt location id, timezone info, utc/local times of appt' do
allow_any_instance_of(VAOS::V2::AppointmentsService)
.to receive(:get_facility_timezone_memoized)
.and_return('Asia/Manila')
allow(Rails.logger).to receive(:info)

subject.send(:convert_appointment_time, manila_appt)
expect(Rails.logger).to have_received(:info).with('Timezone info for Manila Philippines location_id 358',
{
location_id: '358',
facility_timezone: 'Asia/Manila',
appt_start_time_utc: '2024-12-20T00:00:00Z',
appt_start_time_local: subject.send(
:convert_utc_to_local_time,
manila_appt[:start],
'Asia/Manila'
)
}.to_json)
end

it 'logs the appt location id, timezone info, utc/local times of appt request' do
allow_any_instance_of(VAOS::V2::AppointmentsService)
.to receive(:get_facility_timezone_memoized)
.and_return('Asia/Manila')
allow(Rails.logger).to receive(:info)

subject.send(:convert_appointment_time, manila_appt_req)
expect(Rails.logger).to have_received(:info).with('Timezone info for Manila Philippines location_id 358',
{
location_id: '358',
facility_timezone: 'Asia/Manila',
appt_start_time_utc: '2024-12-20T00:00:00Z',
appt_start_time_local: subject.send(
:convert_utc_to_local_time, manila_appt_req.dig(
:requested_periods,
0,
:start
), 'Asia/Manila'
)
}.to_json)
end
end
end

describe '#convert_utc_to_local_time' do
let(:start_datetime) { '2021-09-02T14:00:00Z'.to_datetime }

Expand Down
4 changes: 4 additions & 0 deletions spec/models/form526_submission_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,10 @@
.to(:unprocessable).on_event(:mark_as_unprocessable)
expect(submission).to transition_from(:unprocessed)
.to(:in_remediation).on_event(:begin_remediation)
expect(submission).to transition_from(:unprocessed)
.to(:processed_in_batch_remediation).on_event(:process_in_batch_remediation)
expect(submission).to transition_from(:unprocessed)
.to(:ignorable_duplicate).on_event(:ignore_as_duplicate)
end
end

Expand Down

0 comments on commit 41df9ff

Please sign in to comment.