From 34b3fb4c0e676b05c8a824293e0666d5b2872735 Mon Sep 17 00:00:00 2001 From: sahalliburton <61989526+sahalliburton@users.noreply.github.com> Date: Fri, 8 May 2020 12:15:10 -0400 Subject: [PATCH] Updated evidence submission window task expiration based on hearing withdrawal date (#14135) Resolves #14077 ### Description Changed the logic for calculating when an EvidencesSubmissionWindow task expires. - Previously the expiration was based on receipt date so long as there was not an associated hearing. - Now the task expires based on the receipt date only if in the evidence submission docket and it expires based on the hearing withdrawal date for all others ### Acceptance Criteria - [ ] Code compiles correctly - [ ] EvidenceSubmissionWindow task is closed at the correct time based on the docket and whether it has an associated hearing --- .../tasks/evidence_submission_window_task.rb | 40 +++++- .../appeal_status_api_decorator_spec.rb | 4 + .../assign_hearing_disposition_task_spec.rb | 2 +- .../evidence_submission_window_task_spec.rb | 126 +++++++++++++----- 4 files changed, 132 insertions(+), 40 deletions(-) diff --git a/app/models/tasks/evidence_submission_window_task.rb b/app/models/tasks/evidence_submission_window_task.rb index 01903313575..a43def7ff66 100644 --- a/app/models/tasks/evidence_submission_window_task.rb +++ b/app/models/tasks/evidence_submission_window_task.rb @@ -14,10 +14,21 @@ def when_timer_ends update!(status: :completed) end + # Determines when the ESW task should be expired def timer_ends_at - from_date = hearing.hearing_day&.scheduled_for if hearing.present? - from_date ||= appeal.receipt_date + # from_date should be appeal receipt date if the appeal is in the ESW docket + from_date = appeal.receipt_date if appeal.evidence_submission_docket? + # ...or from_date should be the date the hearing was scheduled if a hearing is present + from_date ||= hearing.hearing_day&.scheduled_for if hearing.present? + + # ...or if no hearing is present, from_date should end when the hearing task was cancelled + from_date ||= cancelled_schedule_hearing_task&.closed_at + + # if from_date is still nil, fall back to when this task was created + from_date = ensure_from_date_set(from_date) + + # Add 90 days to the timer based on the date above from_date + 90.days end @@ -30,4 +41,29 @@ def hearing def set_assignee self.assigned_to ||= MailTeam.singleton end + + def ensure_from_date_set(from_date) + if from_date.blank? && open_schedule_hearing_task.blank? + msg = "EvidenceSubmissionWindowTask #{id} on Appeal #{appeal.id} was unable to calculate " \ + "timer_ends_at. The task's parent HearingTask has no child ScheduleHearingTask. This is " \ + "an unexpected state and may indicate that something is wrong." + Raven.capture_message(msg) + end + + from_date ||= created_at || Time.zone.now + + from_date + end + + def open_schedule_hearing_task + parent.children.open.find_by(type: ScheduleHearingTask.name) + end + + def cancelled_schedule_hearing_task + # Get the schedule hearing task + parent.children.find_by( + type: ScheduleHearingTask.name, + status: Constants.TASK_STATUSES.cancelled + ) + end end diff --git a/spec/decorators/appeal_status_api_decorator_spec.rb b/spec/decorators/appeal_status_api_decorator_spec.rb index 1c28fc8d83d..afa5bd307a2 100644 --- a/spec/decorators/appeal_status_api_decorator_spec.rb +++ b/spec/decorators/appeal_status_api_decorator_spec.rb @@ -332,6 +332,10 @@ create(:evidence_submission_window_task, :in_progress, appeal: appeal, assigned_to: Bva.singleton) end + before do + appeal.update(docket_type: Constants.AMA_DOCKETS.evidence_submission) + end + it "has an evidentiary_period alert" do expect(subject.count).to eq(1) expect(subject[0][:type]).to eq("evidentiary_period") diff --git a/spec/models/tasks/assign_hearing_disposition_task_spec.rb b/spec/models/tasks/assign_hearing_disposition_task_spec.rb index 03f2d96d6bb..627e7142aa3 100644 --- a/spec/models/tasks/assign_hearing_disposition_task_spec.rb +++ b/spec/models/tasks/assign_hearing_disposition_task_spec.rb @@ -227,7 +227,7 @@ context "disposition updates" do let(:disposition) { nil } - let(:appeal) { create(:appeal) } + let(:appeal) { create(:appeal, docket_type: Constants.AMA_DOCKETS.hearing) } let(:root_task) { create(:root_task, appeal: appeal) } let(:distribution_task) { create(:distribution_task, parent: root_task) } let(:hearing_task) { create(:hearing_task, parent: distribution_task) } diff --git a/spec/models/tasks/evidence_submission_window_task_spec.rb b/spec/models/tasks/evidence_submission_window_task_spec.rb index 84ee45a0355..52aeaaaa332 100644 --- a/spec/models/tasks/evidence_submission_window_task_spec.rb +++ b/spec/models/tasks/evidence_submission_window_task_spec.rb @@ -4,13 +4,14 @@ let(:participant_id_with_pva) { "000000" } let(:participant_id_with_no_vso) { "11111" } let!(:receipt_date) { 2.days.ago } + let(:docket_type) { Constants.AMA_DOCKETS.evidence_submission } let!(:appeal) do - create(:appeal, docket_type: Constants.AMA_DOCKETS.evidence_submission, receipt_date: receipt_date, claimants: [ + create(:appeal, docket_type: docket_type, receipt_date: receipt_date, claimants: [ create(:claimant, participant_id: participant_id_with_pva) ]) end let!(:appeal_no_vso) do - create(:appeal, docket_type: Constants.AMA_DOCKETS.evidence_submission, claimants: [ + create(:appeal, docket_type: docket_type, claimants: [ create(:claimant, participant_id: participant_id_with_no_vso) ]) end @@ -53,14 +54,14 @@ end context "timer_delay" do - context "parent is not a AssignHearingDispositionTask" do + context "hearing is in the evidence submission docket" do before { InitialTasksFactory.new(appeal).create_root_and_sub_tasks! } let(:task) do appeal.tasks.last end - it "is marked as complete and vso tasks are created in 90 days" do + it "is marked as complete and vso tasks are created in 90 days from receipt date" do TaskTimerJob.perform_now expect(task.reload.status).to eq("assigned") @@ -71,48 +72,99 @@ end end - context "parent is a AssignHearingDispositionTask and there is a held hearing" do + context "appeal is in the hearing docket" do let(:root_task) { create(:root_task, appeal: appeal) } let(:hearing_task) { create(:hearing_task, parent: root_task) } - let(:hearing_day) { create(:hearing_day, scheduled_for: appeal.receipt_date + 15.days) } - let(:hearing) do - create( - :hearing, - appeal: appeal, - disposition: Constants.HEARING_DISPOSITION_TYPES.held, - hearing_day: hearing_day - ) - end - let!(:hearing_task_association) do - create( - :hearing_task_association, - hearing: hearing, - hearing_task: hearing_task - ) - end - let!(:parent) do - create( - :assign_hearing_disposition_task, - :in_progress, - parent: hearing_task - ) - end - let!(:task) do - EvidenceSubmissionWindowTask.create!(appeal: appeal, assigned_to: Bva.singleton, parent: parent) - end + let(:docket_type) { Constants.AMA_DOCKETS.hearing } - it "sets the timer to end 90 days after the hearing day" do - TaskTimerJob.perform_now - expect(task.reload.status).to eq("assigned") + context "parent is a AssignHearingDispositionTask and there is a held hearing" do + let(:root_task) { create(:root_task, appeal: appeal) } + let(:hearing_task) { create(:hearing_task, parent: root_task) } + let(:hearing_day) { create(:hearing_day, scheduled_for: appeal.receipt_date + 15.days) } + let(:hearing) do + create( + :hearing, + appeal: appeal, + disposition: Constants.HEARING_DISPOSITION_TYPES.held, + hearing_day: hearing_day + ) + end + let!(:hearing_task_association) do + create( + :hearing_task_association, + hearing: hearing, + hearing_task: hearing_task + ) + end + let!(:parent) do + create( + :assign_hearing_disposition_task, + :in_progress, + parent: hearing_task + ) + end + let!(:task) do + EvidenceSubmissionWindowTask.create!(appeal: appeal, assigned_to: Bva.singleton, parent: parent) + end - Timecop.travel(receipt_date + 90.days) do + it "sets the timer to end 90 days after the hearing day", :aggregate_failures do TaskTimerJob.perform_now expect(task.reload.status).to eq("assigned") + + Timecop.travel(receipt_date + 90.days) do + TaskTimerJob.perform_now + expect(task.reload.status).to eq("assigned") + end + + Timecop.travel(hearing_day.scheduled_for + 90.days) do + TaskTimerJob.perform_now + expect(task.reload.status).to eq("completed") + end + end + end + + context "hearing is not in the evidences submission docket and the hearing request is withdrawn" do + let!(:schedule_hearing_task) do + create( + :schedule_hearing_task, + :cancelled, + parent: hearing_task, + appeal: appeal + ) + end + let!(:task) do + EvidenceSubmissionWindowTask.create!(appeal: appeal, assigned_to: Bva.singleton, parent: hearing_task) end - Timecop.travel(hearing_day.scheduled_for + 90.days) do + it "sets the timer to end 90 days after the hearing request is withdrawn" do TaskTimerJob.perform_now - expect(task.reload.status).to eq("completed") + expect(task.reload.status).to eq("assigned") + + Timecop.travel(receipt_date + 90.days) do + TaskTimerJob.perform_now + expect(task.reload.status).to eq("assigned") + end + + Timecop.travel(schedule_hearing_task.closed_at + 91.days) do + TaskTimerJob.perform_now + expect(task.reload.status).to eq("completed") + end + end + end + + context "hearing is not in the evidences submission docket" \ + "and the hearing request is withdrawn with no schedule hearing task" do + it "sends a message to Raven and sets the time to end 90 days after the task was created" do + expect(Raven).to receive(:capture_message).once + + esw_task = EvidenceSubmissionWindowTask.create!( + appeal: appeal, + assigned_to: Bva.singleton, + parent: hearing_task + ) + + task_timer = TaskTimer.find_by(task_id: esw_task.id) + expect(task_timer.submitted_at).to be_within(10.seconds).of(esw_task.created_at + 90.days) end end end