diff --git a/modules/appeals_api/app/models/appeals_api/supplemental_claim.rb b/modules/appeals_api/app/models/appeals_api/supplemental_claim.rb index d994814374a..b2e270dbab6 100644 --- a/modules/appeals_api/app/models/appeals_api/supplemental_claim.rb +++ b/modules/appeals_api/app/models/appeals_api/supplemental_claim.rb @@ -15,7 +15,7 @@ class SupplementalClaim < ApplicationRecord attr_readonly :form_data before_create :assign_metadata, :assign_veteran_icn - before_update :submit_evidence_to_central_mail!, if: -> { status_changed_to_success? && delay_evidence_enabled? } + before_update :submit_evidence_to_central_mail!, if: -> { status_changed_to_complete? && delay_evidence_enabled? } def self.past?(date) date < Time.zone.today @@ -45,6 +45,7 @@ def self.date_from_string(string) has_many :evidence_submissions, as: :supportable, dependent: :destroy has_many :status_updates, as: :statusable, dependent: :destroy + # the controller applies the JSON Schemas in modules/appeals_api/config/schemas/ # further validations: validate( @@ -330,8 +331,8 @@ def email_present? claimant.email.present? || email_identifier.present? end - def status_changed_to_success? - status_changed? && status == 'success' + def status_changed_to_complete? + status_changed? && status == 'complete' end def delay_evidence_enabled? diff --git a/modules/appeals_api/app/sidekiq/appeals_api/evidence_submission_backup.rb b/modules/appeals_api/app/sidekiq/appeals_api/evidence_submission_backup.rb index a7f9ad80eb2..23fddf6773e 100644 --- a/modules/appeals_api/app/sidekiq/appeals_api/evidence_submission_backup.rb +++ b/modules/appeals_api/app/sidekiq/appeals_api/evidence_submission_backup.rb @@ -14,15 +14,41 @@ class EvidenceSubmissionBackup sidekiq_options retry: 5 APPEAL_TYPES = [NoticeOfDisagreement.name, SupplementalClaim.name].freeze - APPEAL_STATUSES = %w[success complete error].freeze + APPEAL_STATUSES = %w[complete error].freeze def perform return unless enabled? - evidence_to_submit.each(&:submit_to_central_mail!) + evidence_to_submit_by_status.each(&:submit_to_central_mail!) + evidence_to_submit_by_age.each(&:submit_to_central_mail!) end - def evidence_to_submit + def evidence_to_submit_by_age + # Get Supp Claims EvidenceSubmissions that have been uploaded to our s3 bucket, but not submitted to central_mail. + # Preload the SupplementalClaim(supportable) association and the nested status_updates to get the submitted to + # central mail date time to wait 24 hours after CM has the appeal to force the upload irregardless + # of the appeal's status. + ess = AppealsApi::EvidenceSubmission.includes(supportable: :status_updates).uploaded + .where(supportable_type: APPEAL_TYPES) + + # filter out EvidenceSubmissions less than 24 hours old + ess.filter do |es| + # get the time since the supp claim itself was submited and accepted by central mail in hours + cm_submitted_time = es.supportable.status_updates + .filter { |us| us.to == 'submitted' } + .max_by { |us| us.status_update_time.to_i } + &.status_update_time + + # if no status update to submitted record just use appeal created_at instead + cm_submitted_time = es.supportable.created_at if cm_submitted_time.nil? + + # convert seconds to hours, if the appeal is older than 24 hours, evidence submission + # needs to be uploaded to central mail + (Time.zone.now - cm_submitted_time) / 3600.0 >= 24 + end + end + + def evidence_to_submit_by_status preloaded_evidence_submissions.select { |es| APPEAL_STATUSES.include?(es.supportable.status) } end diff --git a/modules/appeals_api/spec/models/supplemental_claim_spec.rb b/modules/appeals_api/spec/models/supplemental_claim_spec.rb index d543ebf656c..edf743dc81c 100644 --- a/modules/appeals_api/spec/models/supplemental_claim_spec.rb +++ b/modules/appeals_api/spec/models/supplemental_claim_spec.rb @@ -458,14 +458,14 @@ describe 'before_update' do before { allow(supplemental_claim).to receive(:submit_evidence_to_central_mail!) } - context 'when the status has changed to "success"' do + context 'when the status has changed to "complete"' do let(:supplemental_claim) { create(:supplemental_claim, status: 'processing') } context 'and the delay evidence feature is enabled' do before { Flipper.enable(:decision_review_delay_evidence) } it 'calls "#submit_evidence_to_central_mail!"' do - supplemental_claim.update(status: 'success') + supplemental_claim.update(status: 'complete') expect(supplemental_claim).to have_received(:submit_evidence_to_central_mail!) end @@ -475,7 +475,7 @@ before { Flipper.disable(:decision_review_delay_evidence) } it 'does not call "#submit_evidence_to_central_mail!"' do - supplemental_claim.update(status: 'success') + supplemental_claim.update(status: 'complete') expect(supplemental_claim).not_to have_received(:submit_evidence_to_central_mail!) end diff --git a/modules/appeals_api/spec/sidekiq/appeals_api/evidence_submission_backup_spec.rb b/modules/appeals_api/spec/sidekiq/appeals_api/evidence_submission_backup_spec.rb index a029cab07ac..b961a8b5c80 100644 --- a/modules/appeals_api/spec/sidekiq/appeals_api/evidence_submission_backup_spec.rb +++ b/modules/appeals_api/spec/sidekiq/appeals_api/evidence_submission_backup_spec.rb @@ -18,12 +18,24 @@ upload_submission: create(:upload_submission, status: 'uploaded', guid: SecureRandom.uuid)) end + let(:evidence_submission_appeal_with_old_uploaded_status_updates) do + create(:evidence_submission, + supportable: create(:notice_of_disagreement, status: 'submitted'), + upload_submission: create(:upload_submission, status: 'uploaded', guid: SecureRandom.uuid)) + end + let(:status_update_submitted) do + create(:status_update, + to: 'submitted', + status_update_time: 92.days.ago, + statusable: evidence_submission_appeal_with_old_uploaded_status_updates.supportable) + end + it_behaves_like 'a monitored worker' # rubocop:disable RSpec/SubjectStub describe '#perform' do before do - allow(subject).to receive(:evidence_to_submit).and_return( + allow(subject).to receive(:evidence_to_submit_by_status).and_return( [ evidence_submission_appeal_success, evidence_submission_appeal_complete @@ -31,6 +43,13 @@ ) allow(evidence_submission_appeal_success).to receive(:submit_to_central_mail!) allow(evidence_submission_appeal_complete).to receive(:submit_to_central_mail!) + + allow(subject).to receive(:evidence_to_submit_by_age).and_return( + [ + evidence_submission_appeal_with_old_uploaded_status_updates + ] + ) + allow(evidence_submission_appeal_with_old_uploaded_status_updates).to receive(:submit_to_central_mail!) end context 'when the delay evidence feature is enabled' do @@ -41,6 +60,7 @@ expect(evidence_submission_appeal_success).to have_received(:submit_to_central_mail!) expect(evidence_submission_appeal_complete).to have_received(:submit_to_central_mail!) + expect(evidence_submission_appeal_with_old_uploaded_status_updates).to have_received(:submit_to_central_mail!) end end @@ -50,29 +70,23 @@ it 'does not take any action' do subject.perform - expect(subject).not_to have_received(:evidence_to_submit) + expect(subject).not_to have_received(:evidence_to_submit_by_status) expect(evidence_submission_appeal_success).not_to have_received(:submit_to_central_mail!) expect(evidence_submission_appeal_complete).not_to have_received(:submit_to_central_mail!) + expect(evidence_submission_appeal_with_old_uploaded_status_updates) + .not_to have_received(:submit_to_central_mail!) end end end # rubocop:enable RSpec/SubjectStub - describe '#evidence_to_submit' do - it 'returns evidence in "uploaded" status when appeal is in "success" status' do - evidence = create(:evidence_submission, - supportable: create(:supplemental_claim, status: 'success'), - upload_submission: create(:upload_submission, status: 'uploaded', guid: SecureRandom.uuid)) - - expect(subject.evidence_to_submit).to include(evidence) - end - + describe '#evidence_to_submit_by_status' do it 'returns evidence in "uploaded" status when appeal is in "complete" status' do evidence = create(:evidence_submission, supportable: create(:notice_of_disagreement, status: 'complete'), upload_submission: create(:upload_submission, status: 'uploaded', guid: SecureRandom.uuid)) - expect(subject.evidence_to_submit).to include(evidence) + expect(subject.evidence_to_submit_by_status).to include(evidence) end it 'returns evidence in "uploaded" status when appeal is in "error" status' do @@ -80,7 +94,7 @@ supportable: create(:supplemental_claim, status: 'error'), upload_submission: create(:upload_submission, status: 'uploaded', guid: SecureRandom.uuid)) - expect(subject.evidence_to_submit).to include(evidence) + expect(subject.evidence_to_submit_by_status).to include(evidence) end it 'does not return evidence when evidence not in "uploaded" status' do @@ -88,7 +102,15 @@ supportable: create(:notice_of_disagreement, status: 'success'), upload_submission: create(:upload_submission, status: 'received', guid: SecureRandom.uuid)) - expect(subject.evidence_to_submit).not_to include(evidence) + expect(subject.evidence_to_submit_by_status).not_to include(evidence) + end + + it 'does not returns evidence in "uploaded" status when appeal is in "success" status' do + evidence = create(:evidence_submission, + supportable: create(:supplemental_claim, status: 'success'), + upload_submission: create(:upload_submission, status: 'uploaded', guid: SecureRandom.uuid)) + + expect(subject.evidence_to_submit_by_status).not_to include(evidence) end it 'does not return evidence in "uploaded" status when appeal is still in "submitted" status' do @@ -96,7 +118,69 @@ supportable: create(:supplemental_claim, status: 'submitted'), upload_submission: create(:upload_submission, status: 'uploaded', guid: SecureRandom.uuid)) - expect(subject.evidence_to_submit).not_to include(evidence) + expect(subject.evidence_to_submit_by_status).not_to include(evidence) + end + end + + describe '#evidence_to_submit_by_age' do + it 'returns evidence in "uploaded" status when appeal is in "submitted" status' do + # appeal over 24 hours old so should be returned + nod = create(:notice_of_disagreement, status: 'submitted') + # status update record for appeal + create(:status_update, + to: 'submitted', + status_update_time: 5.days.ago, + statusable: nod) + old_evidence1 = create(:evidence_submission, + supportable: nod, + upload_submission: create(:upload_submission, + status: 'uploaded', + guid: SecureRandom.uuid)) + old_evidence2 = create(:evidence_submission, + supportable: nod, + upload_submission: create(:upload_submission, + status: 'uploaded', + guid: SecureRandom.uuid)) + + # appeal less than 24 hours old + new_evidence = create(:evidence_submission, + supportable: create(:notice_of_disagreement, status: 'submitted'), + upload_submission: create(:upload_submission, status: 'uploaded', guid: SecureRandom.uuid)) + # corner case, two status records, should use the 'newest'(1 hour old one) for appeal + # age calc, and since its only 1 hour old since submitted to CM, this evidence submission + # should not be uploaded yet + create(:status_update, + to: 'submitted', + status_update_time: 5.days.ago, + statusable: new_evidence.supportable) + create(:status_update, + to: 'submitted', + status_update_time: 1.hour.ago, + statusable: new_evidence.supportable) + + # appeal older than 24 hours, no status update so uses created at timestamp to calc age + old_evidence_no_submitted_status_update = create(:evidence_submission, + supportable: create(:notice_of_disagreement, + status: 'submitted', + created_at: 2.days.ago), + upload_submission: create(:upload_submission, + status: 'uploaded', + guid: SecureRandom.uuid)) + + # appeal less than 24 hours old, no status update so uses created at timestamp to calc age + new_evidence_no_submitted_status_update = create(:evidence_submission, + supportable: create(:notice_of_disagreement, + status: 'submitted', + created_at: 1.minute.ago), + upload_submission: create(:upload_submission, + status: 'uploaded', + guid: SecureRandom.uuid)) + expect(subject.evidence_to_submit_by_age).to include(old_evidence1) + expect(subject.evidence_to_submit_by_age).to include(old_evidence2) + expect(subject.evidence_to_submit_by_age).to include(old_evidence_no_submitted_status_update) + + expect(subject.evidence_to_submit_by_age).not_to include(new_evidence) + expect(subject.evidence_to_submit_by_age).not_to include(new_evidence_no_submitted_status_update) end end end