From 4904fe6eaf84908e14a27f7c47c02bee9968f920 Mon Sep 17 00:00:00 2001 From: = Date: Mon, 7 Oct 2024 16:32:41 -0400 Subject: [PATCH 01/21] Initial commit that alters the business line logic to accept a date filter for the tasks completed at column and logic to support and filter by it via the database query. --- app/models/organizations/business_line.rb | 58 +++++++++++++++++++ app/models/organizations/vha_business_line.rb | 2 +- 2 files changed, 59 insertions(+), 1 deletion(-) diff --git a/app/models/organizations/business_line.rb b/app/models/organizations/business_line.rb index 5b43066bce2..d955928e42a 100644 --- a/app/models/organizations/business_line.rb +++ b/app/models/organizations/business_line.rb @@ -137,6 +137,7 @@ def build_query .from(combined_decision_review_tasks_query) .includes(*decision_review_task_includes) .where(task_filter_predicate(query_params[:filters])) + .where(closed_at_filter_predicate(query_params[:filters])) .order(order_clause) end @@ -834,6 +835,63 @@ def locate_issue_type_filter(filters) def where_clause_from_array(table_class, column, values_array) table_class.arel_table[column].in(values_array) end + + def closed_at_filter_predicate(filters) + return "" if filters.nil? + + closed_at_filter = locate_closed_at_filter(filters) + + return "" unless closed_at_filter + + # ex: "val"=> val=[before,2024-09-08,] + closed_at_params = closed_at_filter["val"].first.split(",") + + build_closed_at_filter_predicate(closed_at_params) || "" + end + + def locate_closed_at_filter(filters) + parsed_filters = parse_filters(filters) + + parsed_filters.find do |filter| + filter["col"].include?("completedDateColumn") + end + end + + def build_closed_at_filter_predicate(closed_at_params) + return "" if closed_at_params.blank? + + mode, start_date, end_date = closed_at_params + operator = date_filter_mode_to_operator(mode) + + date_filters = { + ">" => -> { start_date ? "tasks.closed_at::date > '#{start_date}'::date" : "" }, + "<" => -> { start_date ? "tasks.closed_at::date < '#{start_date}'::date" : "" }, + "=" => -> { start_date ? "tasks.closed_at::date = '#{start_date}'::date" : "" }, + "between" => lambda { + end_date ? "tasks.closed_at::date BETWEEN '#{start_date}'::date AND '#{end_date}'::date" : "" + }, + "last_7_days" => -> { { closed_at: 1.week.ago..Time.zone.now } }, + "last_30_days" => -> { { closed_at: 30.days.ago..Time.zone.now } }, + "last_365_days" => -> { { closed_at: 365.days.ago..Time.zone.now } } + } + + date_filters.fetch(operator, lambda { + Rails.logger.error("Unsupported mode **#{operator}** used for closed at date filtering") + "" + }).call + end + + def date_filter_mode_to_operator(mode) + { + "between" => "between", + "after" => ">", + "before" => "<", + "on" => "=", + "last_7_days" => "last_7_days", + "last_30_days" => "last_30_days", + "last_365_days" => "last_365_days" + }[mode] + end end # rubocop:enable Metrics/ClassLength end diff --git a/app/models/organizations/vha_business_line.rb b/app/models/organizations/vha_business_line.rb index f7d0062b0ed..376e3f5de84 100644 --- a/app/models/organizations/vha_business_line.rb +++ b/app/models/organizations/vha_business_line.rb @@ -13,7 +13,7 @@ def tasks_query_type { incomplete: "on_hold", in_progress: "active", - completed: "recently_completed", + completed: "completed", pending: "active" } end From bb81840a34e83d02d2ed42ee48872562c14e1504 Mon Sep 17 00:00:00 2001 From: = Date: Mon, 7 Oct 2024 22:55:54 -0400 Subject: [PATCH 02/21] Added new tests for the tasksClosedAt filter to the business line spec. Adjusted the between lambda filter to work for either ordering of the start date or end date as the first chronological date in the query. Optimized the business line spec by swapping to before all loops and instance variables to shorten the time it takes to run the test. --- app/models/organizations/business_line.rb | 2 + spec/models/business_line_spec.rb | 452 ++++++++++++++++------ 2 files changed, 328 insertions(+), 126 deletions(-) diff --git a/app/models/organizations/business_line.rb b/app/models/organizations/business_line.rb index d955928e42a..376675629c4 100644 --- a/app/models/organizations/business_line.rb +++ b/app/models/organizations/business_line.rb @@ -868,6 +868,8 @@ def build_closed_at_filter_predicate(closed_at_params) "<" => -> { start_date ? "tasks.closed_at::date < '#{start_date}'::date" : "" }, "=" => -> { start_date ? "tasks.closed_at::date = '#{start_date}'::date" : "" }, "between" => lambda { + # Ensure the dates are sorted correctly so either ordering works e.g. start > end or end > start + start_date, end_date = [start_date, end_date].map(&:to_date).sort end_date ? "tasks.closed_at::date BETWEEN '#{start_date}'::date AND '#{end_date}'::date" : "" }, "last_7_days" => -> { { closed_at: 1.week.ago..Time.zone.now } }, diff --git a/spec/models/business_line_spec.rb b/spec/models/business_line_spec.rb index f9e382d4742..0d3eb91a68e 100644 --- a/spec/models/business_line_spec.rb +++ b/spec/models/business_line_spec.rb @@ -115,43 +115,41 @@ end describe ".in_progress_tasks" do - let!(:hlr_tasks_on_active_decision_reviews) do - create_list(:higher_level_review_vha_task, 5, assigned_to: business_line) - end + before(:all) do + @business_line = VhaBusinessLine.singleton + @veteran = create(:veteran) - let!(:sc_tasks_on_active_decision_reviews) do - create_list(:supplemental_claim_vha_task, 5, assigned_to: business_line) - end + @hlr_tasks_on_active_decision_reviews = + create_list(:higher_level_review_vha_task, 5, assigned_to: @business_line) - let!(:decision_review_tasks_on_inactive_decision_reviews) do - create_list(:higher_level_review_task, 5, assigned_to: business_line) - end + @sc_tasks_on_active_decision_reviews = + create_list(:supplemental_claim_vha_task, 5, assigned_to: @business_line) + + @decision_review_tasks_on_inactive_decision_reviews = + create_list(:higher_level_review_task, 5, assigned_to: @business_line) - let!(:board_grant_effectuation_tasks) do - tasks = create_list(:board_grant_effectuation_task, 5, assigned_to: business_line) + @board_grant_effectuation_tasks = + create_list(:board_grant_effectuation_task, 5, assigned_to: @business_line) - tasks.each do |task| + @board_grant_effectuation_tasks.each do |task| create( :request_issue, :nonrating, decision_review: task.appeal, - benefit_type: business_line.url, + benefit_type: @business_line.url, closed_at: Time.zone.now, closed_status: "decided" ) end - tasks - end - - let!(:veteran_record_request_on_active_appeals) do - add_veteran_and_request_issues_to_decision_reviews( - create_list(:veteran_record_request_task, 5, assigned_to: business_line) + @veteran_record_request_on_active_appeals = add_veteran_and_request_issues_to_decision_reviews( + create_list(:veteran_record_request_task, 5, assigned_to: @business_line), + @veteran, + @business_line ) - end - let!(:veteran_record_request_on_inactive_appeals) do - create_list(:veteran_record_request_task, 5, assigned_to: business_line) + @veteran_record_request_on_inactive_appeals = + create_list(:veteran_record_request_task, 5, assigned_to: @business_line) end subject { business_line.in_progress_tasks(filters: task_filters) } @@ -167,10 +165,10 @@ it "All tasks associated with active decision reviews and BoardGrantEffectuationTasks are included" do expect(subject.size).to eq 20 expect(subject.map(&:id)).to match_array( - (veteran_record_request_on_active_appeals + - board_grant_effectuation_tasks + - hlr_tasks_on_active_decision_reviews + - sc_tasks_on_active_decision_reviews + (@veteran_record_request_on_active_appeals + + @board_grant_effectuation_tasks + + @hlr_tasks_on_active_decision_reviews + + @sc_tasks_on_active_decision_reviews ).pluck(:id) ) end @@ -184,9 +182,9 @@ it "All tasks associated with active decision reviews are included, but not BoardGrantEffectuationTasks" do expect(subject.size).to eq 15 expect(subject.map(&:id)).to match_array( - (veteran_record_request_on_active_appeals + - hlr_tasks_on_active_decision_reviews + - sc_tasks_on_active_decision_reviews + (@veteran_record_request_on_active_appeals + + @hlr_tasks_on_active_decision_reviews + + @sc_tasks_on_active_decision_reviews ).pluck(:id) ) end @@ -194,22 +192,18 @@ end describe ".incomplete_tasks" do - let!(:hlr_tasks_on_active_decision_reviews) do - tasks = create_list(:higher_level_review_vha_task, 5, assigned_to: business_line) - tasks.each(&:on_hold!) - tasks - end + before(:all) do + @business_line = VhaBusinessLine.singleton + @veteran = create(:veteran) - let!(:sc_tasks_on_active_decision_reviews) do - tasks = create_list(:supplemental_claim_vha_task, 5, assigned_to: business_line) - tasks.each(&:on_hold!) - tasks - end + @hlr_tasks_on_active_decision_reviews = + create_list(:higher_level_review_vha_task, 5, assigned_to: @business_line).each(&:on_hold!) + + @sc_tasks_on_active_decision_reviews = + create_list(:supplemental_claim_vha_task, 5, assigned_to: @business_line).each(&:on_hold!) - let!(:decision_review_tasks_on_inactive_decision_reviews) do - tasks = create_list(:higher_level_review_task, 5, assigned_to: business_line) - tasks.each(&:on_hold!) - tasks + @decision_review_tasks_on_inactive_decision_reviews = + create_list(:higher_level_review_task, 5, assigned_to: @business_line).each(&:on_hold!) end subject { business_line.incomplete_tasks(filters: task_filters) } @@ -222,8 +216,8 @@ it "All tasks associated with active decision reviews and BoardGrantEffectuationTasks are included" do expect(subject.size).to eq 10 expect(subject.map(&:id)).to match_array( - (hlr_tasks_on_active_decision_reviews + - sc_tasks_on_active_decision_reviews + (@hlr_tasks_on_active_decision_reviews + + @sc_tasks_on_active_decision_reviews ).pluck(:id) ) end @@ -231,59 +225,64 @@ end describe ".completed_tasks" do - let!(:open_hlr_tasks) do - add_veteran_and_request_issues_to_decision_reviews( - create_list(:higher_level_review_task, 5, assigned_to: business_line) + before(:all) do + @business_line = VhaBusinessLine.singleton + @veteran = create(:veteran) + + @open_hlr_tasks = add_veteran_and_request_issues_to_decision_reviews( + create_list(:higher_level_review_task, 5, assigned_to: @business_line), + @veteran, + @business_line ) - end - let!(:completed_hlr_tasks) do - add_veteran_and_request_issues_to_decision_reviews( + @completed_hlr_tasks = add_veteran_and_request_issues_to_decision_reviews( complete_all_tasks( - create_list(:higher_level_review_task, 5, assigned_to: business_line) - ) + create_list(:higher_level_review_task, 5, assigned_to: @business_line) + ), + @veteran, + @business_line ) - end - let!(:open_sc_tasks) do - add_veteran_and_request_issues_to_decision_reviews( - create_list(:supplemental_claim_task, 5, assigned_to: business_line) + @open_sc_tasks = add_veteran_and_request_issues_to_decision_reviews( + create_list(:supplemental_claim_task, 5, assigned_to: @business_line), + @veteran, + @business_line ) - end - let!(:completed_sc_tasks) do - add_veteran_and_request_issues_to_decision_reviews( + @completed_sc_tasks = add_veteran_and_request_issues_to_decision_reviews( complete_all_tasks( - create_list(:supplemental_claim_task, 5, assigned_to: business_line) - ) + create_list(:supplemental_claim_task, 5, assigned_to: @business_line) + ), + @veteran, + @business_line ) - end - let!(:open_board_grant_effectuation_tasks) do - add_veteran_and_request_issues_to_decision_reviews( - create_list(:board_grant_effectuation_task, 5, assigned_to: business_line) + @open_board_grant_effectuation_tasks = add_veteran_and_request_issues_to_decision_reviews( + create_list(:board_grant_effectuation_task, 5, assigned_to: @business_line), + @veteran, + @business_line ) - end - let!(:completed_board_grant_effectuation_tasks) do - add_veteran_and_request_issues_to_decision_reviews( + @completed_board_grant_effectuation_tasks = add_veteran_and_request_issues_to_decision_reviews( complete_all_tasks( - create_list(:board_grant_effectuation_task, 5, assigned_to: business_line) - ) + create_list(:board_grant_effectuation_task, 5, assigned_to: @business_line) + ), + @veteran, + @business_line ) - end - let!(:open_veteran_record_requests) do - add_veteran_and_request_issues_to_decision_reviews( - create_list(:veteran_record_request_task, 5, assigned_to: business_line) + @open_veteran_record_request = add_veteran_and_request_issues_to_decision_reviews( + create_list(:veteran_record_request_task, 5, assigned_to: @business_line), + @veteran, + @business_line ) - end - let!(:completed_veteran_record_requests) do - add_veteran_and_request_issues_to_decision_reviews( + @completed_veteran_record_requests = add_veteran_and_request_issues_to_decision_reviews( complete_all_tasks( - create_list(:veteran_record_request_task, 5, assigned_to: business_line) - ) + create_list(:veteran_record_request_task, 5, assigned_to: @business_line) + ), + @veteran, + @business_line ) end @@ -297,14 +296,218 @@ it "All completed tasks are included in results" do expect(subject.size).to eq 20 expect(subject.map(&:id)).to match_array( - (completed_hlr_tasks + - completed_sc_tasks + - completed_board_grant_effectuation_tasks + - completed_veteran_record_requests + (@completed_hlr_tasks + + @completed_sc_tasks + + @completed_board_grant_effectuation_tasks + + @completed_veteran_record_requests ).pluck(:id) ) end end + + context "With closed at filters" do + context "with a before filter" do + # Create some closed tasks that should match before the filter + let!(:tasks_for_closed_at_filter) do + tasks = add_veteran_and_request_issues_to_decision_reviews( + complete_all_tasks( + create_list(:supplemental_claim_task, 5, assigned_to: @business_line) + ), + @veteran, + @business_line + ) + tasks.each do |task| + task.closed_at = 5.days.ago + task.save + end + tasks + end + + let(:task_filters) do + ["col=completedDateColumn&val=before,#{3.days.ago.strftime('%Y-%m-%d')},"] + end + + it "should filter the tasks for a date before the closed at date" do + expect(subject.size).to eq 5 + expect(subject.map(&:id)).to match_array(tasks_for_closed_at_filter.pluck(:id)) + end + end + + context "with an after filter" do + # Create some closed tasks that should not match the after filter + let!(:tasks_for_closed_at_filter) do + tasks = add_veteran_and_request_issues_to_decision_reviews( + complete_all_tasks( + create_list(:supplemental_claim_task, 5, assigned_to: @business_line) + ), + @veteran, + @business_line + ) + tasks.each do |task| + task.closed_at = 5.days.ago + task.save + end + tasks + end + + let(:task_filters) do + ["col=completedDateColumn&val=after,#{3.days.ago.strftime('%Y-%m-%d')},"] + end + + it "should filter the tasks for a date after the closed at date" do + expect(subject.size).to eq 20 + expect(subject.map(&:id)).to match_array( + (@completed_hlr_tasks + + @completed_sc_tasks + + @completed_board_grant_effectuation_tasks + + @completed_veteran_record_requests + ).pluck(:id) + ) + end + end + + context "with a between filter" do + # Create some closed tasks that should match the between filter + let!(:tasks_for_closed_at_filter) do + tasks = add_veteran_and_request_issues_to_decision_reviews( + complete_all_tasks( + create_list(:supplemental_claim_task, 3, assigned_to: @business_line) + ), + @veteran, + @business_line + ) + # Set two tasks to fit into the between range + tasks[0].closed_at = 5.days.ago + tasks[1].closed_at = 1.day.ago + tasks[2].closed_at = 8.days.ago + tasks[0].save + tasks[1].save + tasks[2].save + tasks + end + + let(:task_filters) do + start_date = 3.days.ago.strftime("%Y-%m-%d") + end_date = 10.days.ago.strftime("%Y-%m-%d") + ["col=completedDateColumn&val=between,#{start_date},#{end_date}"] + end + + it "should filter the tasks for a closed at date between two dates" do + expect(subject.size).to eq 2 + expect(subject.map(&:id)).to match_array( + [ + tasks_for_closed_at_filter[0].id, + tasks_for_closed_at_filter[2].id + ] + ) + end + end + + context "with last 7 days filter" do + # Create some closed tasks that should not match the last 7 days filter + let!(:tasks_for_closed_at_filter) do + tasks = add_veteran_and_request_issues_to_decision_reviews( + complete_all_tasks( + create_list(:supplemental_claim_task, 3, assigned_to: @business_line) + ), + @veteran, + @business_line + ) + tasks.each do |task| + task.closed_at = 10.days.ago + task.save + end + tasks + end + + let(:task_filters) do + ["col=completedDateColumn&val=last_7_days,,"] + end + + it "should filter the tasks for a closed at in the last 7 days" do + expect(subject.size).to eq 20 + expect(subject.map(&:id)).to match_array( + (@completed_hlr_tasks + + @completed_sc_tasks + + @completed_board_grant_effectuation_tasks + + @completed_veteran_record_requests + ).pluck(:id) + ) + end + end + + context "with last 30 days filter" do + # Create some closed tasks that should match the last 30 days filter and one that does not + let!(:tasks_for_closed_at_filter) do + tasks = add_veteran_and_request_issues_to_decision_reviews( + complete_all_tasks( + create_list(:supplemental_claim_task, 3, assigned_to: @business_line) + ), + @veteran, + @business_line + ) + tasks.first(2) do |task| + task.closed_at = 10.days.ago + task.save + end + tasks.last.closed_at = 31.days.ago + tasks.last.save + tasks + end + + let(:task_filters) do + ["col=completedDateColumn&val=last_30_days,,"] + end + + it "should filter the tasks for a closed at in the last 30 days" do + expect(subject.size).to eq 22 + expect(subject.map(&:id)).to match_array( + (@completed_hlr_tasks + + @completed_sc_tasks + + @completed_board_grant_effectuation_tasks + + @completed_veteran_record_requests + + tasks_for_closed_at_filter.first(2) + ).pluck(:id) + ) + end + end + + context "with last 365 days filter" do + # Create some closed tasks that should match the last 365 days filter and one that does not + let!(:tasks_for_closed_at_filter) do + tasks = add_veteran_and_request_issues_to_decision_reviews( + complete_all_tasks( + create_list(:supplemental_claim_task, 3, assigned_to: @business_line) + ), + @veteran, + @business_line + ) + tasks.first(2) do |task| + task.closed_at = 200.days.ago + task.save + end + tasks.last.closed_at = 400.days.ago + tasks.last.save + tasks + end + + let(:task_filters) do + ["col=completedDateColumn&val=last_365_days,,"] + end + + it "should filter the tasks for a closed at in the last 365 days" do + expect(subject.size).to eq 22 + expect(subject.map(&:id)).to match_array( + (@completed_hlr_tasks + + @completed_sc_tasks + + @completed_board_grant_effectuation_tasks + + @completed_veteran_record_requests + + tasks_for_closed_at_filter.first(2) + ).pluck(:id) + ) + end + end + end end describe ".pending_tasks" do @@ -385,54 +588,51 @@ end describe ".in_progress_tasks" do - let(:current_time) { Time.zone.now } - let!(:hlr_tasks_on_active_decision_reviews) do - create_list(:higher_level_review_vha_task, 5, assigned_to: business_line) - end + before(:all) do + @current_time = Time.zone.now + # Use a different url and name since the let variable can't be used in before all setup + @business_line = create(:business_line, name: "NONCOMPORG2", url: "nco2") - let!(:sc_tasks_on_active_decision_reviews) do - create_list(:supplemental_claim_vha_task, 5, assigned_to: business_line) - end + @veteran = create(:veteran) - # Set some on hold tasks as well - let!(:on_hold_sc_tasks_on_active_decision_reviews) do - tasks = create_list(:supplemental_claim_vha_task, 5, assigned_to: business_line) - tasks.each(&:on_hold!) - tasks - end + @hlr_tasks_on_active_decision_reviews = + create_list(:higher_level_review_vha_task, 5, assigned_to: @business_line) - let!(:decision_review_tasks_on_inactive_decision_reviews) do - create_list(:higher_level_review_task, 5, assigned_to: business_line) - end + @sc_tasks_on_active_decision_reviews = + create_list(:supplemental_claim_vha_task, 5, assigned_to: @business_line) + + @on_hold_sc_tasks_on_active_decision_reviews = + create_list(:supplemental_claim_vha_task, 5, assigned_to: @business_line).each(&:on_hold!) - let!(:board_grant_effectuation_tasks) do - tasks = create_list(:board_grant_effectuation_task, 5, assigned_to: business_line) + @decision_review_tasks_on_inactive_decision_reviews = + create_list(:higher_level_review_task, 5, assigned_to: @business_line) - tasks.each do |task| + @board_grant_effectuation_tasks = + create_list(:board_grant_effectuation_task, 5, assigned_to: @business_line) + + @board_grant_effectuation_tasks.each do |task| create( :request_issue, :nonrating, decision_review: task.appeal, - benefit_type: business_line.url, - closed_at: current_time, + benefit_type: @business_line.url, + closed_at: @current_time, closed_status: "decided" ) end - tasks - end - - let!(:veteran_record_request_on_active_appeals) do - add_veteran_and_request_issues_to_decision_reviews( - create_list(:veteran_record_request_task, 5, assigned_to: business_line) - ) - end + @veteran_record_request_on_active_appeals = + add_veteran_and_request_issues_to_decision_reviews( + create_list(:veteran_record_request_task, 5, assigned_to: @business_line), + @veteran, + @business_line + ) - let!(:veteran_record_request_on_inactive_appeals) do - create_list(:veteran_record_request_task, 5, assigned_to: business_line) + @veteran_record_request_on_inactive_appeals = + create_list(:veteran_record_request_task, 5, assigned_to: @business_line) end - subject { business_line.in_progress_tasks(filters: task_filters) } + subject { @business_line.in_progress_tasks(filters: task_filters) } include_examples "task filtration" @@ -445,11 +645,11 @@ it "All tasks associated with active decision reviews and BoardGrantEffectuationTasks are included" do expect(subject.size).to eq 25 expect(subject.map(&:id)).to match_array( - (veteran_record_request_on_active_appeals + - board_grant_effectuation_tasks + - hlr_tasks_on_active_decision_reviews + - sc_tasks_on_active_decision_reviews + - on_hold_sc_tasks_on_active_decision_reviews + (@veteran_record_request_on_active_appeals + + @board_grant_effectuation_tasks + + @hlr_tasks_on_active_decision_reviews + + @sc_tasks_on_active_decision_reviews + + @on_hold_sc_tasks_on_active_decision_reviews ).pluck(:id) ) end @@ -463,10 +663,10 @@ it "All tasks associated with active decision reviews are included, but not BoardGrantEffectuationTasks" do expect(subject.size).to eq 20 expect(subject.map(&:id)).to match_array( - (veteran_record_request_on_active_appeals + - hlr_tasks_on_active_decision_reviews + - sc_tasks_on_active_decision_reviews + - on_hold_sc_tasks_on_active_decision_reviews + (@veteran_record_request_on_active_appeals + + @hlr_tasks_on_active_decision_reviews + + @sc_tasks_on_active_decision_reviews + + @on_hold_sc_tasks_on_active_decision_reviews ).pluck(:id) ) end @@ -913,7 +1113,7 @@ end end - def add_veteran_and_request_issues_to_decision_reviews(tasks) + def add_veteran_and_request_issues_to_decision_reviews(tasks, veteran, business_line) tasks.each do |task| task.appeal.update!(veteran_file_number: veteran.file_number) rand(1..4).times do From e1c84ce50da17926ad50754a0947de06891fb8e6 Mon Sep 17 00:00:00 2001 From: = Date: Tue, 8 Oct 2024 11:33:15 -0400 Subject: [PATCH 03/21] Rewrote a bit more of the business line spec to speed it up via one time test data setup rather than for each test. --- spec/models/business_line_spec.rb | 259 +++++++++++++++++------------- 1 file changed, 145 insertions(+), 114 deletions(-) diff --git a/spec/models/business_line_spec.rb b/spec/models/business_line_spec.rb index 0d3eb91a68e..74c02d323b4 100644 --- a/spec/models/business_line_spec.rb +++ b/spec/models/business_line_spec.rb @@ -511,45 +511,76 @@ end describe ".pending_tasks" do - let!(:requestor) { create(:user) } - let!(:decider) { create(:user) } - let!(:hlr_pending_tasks) do - create_list(:issue_modification_request, - 3, - :with_higher_level_review, - status: "assigned", - requestor: requestor, - decider: decider) - end - - let!(:sc_pending_tasks) do - create_list(:issue_modification_request, - 3, - :with_supplemental_claim, - status: "assigned", - requestor: requestor, - decider: decider) - end - - let!(:extra_modification_request) do - create(:issue_modification_request, - :with_higher_level_review, - status: "assigned", - requestor: requestor, - decider: decider) - end - - let(:extra_decision_review) do - extra_modification_request.decision_review - end - - let!(:extra_modification_request2) do - create(:issue_modification_request, - status: "assigned", - requestor: requestor, - decider: decider, - decision_review: extra_decision_review) + before(:all) do + @requestor = create(:user) + @decider = create(:user) + @hlr_pending_tasks = create_list(:issue_modification_request, + 3, + :with_higher_level_review, + status: "assigned", + requestor: @requestor, + decider: @decider) + + @sc_pending_tasks = create_list(:issue_modification_request, + 3, + :with_supplemental_claim, + status: "assigned", + requestor: @requestor, + decider: @decider) + + @extra_modification_request = create(:issue_modification_request, + :with_higher_level_review, + status: "assigned", + requestor: @requestor, + decider: @decider) + + @extra_decision_review = @extra_modification_request.decision_review + + @extra_modification_request2 = create(:issue_modification_request, + status: "assigned", + requestor: @requestor, + decider: @decider, + decision_review: @extra_decision_review) end + # let!(:requestor) { create(:user) } + # let!(:decider) { create(:user) } + # let!(:hlr_pending_tasks) do + # create_list(:issue_modification_request, + # 3, + # :with_higher_level_review, + # status: "assigned", + # requestor: requestor, + # decider: decider) + # end + + # let!(:sc_pending_tasks) do + # create_list(:issue_modification_request, + # 3, + # :with_supplemental_claim, + # status: "assigned", + # requestor: requestor, + # decider: decider) + # end + + # let!(:extra_modification_request) do + # create(:issue_modification_request, + # :with_higher_level_review, + # status: "assigned", + # requestor: requestor, + # decider: decider) + # end + + # let(:extra_decision_review) do + # extra_modification_request.decision_review + # end + + # let!(:extra_modification_request2) do + # create(:issue_modification_request, + # status: "assigned", + # requestor: requestor, + # decider: decider, + # decision_review: extra_decision_review) + # end subject { business_line.pending_tasks(filters: task_filters) } @@ -562,12 +593,12 @@ expect(subject.size).to eq(7) expect(subject.map(&:appeal_id)).to match_array( - (hlr_pending_tasks + sc_pending_tasks + [extra_modification_request]).pluck(:decision_review_id) + (@hlr_pending_tasks + @sc_pending_tasks + [@extra_modification_request]).pluck(:decision_review_id) ) # Verify the issue count and issue modfication count is correct for the extra task extra_task = subject.find do |task| - task.appeal_id == extra_modification_request.decision_review_id && + task.appeal_id == @extra_modification_request.decision_review_id && task.appeal_type == "HigherLevelReview" end expect(extra_task[:issue_count]).to eq(1) @@ -676,36 +707,23 @@ describe ".change_history_rows" do let(:change_history_filters) { {} } - let!(:hlr_task) { create(:higher_level_review_vha_task_with_decision) } - let!(:hlr_task2) { create(:higher_level_review_vha_task) } - let!(:sc_task) do - create(:supplemental_claim_vha_task, - appeal: create(:supplemental_claim, - :with_vha_issue, - :with_intake, - benefit_type: "vha", - claimant_type: :dependent_claimant)) - end - let(:decision_issue) { create(:decision_issue, disposition: "denied", benefit_type: hlr_task.appeal.benefit_type) } - let(:intake_user) { create(:user, full_name: "Alexander Dewitt", css_id: "ALEXVHA", station_id: "103") } - let(:decision_user) { create(:user, full_name: "Gaius Baelsar", css_id: "GAIUSVHA", station_id: "104") } # Reusable expectations let(:hlr_task_1_ri_1_expectation) do a_hash_including( "nonrating_issue_category" => "Caregiver | Other", "nonrating_issue_description" => "VHA - Caregiver ", - "task_id" => hlr_task.id, - "veteran_file_number" => hlr_task.appeal.veteran_file_number, - "intake_user_name" => hlr_task.appeal.intake.user.full_name, - "intake_user_css_id" => hlr_task.appeal.intake.user.css_id, - "intake_user_station_id" => hlr_task.appeal.intake.user.station_id, + "task_id" => @hlr_task.id, + "veteran_file_number" => @hlr_task.appeal.veteran_file_number, + "intake_user_name" => @hlr_task.appeal.intake.user.full_name, + "intake_user_css_id" => @hlr_task.appeal.intake.user.css_id, + "intake_user_station_id" => @hlr_task.appeal.intake.user.station_id, "disposition" => "Granted", - "decision_user_name" => decision_user.full_name, - "decision_user_css_id" => decision_user.css_id, - "decision_user_station_id" => decision_user.station_id, - "claimant_name" => hlr_task.appeal.claimant.name, - "task_status" => hlr_task.status, + "decision_user_name" => @decision_user.full_name, + "decision_user_css_id" => @decision_user.css_id, + "decision_user_station_id" => @decision_user.station_id, + "claimant_name" => @hlr_task.appeal.claimant.name, + "task_status" => @hlr_task.status, "request_issue_benefit_type" => "vha", "days_waiting" => 10 ) @@ -714,17 +732,17 @@ a_hash_including( "nonrating_issue_category" => "CHAMPVA", "nonrating_issue_description" => "This is a CHAMPVA issue", - "task_id" => hlr_task.id, - "veteran_file_number" => hlr_task.appeal.veteran_file_number, - "intake_user_name" => hlr_task.appeal.intake.user.full_name, - "intake_user_css_id" => hlr_task.appeal.intake.user.css_id, - "intake_user_station_id" => hlr_task.appeal.intake.user.station_id, + "task_id" => @hlr_task.id, + "veteran_file_number" => @hlr_task.appeal.veteran_file_number, + "intake_user_name" => @hlr_task.appeal.intake.user.full_name, + "intake_user_css_id" => @hlr_task.appeal.intake.user.css_id, + "intake_user_station_id" => @hlr_task.appeal.intake.user.station_id, "disposition" => "denied", - "decision_user_name" => decision_user.full_name, - "decision_user_css_id" => decision_user.css_id, - "decision_user_station_id" => decision_user.station_id, - "claimant_name" => hlr_task.appeal.claimant.name, - "task_status" => hlr_task.status, + "decision_user_name" => @decision_user.full_name, + "decision_user_css_id" => @decision_user.css_id, + "decision_user_station_id" => @decision_user.station_id, + "claimant_name" => @hlr_task.appeal.claimant.name, + "task_status" => @hlr_task.status, "request_issue_benefit_type" => "vha", "days_waiting" => 10 ) @@ -733,17 +751,17 @@ a_hash_including( "nonrating_issue_category" => "Caregiver | Other", "nonrating_issue_description" => "VHA - Caregiver ", - "task_id" => hlr_task2.id, - "veteran_file_number" => hlr_task2.appeal.veteran_file_number, - "intake_user_name" => intake_user.full_name, - "intake_user_css_id" => intake_user.css_id, - "intake_user_station_id" => intake_user.station_id, + "task_id" => @hlr_task2.id, + "veteran_file_number" => @hlr_task2.appeal.veteran_file_number, + "intake_user_name" => @intake_user.full_name, + "intake_user_css_id" => @intake_user.css_id, + "intake_user_station_id" => @intake_user.station_id, "disposition" => nil, "decision_user_name" => nil, "decision_user_css_id" => nil, "decision_user_station_id" => nil, - "claimant_name" => hlr_task2.appeal.claimant.name, - "task_status" => hlr_task2.status, + "claimant_name" => @hlr_task2.appeal.claimant.name, + "task_status" => @hlr_task2.status, "request_issue_benefit_type" => "vha", "days_waiting" => 5 ) @@ -752,17 +770,17 @@ a_hash_including( "nonrating_issue_category" => "Camp Lejune Family Member", "nonrating_issue_description" => "This is a Camp Lejune issue", - "task_id" => hlr_task2.id, - "veteran_file_number" => hlr_task2.appeal.veteran_file_number, - "intake_user_name" => intake_user.full_name, - "intake_user_css_id" => intake_user.css_id, - "intake_user_station_id" => intake_user.station_id, + "task_id" => @hlr_task2.id, + "veteran_file_number" => @hlr_task2.appeal.veteran_file_number, + "intake_user_name" => @intake_user.full_name, + "intake_user_css_id" => @intake_user.css_id, + "intake_user_station_id" => @intake_user.station_id, "disposition" => nil, "decision_user_name" => nil, "decision_user_css_id" => nil, "decision_user_station_id" => nil, - "claimant_name" => hlr_task2.appeal.claimant.name, - "task_status" => hlr_task2.status, + "claimant_name" => @hlr_task2.appeal.claimant.name, + "task_status" => @hlr_task2.status, "request_issue_benefit_type" => "vha", "days_waiting" => 5 ) @@ -771,19 +789,19 @@ a_hash_including( "nonrating_issue_category" => "Beneficiary Travel", "nonrating_issue_description" => "VHA issue description ", - "task_id" => sc_task.id, - "veteran_file_number" => sc_task.appeal.veteran_file_number, - "intake_user_name" => sc_task.appeal.intake.user.full_name, - "intake_user_css_id" => sc_task.appeal.intake.user.css_id, - "intake_user_station_id" => sc_task.appeal.intake.user.station_id, + "task_id" => @sc_task.id, + "veteran_file_number" => @sc_task.appeal.veteran_file_number, + "intake_user_name" => @sc_task.appeal.intake.user.full_name, + "intake_user_css_id" => @sc_task.appeal.intake.user.css_id, + "intake_user_station_id" => @sc_task.appeal.intake.user.station_id, "disposition" => nil, "decision_user_name" => nil, "decision_user_css_id" => nil, "decision_user_station_id" => nil, - "claimant_name" => sc_task.appeal.claimant.name, - "task_status" => sc_task.status, + "claimant_name" => @sc_task.appeal.claimant.name, + "task_status" => @sc_task.status, "request_issue_benefit_type" => "vha", - "days_waiting" => (Time.zone.today - Date.parse(sc_task.assigned_at.iso8601)).to_i + "days_waiting" => (Time.zone.today - Date.parse(@sc_task.assigned_at.iso8601)).to_i ) end @@ -797,7 +815,20 @@ ] end - before do + before(:all) do + DatabaseCleaner.clean_with(:truncation) + + @hlr_task = create(:higher_level_review_vha_task_with_decision) + @hlr_task2 = create(:higher_level_review_vha_task) + @sc_task = create(:supplemental_claim_vha_task, appeal: create(:supplemental_claim, + :with_vha_issue, + :with_intake, + benefit_type: "vha", + claimant_type: :dependent_claimant)) + @decision_issue = create(:decision_issue, disposition: "denied", benefit_type: @hlr_task.appeal.benefit_type) + @intake_user = create(:user, full_name: "Alexander Dewitt", css_id: "ALEXVHA", station_id: "103") + @decision_user = create(:user, full_name: "Gaius Baelsar", css_id: "GAIUSVHA", station_id: "104") + issue = create(:request_issue, nonrating_issue_category: "CHAMPVA", nonrating_issue_description: "This is a CHAMPVA issue", @@ -806,34 +837,34 @@ nonrating_issue_category: "Camp Lejune Family Member", nonrating_issue_description: "This is a Camp Lejune issue", benefit_type: "vha") - hlr_task.appeal.request_issues << issue - hlr_task2.appeal.request_issues << issue2 + @hlr_task.appeal.request_issues << issue + @hlr_task2.appeal.request_issues << issue2 # Add a different intake user to the second hlr task for data differences - second_intake = hlr_task2.appeal.intake - second_intake.user = intake_user + second_intake = @hlr_task2.appeal.intake + second_intake.user = @intake_user second_intake.save # Add a couple of dispostions one here and one through the factory, to the first hlr task - decision_issue.request_issues << issue - hlr_task.appeal.decision_issues << decision_issue - hlr_task.appeal.save + @decision_issue.request_issues << issue + @hlr_task.appeal.decision_issues << @decision_issue + @hlr_task.appeal.save # Set the assigned at for days waiting filtering for hlr_task2 - hlr_task2.assigned_at = 5.days.ago - hlr_task2.save + @hlr_task2.assigned_at = 5.days.ago + @hlr_task2.save # Set up assigned at for days waiting filtering for hlr_task1 PaperTrail.request(enabled: false) do # This uses the task versions whodunnit field now instead of completed by # hlr_task.completed_by = decision_user - hlr_task.assigned_at = 10.days.ago - hlr_task.save + @hlr_task.assigned_at = 10.days.ago + @hlr_task.save end # Set the whodunnnit of the completed version status to the decision user - version = hlr_task.versions.first - version.whodunnit = decision_user.id.to_s + version = @hlr_task.versions.first + version.whodunnit = @decision_user.id.to_s version.save end @@ -848,7 +879,7 @@ context "with task_id filter" do context "with multiple task ids" do - let(:change_history_filters) { { task_id: [hlr_task.id, sc_task.id] } } + let(:change_history_filters) { { task_id: [@hlr_task.id, @sc_task.id] } } it "should return rows for all matching ids" do expect(subject.entries.count).to eq(3) @@ -860,7 +891,7 @@ end end - let(:change_history_filters) { { task_id: hlr_task.id } } + let(:change_history_filters) { { task_id: @hlr_task.id } } it "should only return rows for that task" do expect(subject.entries.count).to eq(2) @@ -1069,7 +1100,7 @@ end context "when filtering by multiple user css ids" do - let(:change_history_filters) { { personnel: [intake_user.css_id, decision_user.css_id] } } + let(:change_history_filters) { { personnel: [@intake_user.css_id, @decision_user.css_id] } } it "only return rows where either an intake, decisions, or updates user matches the css_ids" do expect(subject.entries.count).to eq(4) @@ -1078,7 +1109,7 @@ end context "when filtering by a single css id" do - let(:change_history_filters) { { personnel: [intake_user.css_id] } } + let(:change_history_filters) { { personnel: [@intake_user.css_id] } } it "only return rows where either an intake, decisions, or updates user matches the user css id" do expect(subject.entries.count).to eq(2) @@ -1092,7 +1123,7 @@ context "when filtering by multiple filters at the same time" do context "task_id and issue_type" do - let(:change_history_filters) { { issue_types: ["Caregiver | Other"], task_id: hlr_task.id } } + let(:change_history_filters) { { issue_types: ["Caregiver | Other"], task_id: @hlr_task.id } } it "should only return rows that match both filters" do expect(subject.entries.count).to eq(1) From 54b9fe8e0b4c460e794639b3902eb48ba04c2e85 Mon Sep 17 00:00:00 2001 From: = Date: Tue, 8 Oct 2024 14:01:55 -0400 Subject: [PATCH 04/21] Updated the vha business line spec file. Fixed a code climate warning. --- app/models/organizations/business_line.rb | 23 ++++++++++++++--------- spec/models/vha_business_line_spec.rb | 2 +- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/app/models/organizations/business_line.rb b/app/models/organizations/business_line.rb index 376675629c4..9bf878e21a5 100644 --- a/app/models/organizations/business_line.rb +++ b/app/models/organizations/business_line.rb @@ -863,10 +863,20 @@ def build_closed_at_filter_predicate(closed_at_params) mode, start_date, end_date = closed_at_params operator = date_filter_mode_to_operator(mode) - date_filters = { - ">" => -> { start_date ? "tasks.closed_at::date > '#{start_date}'::date" : "" }, - "<" => -> { start_date ? "tasks.closed_at::date < '#{start_date}'::date" : "" }, - "=" => -> { start_date ? "tasks.closed_at::date = '#{start_date}'::date" : "" }, + # Break early if start date is not present and it's not one of these 3 filter types + return "" if !%w[last_7_days last_30_days last_365_days].include?(operator) && start_date.blank? + + date_filter_lambda_hash(start_date, end_date).fetch(operator, lambda { + Rails.logger.error("Unsupported mode **#{operator}** used for closed at date filtering") + "" + }).call + end + + def date_filter_lambda_hash(start_date, end_date) + { + ">" => -> { "tasks.closed_at::date > '#{start_date}'::date" }, + "<" => -> { "tasks.closed_at::date < '#{start_date}'::date" }, + "=" => -> { "tasks.closed_at::date = '#{start_date}'::date" }, "between" => lambda { # Ensure the dates are sorted correctly so either ordering works e.g. start > end or end > start start_date, end_date = [start_date, end_date].map(&:to_date).sort @@ -876,11 +886,6 @@ def build_closed_at_filter_predicate(closed_at_params) "last_30_days" => -> { { closed_at: 30.days.ago..Time.zone.now } }, "last_365_days" => -> { { closed_at: 365.days.ago..Time.zone.now } } } - - date_filters.fetch(operator, lambda { - Rails.logger.error("Unsupported mode **#{operator}** used for closed at date filtering") - "" - }).call end def date_filter_mode_to_operator(mode) diff --git a/spec/models/vha_business_line_spec.rb b/spec/models/vha_business_line_spec.rb index ec19cd33756..bb14aec399f 100644 --- a/spec/models/vha_business_line_spec.rb +++ b/spec/models/vha_business_line_spec.rb @@ -22,7 +22,7 @@ expect(subject.tasks_query_type).to eq( incomplete: "on_hold", in_progress: "active", - completed: "recently_completed", + completed: "completed", pending: "active" ) end From c6e92e3159f2af007b8b78f568a472335c13a436 Mon Sep 17 00:00:00 2001 From: = Date: Tue, 8 Oct 2024 16:09:11 -0400 Subject: [PATCH 05/21] Removed some commented out code and changed the database cleaner to Task.delete all to be a bit more specific on cleanup before the change history tests. --- spec/models/business_line_spec.rb | 42 ++----------------------------- 1 file changed, 2 insertions(+), 40 deletions(-) diff --git a/spec/models/business_line_spec.rb b/spec/models/business_line_spec.rb index 74c02d323b4..e4da110a3f9 100644 --- a/spec/models/business_line_spec.rb +++ b/spec/models/business_line_spec.rb @@ -542,45 +542,6 @@ decider: @decider, decision_review: @extra_decision_review) end - # let!(:requestor) { create(:user) } - # let!(:decider) { create(:user) } - # let!(:hlr_pending_tasks) do - # create_list(:issue_modification_request, - # 3, - # :with_higher_level_review, - # status: "assigned", - # requestor: requestor, - # decider: decider) - # end - - # let!(:sc_pending_tasks) do - # create_list(:issue_modification_request, - # 3, - # :with_supplemental_claim, - # status: "assigned", - # requestor: requestor, - # decider: decider) - # end - - # let!(:extra_modification_request) do - # create(:issue_modification_request, - # :with_higher_level_review, - # status: "assigned", - # requestor: requestor, - # decider: decider) - # end - - # let(:extra_decision_review) do - # extra_modification_request.decision_review - # end - - # let!(:extra_modification_request2) do - # create(:issue_modification_request, - # status: "assigned", - # requestor: requestor, - # decider: decider, - # decision_review: extra_decision_review) - # end subject { business_line.pending_tasks(filters: task_filters) } @@ -816,7 +777,8 @@ end before(:all) do - DatabaseCleaner.clean_with(:truncation) + # Make sure the previous data from the before alls is cleaned up. + Task.delete_all @hlr_task = create(:higher_level_review_vha_task_with_decision) @hlr_task2 = create(:higher_level_review_vha_task) From a091395816c369b5ca693c9205be11aa2c207ddb Mon Sep 17 00:00:00 2001 From: = Date: Wed, 9 Oct 2024 21:53:44 -0400 Subject: [PATCH 06/21] Removed QueueTable code that was unrelated to the DatePicker that was causing errors. --- client/COPY.json | 13 ++++++++++++- client/app/components/TableFilter.jsx | 6 +++++- client/app/queue/QueueTable.jsx | 19 +++---------------- 3 files changed, 20 insertions(+), 18 deletions(-) diff --git a/client/COPY.json b/client/COPY.json index 05191f7d8b0..3ad44386598 100644 --- a/client/COPY.json +++ b/client/COPY.json @@ -1516,5 +1516,16 @@ }, "VHA_BANNER_DISPOSITIONS_CANNOT_BE_UPDATED_NON_ADMIN": "Requests for issue modifications have been submitted for this case. Dispositions cannot be made until a VHA admin completes review of the requested changes.", "VHA_BANNER_DISPOSITIONS_CANNOT_BE_UPDATED_ADMIN": "Requests for issue modifications have been submitted for this case. Dispositions cannot be made until a VHA admin completes review of the requested changes. Click the \"Edit issues\" button above to review the issue modification requests.", - "REMANDS_NOT_EDITABLE": "Remands can not be edited." + "REMANDS_NOT_EDITABLE": "Remands can not be edited.", + "DATE_PICKER_APPLY": "Apply Filter", + "DATE_PICKER_TO": "To", + "DATE_PICKER_FROM": "From", + "DATE_PICKER_DATE": "Date", + "DATE_PICKER_DROPDOWN_BETWEEN": "Between these dates", + "DATE_PICKER_DROPDOWN_BEFORE": "Before this date", + "DATE_PICKER_DROPDOWN_AFTER": "After this date", + "DATE_PICKER_DROPDOWN_ON": "On this date", + "DATE_PICKER_CLEAR": "Clear filter", + "DATE_PICKER_DROPDOWN_LABEL": "Date filter parameters", + "DATE_PICKER_QUICK_BUTTON_30": "Last 30 days" } diff --git a/client/app/components/TableFilter.jsx b/client/app/components/TableFilter.jsx index 449d2cedef3..e286f6cc6cf 100644 --- a/client/app/components/TableFilter.jsx +++ b/client/app/components/TableFilter.jsx @@ -77,7 +77,11 @@ class TableFilter extends React.PureComponent { }); // Case insensitive ordering for the filter options - return _.orderBy(filterOptionsFromApi, [(option) => option.displayText.toLowerCase()], ['asc']); + return _.orderBy( + filterOptionsFromApi.filter((option) => option.displayText), + [(option) => option.displayText.toLowerCase()], + ['asc'] + ); } const columnValues = tableDataByRow.map((obj) => { diff --git a/client/app/queue/QueueTable.jsx b/client/app/queue/QueueTable.jsx index 984ade89c6b..a8b8074ebc7 100644 --- a/client/app/queue/QueueTable.jsx +++ b/client/app/queue/QueueTable.jsx @@ -663,7 +663,7 @@ export default class QueueTable extends React.PureComponent { const responseFromCache = this.props.useReduxCache ? this.props.reduxCache[endpointUrl] : this.state.cachedResponses[endpointUrl]; - if (responseFromCache && !this.props.skipCache) { + if (responseFromCache) { this.setState({ tasksFromApi: responseFromCache.tasks }); return Promise.resolve(true); @@ -677,17 +677,11 @@ export default class QueueTable extends React.PureComponent { tasks: { data: tasks } } = response.body; - let preparedTasks = tasks; + const preparedTasks = tasksWithAppealsFromRawTasks(tasks); - // modify data from raw tasks if prepareTasks is true - if (this.props.prepareTasks) { - preparedTasks = tasksWithAppealsFromRawTasks(tasks); - } - - const preparedResponse = Object.assign({ ...response.body }, { tasks: preparedTasks }); + const preparedResponse = Object.assign(response.body, { tasks: preparedTasks }); this.setState({ - // cachedResponses: { ...this.state.cachedResponses, [endpointUrl]: preparedResponse }, ...(!this.props.useReduxCache && { cachedResponses: { ...this.state.cachedResponses, @@ -698,10 +692,6 @@ export default class QueueTable extends React.PureComponent { loadingComponent: null }); - if (this.props.onTableDataUpdated) { - this.props.onTableDataUpdated(preparedTasks); - } - if (this.props.useReduxCache) { this.props.updateReduxCache({ key: endpointUrl, value: preparedResponse }); } @@ -903,9 +893,6 @@ HeaderRow.propTypes = FooterRow.propTypes = Row.propTypes = BodyRows.propTypes = }), onHistoryUpdate: PropTypes.func, preserveFilter: PropTypes.bool, - prepareTasks: PropTypes.bool, - onTableDataUpdated: PropTypes.func, - skipCache: PropTypes.bool, useReduxCache: PropTypes.bool, reduxCache: PropTypes.object, updateReduxCache: PropTypes.func From f4b22cc3f81c039097cfd45b5052f146bd36e9bc Mon Sep 17 00:00:00 2001 From: = Date: Wed, 9 Oct 2024 22:03:40 -0400 Subject: [PATCH 07/21] Updated the wording in the filter summary for the closedAt filter to say Date Compeleted instead of closedAt. --- client/app/components/FilterSummary.jsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/app/components/FilterSummary.jsx b/client/app/components/FilterSummary.jsx index 07bbca46cb7..5f4aa8aa672 100644 --- a/client/app/components/FilterSummary.jsx +++ b/client/app/components/FilterSummary.jsx @@ -16,7 +16,8 @@ const ALTERNATE_COLUMN_NAMES = { suggestedLocation: 'Suggested Location', hearingLocation: 'Hearing Location', readableEventType: 'Actvitity', - eventUser: 'User' + eventUser: 'User', + closedAt: 'Date Completed' }; const FilterSummary = ({ filteredByList, clearFilteredByList }) => { From a81a22c7e387072e477cbafafb21f0937b7a078e Mon Sep 17 00:00:00 2001 From: = Date: Thu, 10 Oct 2024 16:25:24 -0400 Subject: [PATCH 08/21] Fixed a bug where the filter preservation was not working with the way the date filter params were added to the get params. Altered the Completed tasks tab description based on the Date Completed filter. Started adding a feature test for the completed date filtering. --- client/COPY.json | 1 + client/app/nonComp/components/NonCompTabs.jsx | 34 ++++++++++++++- .../nonComp/hooks/useLocalFilterStorage.js | 10 ++++- spec/feature/non_comp/reviews_spec.rb | 41 +++++++++++++++++++ 4 files changed, 84 insertions(+), 2 deletions(-) diff --git a/client/COPY.json b/client/COPY.json index 3ad44386598..c3dc7ce566c 100644 --- a/client/COPY.json +++ b/client/COPY.json @@ -329,6 +329,7 @@ "ORGANIZATIONAL_QUEUE_PAGE_IN_PROGRESS_TAB_TITLE": "In Progress (%d)", "ORGANIZATIONAL_QUEUE_ON_HOLD_TAB_TITLE": "On Hold (%d)", "VHA_QUEUE_PAGE_COMPLETE_TASKS_DESCRIPTION": "Cases completed:", + "VHA_QUEUE_PAGE_COMPLETE_TASKS_DESCRIPTION_WITH_FILTER": "Cases completed (%s)", "EDUCATION_RPO_QUEUE_PAGE_COMPLETED_TASKS_DESCRIPTION": "Cases completed in the last 7 days:", "VHA_ORGANIZATIONAL_QUEUE_PAGE_READY_FOR_REVIEW_TAB_TITLE": "Ready for Review", "VHA_ORGANIZATIONAL_QUEUE_PAGE_ON_HOLD_TAB_TITLE": "On Hold", diff --git a/client/app/nonComp/components/NonCompTabs.jsx b/client/app/nonComp/components/NonCompTabs.jsx index 10c82deeb97..6bb93e483fd 100644 --- a/client/app/nonComp/components/NonCompTabs.jsx +++ b/client/app/nonComp/components/NonCompTabs.jsx @@ -8,6 +8,7 @@ import COPY from '../../../COPY'; import TaskTableTab from './TaskTableTab'; import useLocalFilterStorage from '../hooks/useLocalFilterStorage'; import { mapValues, sumBy } from 'lodash'; +import { sprintf } from 'sprintf-js'; const NonCompTabsUnconnected = (props) => { const [localFilter, setFilter] = useLocalFilterStorage('nonCompFilter', []); @@ -47,6 +48,37 @@ const NonCompTabsUnconnected = (props) => { mapValues(props.taskFilterDetails, (obj) => sumBy(Object.values(obj))) ), [props.taskFilterDetails]); + const buildCompletedTabDescriptionFromFilter = (filters) => { + const completedDateFilter = filters.find((value) => value.includes('col=completedDateColumn')); + + if (completedDateFilter) { + const match = completedDateFilter.match(/val=([^&]*)/); + + if (match) { + const dateFilter = match[1]; + const [mode, startDate = null, endDate = null] = dateFilter.split(','); + + // Object that defines how to build the string based on the mode + const completedDateFilterModeHandlers = { + before: `Before this date ${startDate}`, + after: `After this date ${startDate}`, + on: `On this date ${startDate}`, + between: `Between this ${startDate} and that ${endDate}`, + last_7_days: 'Last 7 Days', + last_30_days: 'Last 30 Days', + last_365_days: 'Last 365 Days' + }; + + return sprintf(COPY.VHA_QUEUE_PAGE_COMPLETE_TASKS_DESCRIPTION_WITH_FILTER, + completedDateFilterModeHandlers[mode]); + } + + } + + return COPY.QUEUE_PAGE_COMPLETE_TASKS_DESCRIPTION; + + }; + const ALL_TABS = { incomplete: { label: `Incomplete Tasks (${taskCounts.incomplete})`, @@ -97,7 +129,7 @@ const NonCompTabsUnconnected = (props) => { {...(isVhaBusinessLine ? { onHistoryUpdate } : {})} filterableTaskTypes={props.taskFilterDetails.completed} filterableTaskIssueTypes={props.taskFilterDetails.completed_issue_types} - description={COPY.QUEUE_PAGE_COMPLETE_LAST_SEVEN_DAYS_TASKS_DESCRIPTION} + description={buildCompletedTabDescriptionFromFilter(filter)} predefinedColumns={{ includeCompletedDate: true }} /> } }; diff --git a/client/app/nonComp/hooks/useLocalFilterStorage.js b/client/app/nonComp/hooks/useLocalFilterStorage.js index 037954e5d62..7efaf6af022 100644 --- a/client/app/nonComp/hooks/useLocalFilterStorage.js +++ b/client/app/nonComp/hooks/useLocalFilterStorage.js @@ -1,10 +1,18 @@ +import { compact } from 'lodash'; import { useEffect, useState } from 'react'; const useLocalFilterStorage = (key, defaultValue) => { const [value, setValue] = useState(() => { const storedValue = localStorage.getItem(key); - return storedValue && storedValue !== 'null' ? [storedValue?.split(',')].flat() : defaultValue; + if (storedValue === null) { + return defaultValue; + } + + const regex = /col=[^&]+&val=[^,]+(?:,[^&]+)*(?=,|$)/g; + const columnsWithValues = [...storedValue.matchAll(regex)].map((match) => match[0]); + + return compact(columnsWithValues); }); useEffect(() => { diff --git a/spec/feature/non_comp/reviews_spec.rb b/spec/feature/non_comp/reviews_spec.rb index 1cf36ba917c..862d5e2f0c9 100644 --- a/spec/feature/non_comp/reviews_spec.rb +++ b/spec/feature/non_comp/reviews_spec.rb @@ -985,6 +985,47 @@ def current_table_rows end end + context "Completed Date filtering" do + it "is filterable by the completed date column" do + visit BASE_URL + expect(page).to have_content("Veterans Health Administration") + click_on "Completed Tasks" + # TODO: Change this to last 7 days + expect(page).to have_content("Cases completed:") + find("[aria-label='Filter by completed date']").click + expect(page).to have_content("Date filter parameters") + submit_button = find("button", text: "Apply Filter") + + expect(submit_button[:disabled]).to eq "true" + # TODO: Figure out how to do this via helpers so it's not so gross + page.find(".cf-select__control", match: :first).click + page.all("cf-select__option") + all_date_filter_options = [ + "Between these dates", + "Before this date", + "After this date", + "On this date", + "Last 7 days", + "Last 30 days", + "Last 365 days", + "View All" + ] + all_date_filter_options.each do |date_filter_option| + expect(page).to have_content(date_filter_option) + end + # TODO: match all of the options here + find("div", class: "cf-select__option", text: "Before this date", exact_text: true).click + + fill_in "Date", with: "01/01/2019" + expect(submit_button[:disabled]).to eq "false" + submit_button.click + + expect(page).to have_content("Cases completed (Before this date 2019-01-01)") + expect(page).to have_content("Date Completed (1)") + expect(page).to have_content("Viewing 0-0 of 0 total") + end + end + context "get params should not get appended to URL when QueueTable is loading and user navigates to Generate report pages." do # rubocop:disable Layout/LineLength before do create_list(:higher_level_review_vha_task, 30, assigned_to: non_comp_org) From fce21a7fd250efeae44c620cef345be95368d5c3 Mon Sep 17 00:00:00 2001 From: = Date: Thu, 10 Oct 2024 23:21:09 -0400 Subject: [PATCH 09/21] Updated the formatting of the date in the completed tasks tab description to match mm/dd/yyyy format. Finished up the feature spec test for the completed date filtering. --- client/app/nonComp/components/NonCompTabs.jsx | 13 +++-- spec/feature/non_comp/reviews_spec.rb | 58 ++++++++++++++++--- 2 files changed, 59 insertions(+), 12 deletions(-) diff --git a/client/app/nonComp/components/NonCompTabs.jsx b/client/app/nonComp/components/NonCompTabs.jsx index 6bb93e483fd..e55ef5656c1 100644 --- a/client/app/nonComp/components/NonCompTabs.jsx +++ b/client/app/nonComp/components/NonCompTabs.jsx @@ -9,6 +9,7 @@ import TaskTableTab from './TaskTableTab'; import useLocalFilterStorage from '../hooks/useLocalFilterStorage'; import { mapValues, sumBy } from 'lodash'; import { sprintf } from 'sprintf-js'; +import { formatDateStr } from '../../util/DateUtil'; const NonCompTabsUnconnected = (props) => { const [localFilter, setFilter] = useLocalFilterStorage('nonCompFilter', []); @@ -58,12 +59,16 @@ const NonCompTabsUnconnected = (props) => { const dateFilter = match[1]; const [mode, startDate = null, endDate = null] = dateFilter.split(','); + const formattedStartDate = startDate ? formatDateStr(startDate) : ''; + + const formattedEndDate = endDate ? formatDateStr(endDate) : ''; + // Object that defines how to build the string based on the mode const completedDateFilterModeHandlers = { - before: `Before this date ${startDate}`, - after: `After this date ${startDate}`, - on: `On this date ${startDate}`, - between: `Between this ${startDate} and that ${endDate}`, + before: `Before this date ${formattedStartDate}`, + after: `After this date ${formattedStartDate}`, + on: `On this date ${formattedStartDate}`, + between: `Between this ${formattedStartDate} and that ${formattedEndDate}`, last_7_days: 'Last 7 Days', last_30_days: 'Last 30 Days', last_365_days: 'Last 365 Days' diff --git a/spec/feature/non_comp/reviews_spec.rb b/spec/feature/non_comp/reviews_spec.rb index 862d5e2f0c9..a59d78f2b3f 100644 --- a/spec/feature/non_comp/reviews_spec.rb +++ b/spec/feature/non_comp/reviews_spec.rb @@ -88,7 +88,7 @@ :completed, appeal: hlr_c, assigned_to: non_comp_org, - closed_at: 2.days.ago) + closed_at: 3.days.ago) ] end @@ -428,7 +428,7 @@ def current_table_rows click_button("tasks-organization-queue-tab-3") later_date = Time.zone.now.strftime("%m/%d/%y") - earlier_date = 2.days.ago.strftime("%m/%d/%y") + earlier_date = 3.days.ago.strftime("%m/%d/%y") order_buttons[:date_completed].click expect(page).to have_current_path( @@ -990,16 +990,25 @@ def current_table_rows visit BASE_URL expect(page).to have_content("Veterans Health Administration") click_on "Completed Tasks" - # TODO: Change this to last 7 days + + # Swap these on once the Last 7 days pre filter is added back + # expect(page).to have_content("Cases completed (Last 7 Days)") + # expect(page).to have_content("Date Completed (1)") + # expect(page).to have_content("Viewing 1-2 of 2 total") + + # Remove these 3 once Last 7 days pre filter is added back expect(page).to have_content("Cases completed:") + expect(page).to_not have_content("Date Completed (1)") + expect(page).to have_content("Viewing 1-3 of 3 total") + find("[aria-label='Filter by completed date']").click expect(page).to have_content("Date filter parameters") submit_button = find("button", text: "Apply Filter") expect(submit_button[:disabled]).to eq "true" - # TODO: Figure out how to do this via helpers so it's not so gross page.find(".cf-select__control", match: :first).click page.all("cf-select__option") + # Verify that all the date picker options are available all_date_filter_options = [ "Between these dates", "Before this date", @@ -1013,16 +1022,49 @@ def current_table_rows all_date_filter_options.each do |date_filter_option| expect(page).to have_content(date_filter_option) end - # TODO: match all of the options here find("div", class: "cf-select__option", text: "Before this date", exact_text: true).click - fill_in "Date", with: "01/01/2019" + one_day_ago_date_string = 1.day.ago.strftime("%m/%d/%Y") + fill_in "Date", with: one_day_ago_date_string expect(submit_button[:disabled]).to eq "false" submit_button.click - expect(page).to have_content("Cases completed (Before this date 2019-01-01)") + expect(page).to have_content("Cases completed (Before this date #{one_day_ago_date_string})") + expect(page).to have_content("Date Completed (1)") + expect(page).to have_content("Viewing 1-2 of 2 total") + find("[aria-label='Filter by completed date. Filtering by before,#{1.day.ago.strftime('%Y-%m-%d')},']").click + page.find(".cf-select__control", match: :first).click + find("div", class: "cf-select__option", text: "After this date", exact_text: true).click + find("button", text: "Apply Filter").click + + expect(page).to have_content("Cases completed (After this date #{one_day_ago_date_string})") + expect(page).to have_content("Date Completed (1)") + expect(page).to have_content("Viewing 1-1 of 1 total") + + click_on "Clear all filters" + + # Swap these on once the Last 7 days pre filter is added back + # expect(page).to have_content("Cases completed (Last 7 Days)") + # expect(page).to have_content("Date Completed (1)") + # expect(page).to have_content("Viewing 1-2 of 2 total") + + # Remove these 3 once Last 7 days pre filter is added back + expect(page).to have_content("Cases completed:") + expect(page).to_not have_content("Date Completed (1)") + expect(page).to have_content("Viewing 1-3 of 3 total") + + find("[aria-label='Filter by completed date']").click + expect(page).to have_content("Date filter parameters") + submit_button = find("button", text: "Apply Filter") + + expect(submit_button[:disabled]).to eq "true" + page.find(".cf-select__control", match: :first).click + find("div", class: "cf-select__option", text: "Last 30 days", exact_text: true).click + submit_button.click + + expect(page).to have_content("Cases completed (Last 30 Days)") expect(page).to have_content("Date Completed (1)") - expect(page).to have_content("Viewing 0-0 of 0 total") + expect(page).to have_content("Viewing 1-3 of 3 total") end end From 8a862ddce80f26f57921d6976de6783c276daace Mon Sep 17 00:00:00 2001 From: = <109369527+TylerBroyles@users.noreply.github.com> Date: Tue, 22 Oct 2024 14:14:15 -0400 Subject: [PATCH 10/21] Updated the expected values from the DatePicker to match what was in the feature branch. Updated the completed tasks tab description to once again be last 7 days for any business line that is not the VHA. Fixed a code climate issue with the new regex used for the filter preservation hook. Updated the new vha completed by date column to match the old column value so sorting and filtering will work correctly. --- app/models/organizations/business_line.rb | 6 +++--- client/app/nonComp/components/NonCompTabs.jsx | 8 +++++--- client/app/nonComp/components/TaskTableColumns.jsx | 2 +- client/app/nonComp/hooks/useLocalFilterStorage.js | 2 +- spec/models/business_line_spec.rb | 6 +++--- 5 files changed, 13 insertions(+), 11 deletions(-) diff --git a/app/models/organizations/business_line.rb b/app/models/organizations/business_line.rb index bd1fbe811bd..ad8ec694861 100644 --- a/app/models/organizations/business_line.rb +++ b/app/models/organizations/business_line.rb @@ -1142,9 +1142,9 @@ def date_filter_mode_to_operator(mode) "after" => ">", "before" => "<", "on" => "=", - "last_7_days" => "last_7_days", - "last_30_days" => "last_30_days", - "last_365_days" => "last_365_days" + "last7" => "last_7_days", + "last30" => "last_30_days", + "last365" => "last_365_days" }[mode] end end diff --git a/client/app/nonComp/components/NonCompTabs.jsx b/client/app/nonComp/components/NonCompTabs.jsx index cb465282b0d..6be04c7d03f 100644 --- a/client/app/nonComp/components/NonCompTabs.jsx +++ b/client/app/nonComp/components/NonCompTabs.jsx @@ -69,15 +69,17 @@ const NonCompTabsUnconnected = (props) => { after: `After this date ${formattedStartDate}`, on: `On this date ${formattedStartDate}`, between: `Between this ${formattedStartDate} and that ${formattedEndDate}`, - last_7_days: 'Last 7 Days', - last_30_days: 'Last 30 Days', - last_365_days: 'Last 365 Days' + last7: 'Last 7 Days', + last30: 'Last 30 Days', + last365: 'Last 365 Days' }; return sprintf(COPY.VHA_QUEUE_PAGE_COMPLETE_TASKS_DESCRIPTION_WITH_FILTER, completedDateFilterModeHandlers[mode]); } + } else if (!isVhaBusinessLine) { + return COPY.QUEUE_PAGE_COMPLETE_LAST_SEVEN_DAYS_TASKS_DESCRIPTION; } return COPY.QUEUE_PAGE_COMPLETE_TASKS_DESCRIPTION; diff --git a/client/app/nonComp/components/TaskTableColumns.jsx b/client/app/nonComp/components/TaskTableColumns.jsx index 9793d63fb43..4d2d92ddd87 100644 --- a/client/app/nonComp/components/TaskTableColumns.jsx +++ b/client/app/nonComp/components/TaskTableColumns.jsx @@ -65,7 +65,7 @@ export const pendingIssueModificationColumn = () => { export const vhaTaskCompletedDateColumn = () => { return { header: COPY.CASE_LIST_TABLE_COMPLETED_ON_DATE_COLUMN_TITLE, - name: 'completedOnDateColumn', + name: 'completedDateColumn', valueFunction: (task) => task.closedAt ? : null, backendCanSort: true, enableFilter: true, diff --git a/client/app/nonComp/hooks/useLocalFilterStorage.js b/client/app/nonComp/hooks/useLocalFilterStorage.js index 7efaf6af022..1c8a26b92d0 100644 --- a/client/app/nonComp/hooks/useLocalFilterStorage.js +++ b/client/app/nonComp/hooks/useLocalFilterStorage.js @@ -9,7 +9,7 @@ const useLocalFilterStorage = (key, defaultValue) => { return defaultValue; } - const regex = /col=[^&]+&val=[^,]+(?:,[^&]+)*(?=,|$)/g; + const regex = /col=[^&]+&val=[^,]+(?:,[^&,]+)*(?=,|$)/g; const columnsWithValues = [...storedValue.matchAll(regex)].map((match) => match[0]); return compact(columnsWithValues); diff --git a/spec/models/business_line_spec.rb b/spec/models/business_line_spec.rb index 8ddca1848f0..a291deec7ba 100644 --- a/spec/models/business_line_spec.rb +++ b/spec/models/business_line_spec.rb @@ -446,7 +446,7 @@ end let(:task_filters) do - ["col=completedDateColumn&val=last_7_days,,"] + ["col=completedDateColumn&val=last7,,"] end it "should filter the tasks for a closed at in the last 7 days" do @@ -482,7 +482,7 @@ end let(:task_filters) do - ["col=completedDateColumn&val=last_30_days,,"] + ["col=completedDateColumn&val=last30,,"] end it "should filter the tasks for a closed at in the last 30 days" do @@ -519,7 +519,7 @@ end let(:task_filters) do - ["col=completedDateColumn&val=last_365_days,,"] + ["col=completedDateColumn&val=last365,,"] end it "should filter the tasks for a closed at in the last 365 days" do From 528221be5e0d693ae45452254d07cea4dd6a5f80 Mon Sep 17 00:00:00 2001 From: = <109369527+TylerBroyles@users.noreply.github.com> Date: Tue, 22 Oct 2024 14:33:15 -0400 Subject: [PATCH 11/21] Updated the aria label in the new column. --- client/app/nonComp/components/TaskTableColumns.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/app/nonComp/components/TaskTableColumns.jsx b/client/app/nonComp/components/TaskTableColumns.jsx index 4d2d92ddd87..a2cbb67ecf3 100644 --- a/client/app/nonComp/components/TaskTableColumns.jsx +++ b/client/app/nonComp/components/TaskTableColumns.jsx @@ -65,7 +65,7 @@ export const pendingIssueModificationColumn = () => { export const vhaTaskCompletedDateColumn = () => { return { header: COPY.CASE_LIST_TABLE_COMPLETED_ON_DATE_COLUMN_TITLE, - name: 'completedDateColumn', + name: QUEUE_CONFIG.COLUMNS.TASK_CLOSED_DATE.name, valueFunction: (task) => task.closedAt ? : null, backendCanSort: true, enableFilter: true, @@ -78,7 +78,7 @@ export const vhaTaskCompletedDateColumn = () => { }, columnName: 'closedAt', valueName: 'closedAt', - label: 'Date Completed', + label: 'Filter by completed date', getSortValue: (task) => task.closedAt ? new Date(task.closedAt) : null }; }; From f7cc3c62c5e40a9d885e1ae453e621326c0467e2 Mon Sep 17 00:00:00 2001 From: = <109369527+TylerBroyles@users.noreply.github.com> Date: Tue, 22 Oct 2024 15:42:45 -0400 Subject: [PATCH 12/21] Fixed failing tests related to the completed date column, completed tasks description, and the clear filters change from the DatePicker. --- client/test/app/nonComp/NonCompTabs.test.js | 3 ++- spec/feature/non_comp/individual_claim_history_spec.rb | 2 +- spec/feature/non_comp/reviews_spec.rb | 6 ++++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/client/test/app/nonComp/NonCompTabs.test.js b/client/test/app/nonComp/NonCompTabs.test.js index c0703798dfa..a85b9590731 100644 --- a/client/test/app/nonComp/NonCompTabs.test.js +++ b/client/test/app/nonComp/NonCompTabs.test.js @@ -177,7 +177,8 @@ describe('NonCompTabsVha', () => { await tabs[3].click(); await waitFor(() => { - expect(screen.getByText('Cases completed (last 7 days):')).toBeInTheDocument(); + // expect(screen.getByText('Cases completed (last 7 days):')).toBeInTheDocument(); + expect(screen.getByText('Cases completed:')).toBeInTheDocument(); }); // Check for the correct completed tasks header values diff --git a/spec/feature/non_comp/individual_claim_history_spec.rb b/spec/feature/non_comp/individual_claim_history_spec.rb index a5d01b3b835..9d9b76fda35 100644 --- a/spec/feature/non_comp/individual_claim_history_spec.rb +++ b/spec/feature/non_comp/individual_claim_history_spec.rb @@ -29,7 +29,7 @@ def clear_filter_option(filter_text) sort = find("[aria-label='Filter by Activity. Filtering by #{filter_text}']") sort.click - clear_button_filter = page.find(class: "cf-clear-filter-button-wrapper") + clear_button_filter = page.first(:css, '.cf-clear-filter-button-wrapper, .clear-wrapper') clear_button_filter.click end diff --git a/spec/feature/non_comp/reviews_spec.rb b/spec/feature/non_comp/reviews_spec.rb index 39df760c00f..10ca6420344 100644 --- a/spec/feature/non_comp/reviews_spec.rb +++ b/spec/feature/non_comp/reviews_spec.rb @@ -432,7 +432,7 @@ def current_table_rows order_buttons[:date_completed].click expect(page).to have_current_path( - "#{BASE_URL}?tab=completed&page=1&sort_by=completedOnDateColumn&order=desc" + "#{BASE_URL}?tab=completed&page=1&sort_by=completedDateColumn&order=desc" ) table_rows = current_table_rows @@ -581,7 +581,9 @@ def current_table_rows # Verify the filter counts for the completed tab click_on "Completed Tasks" - expect(page).to have_content(COPY::QUEUE_PAGE_COMPLETE_LAST_SEVEN_DAYS_TASKS_DESCRIPTION) + expect(page).to have_content(COPY::QUEUE_PAGE_COMPLETE_TASKS_DESCRIPTION) + # Turn this back on after last 7 days prefilter is added + # expect(page).to have_content(COPY::QUEUE_PAGE_COMPLETE_LAST_SEVEN_DAYS_TASKS_DESCRIPTION) find("[aria-label='Filter by issue type']").click expect(page).to have_content("Apportionment (1)") expect(page).to have_content("Camp Lejune Family Member (1)") From ed56d3075787d68d3c1194da28eedd0aa02f9fe2 Mon Sep 17 00:00:00 2001 From: = <109369527+TylerBroyles@users.noreply.github.com> Date: Tue, 22 Oct 2024 15:43:45 -0400 Subject: [PATCH 13/21] Changed single quotes to double quotes in ruby. --- spec/feature/non_comp/individual_claim_history_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/feature/non_comp/individual_claim_history_spec.rb b/spec/feature/non_comp/individual_claim_history_spec.rb index 9d9b76fda35..8ed7a4b5aab 100644 --- a/spec/feature/non_comp/individual_claim_history_spec.rb +++ b/spec/feature/non_comp/individual_claim_history_spec.rb @@ -29,7 +29,7 @@ def clear_filter_option(filter_text) sort = find("[aria-label='Filter by Activity. Filtering by #{filter_text}']") sort.click - clear_button_filter = page.first(:css, '.cf-clear-filter-button-wrapper, .clear-wrapper') + clear_button_filter = page.first(:css, ".cf-clear-filter-button-wrapper, .clear-wrapper") clear_button_filter.click end From 0b595859ec14dd80f04ad3c3608f00daec902fc8 Mon Sep 17 00:00:00 2001 From: = <109369527+TylerBroyles@users.noreply.github.com> Date: Tue, 22 Oct 2024 17:25:42 -0400 Subject: [PATCH 14/21] Fixed a few more test failures. --- spec/feature/non_comp/reviews_spec.rb | 8 ++++++-- spec/feature/queue/appeal_notifications_page_spec.rb | 8 ++++---- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/spec/feature/non_comp/reviews_spec.rb b/spec/feature/non_comp/reviews_spec.rb index 10ca6420344..81effb848b0 100644 --- a/spec/feature/non_comp/reviews_spec.rb +++ b/spec/feature/non_comp/reviews_spec.rb @@ -252,7 +252,9 @@ def current_table_rows ) click_on "Completed Tasks" - expect(page).to have_content("Higher-Level Review", count: 2) + # expect(page).to have_content("Higher-Level Review", count: 2) + # Remove this once the pre filter 7 days is added back + expect(page).to have_content("Higher-Level Review", count: 3) expect(page).to have_content("Date Completed") decision_date = hlr_b.tasks.first.closed_at.strftime("%m/%d/%y") @@ -428,7 +430,9 @@ def current_table_rows click_button("tasks-organization-queue-tab-3") later_date = Time.zone.now.strftime("%m/%d/%y") - earlier_date = 3.days.ago.strftime("%m/%d/%y") + # earlier_date = 3.days.ago.strftime("%m/%d/%y") + # Remove this one the pre filter 7 days is added + earlier_date = 7.days.ago.strftime("%m/%d/%y") order_buttons[:date_completed].click expect(page).to have_current_path( diff --git a/spec/feature/queue/appeal_notifications_page_spec.rb b/spec/feature/queue/appeal_notifications_page_spec.rb index 44dd8eca6ff..763c0321a46 100644 --- a/spec/feature/queue/appeal_notifications_page_spec.rb +++ b/spec/feature/queue/appeal_notifications_page_spec.rb @@ -156,7 +156,7 @@ # clear filter filter.click - page.find("button", text: "Clear Event filter").click + page.find("button", text: "Clear filter").click # by notification type filter = page.all("path", class: "unselected-filter-icon-inner-1", minimum: 1)[1] @@ -171,7 +171,7 @@ # clear filter filter.click - page.find("button", text: "Clear Notification Type filter").click + page.find("button", text: "Clear filter").click # by recipient information filter = page.all("path", class: "unselected-filter-icon-inner-1", minimum: 1)[2] @@ -186,7 +186,7 @@ # clear filter filter.click - page.find("button", text: "Clear Recipient Information filter").click + page.find("button", text: "Clear filter").click # by status filter = page.all("path", class: "unselected-filter-icon-inner-1", minimum: 1)[3] @@ -201,7 +201,7 @@ # clear filter filter.click - page.find("button", text: "Clear Status filter").click + page.find("button", text: "Clear filter").click # by multiple columns at once filters = page.all("path", class: "unselected-filter-icon-inner-1", minimum: 1) From c2c1ce837735008367bcce65c7de56fd3ccaada2 Mon Sep 17 00:00:00 2001 From: = <109369527+TylerBroyles@users.noreply.github.com> Date: Wed, 23 Oct 2024 15:07:54 -0400 Subject: [PATCH 15/21] Altered the date picker validation code to disable the button if no date is selected for on, before, or after. --- client/app/components/DatePicker.jsx | 5 ----- 1 file changed, 5 deletions(-) diff --git a/client/app/components/DatePicker.jsx b/client/app/components/DatePicker.jsx index fe638e25876..0a7817d2c84 100644 --- a/client/app/components/DatePicker.jsx +++ b/client/app/components/DatePicker.jsx @@ -223,11 +223,6 @@ class DatePicker extends React.PureComponent { disabled = startDate >= endDate; } - } else if (this.state.mode === 'before' || this.state.mode === 'after' || this.state.mode === 'on') { - const startDate = moment(`${this.state.startDate} 00:00:00`).valueOf(); - const currentDate = moment().valueOf(); - - disabled = startDate >= currentDate; } else if (this.state.mode !== '') { disabled = this.state.startDate === ''; } From 5c48b00e5cd82dfa61c59761c8f83f87e0da18c0 Mon Sep 17 00:00:00 2001 From: = <109369527+TylerBroyles@users.noreply.github.com> Date: Wed, 23 Oct 2024 15:40:37 -0400 Subject: [PATCH 16/21] Updated the completed tasks tab description filtered by completed text to be less verbose. Change .nil? to .blank? in the closed_at filter parsing. Updated the test to reflect the new wording. --- app/models/organizations/business_line.rb | 2 +- client/app/nonComp/components/NonCompTabs.jsx | 8 ++++---- spec/feature/non_comp/reviews_spec.rb | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/app/models/organizations/business_line.rb b/app/models/organizations/business_line.rb index ad8ec694861..8d8ce3c8f49 100644 --- a/app/models/organizations/business_line.rb +++ b/app/models/organizations/business_line.rb @@ -1085,7 +1085,7 @@ def where_clause_from_array(table_class, column, values_array) end def closed_at_filter_predicate(filters) - return "" if filters.nil? + return "" if filters.blank? closed_at_filter = locate_closed_at_filter(filters) diff --git a/client/app/nonComp/components/NonCompTabs.jsx b/client/app/nonComp/components/NonCompTabs.jsx index 6be04c7d03f..46109b3097e 100644 --- a/client/app/nonComp/components/NonCompTabs.jsx +++ b/client/app/nonComp/components/NonCompTabs.jsx @@ -65,10 +65,10 @@ const NonCompTabsUnconnected = (props) => { // Object that defines how to build the string based on the mode const completedDateFilterModeHandlers = { - before: `Before this date ${formattedStartDate}`, - after: `After this date ${formattedStartDate}`, - on: `On this date ${formattedStartDate}`, - between: `Between this ${formattedStartDate} and that ${formattedEndDate}`, + before: `Before ${formattedStartDate}`, + after: `After ${formattedStartDate}`, + on: `On ${formattedStartDate}`, + between: `Between ${formattedStartDate} and ${formattedEndDate}`, last7: 'Last 7 Days', last30: 'Last 30 Days', last365: 'Last 365 Days' diff --git a/spec/feature/non_comp/reviews_spec.rb b/spec/feature/non_comp/reviews_spec.rb index 81effb848b0..b048313b660 100644 --- a/spec/feature/non_comp/reviews_spec.rb +++ b/spec/feature/non_comp/reviews_spec.rb @@ -1035,7 +1035,7 @@ def current_table_rows expect(submit_button[:disabled]).to eq "false" submit_button.click - expect(page).to have_content("Cases completed (Before this date #{one_day_ago_date_string})") + expect(page).to have_content("Cases completed (Before #{one_day_ago_date_string})") expect(page).to have_content("Date Completed (1)") expect(page).to have_content("Viewing 1-2 of 2 total") find("[aria-label='Filter by completed date. Filtering by before,#{1.day.ago.strftime('%Y-%m-%d')},']").click @@ -1043,7 +1043,7 @@ def current_table_rows find("div", class: "cf-select__option", text: "After this date", exact_text: true).click find("button", text: "Apply Filter").click - expect(page).to have_content("Cases completed (After this date #{one_day_ago_date_string})") + expect(page).to have_content("Cases completed (After #{one_day_ago_date_string})") expect(page).to have_content("Date Completed (1)") expect(page).to have_content("Viewing 1-1 of 1 total") From 77465a55cd28c1cffcc9632998f9c5723929b392 Mon Sep 17 00:00:00 2001 From: = <109369527+TylerBroyles@users.noreply.github.com> Date: Thu, 24 Oct 2024 12:13:47 -0400 Subject: [PATCH 17/21] Updated the Completed Cases text to contain no colon for the vha decision review queue. Fixed a bug in the date picker where the View All was not resetting the filter correctly. --- client/COPY.json | 2 +- client/app/components/DatePicker.jsx | 22 ++++++++++++++----- client/app/nonComp/components/NonCompTabs.jsx | 2 +- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/client/COPY.json b/client/COPY.json index c9fad28a95c..02c9fd85d1f 100644 --- a/client/COPY.json +++ b/client/COPY.json @@ -328,7 +328,7 @@ "ORGANIZATIONAL_QUEUE_PAGE_ASSIGNED_TAB_TITLE": "Assigned (%d)", "ORGANIZATIONAL_QUEUE_PAGE_IN_PROGRESS_TAB_TITLE": "In Progress (%d)", "ORGANIZATIONAL_QUEUE_ON_HOLD_TAB_TITLE": "On Hold (%d)", - "VHA_QUEUE_PAGE_COMPLETE_TASKS_DESCRIPTION": "Cases completed:", + "VHA_QUEUE_PAGE_COMPLETE_TASKS_DESCRIPTION": "Cases completed", "VHA_QUEUE_PAGE_COMPLETE_TASKS_DESCRIPTION_WITH_FILTER": "Cases completed (%s)", "EDUCATION_RPO_QUEUE_PAGE_COMPLETED_TASKS_DESCRIPTION": "Cases completed in the last 7 days:", "VHA_ORGANIZATIONAL_QUEUE_PAGE_READY_FOR_REVIEW_TAB_TITLE": "Ready for Review", diff --git a/client/app/components/DatePicker.jsx b/client/app/components/DatePicker.jsx index 0a7817d2c84..4133b23c128 100644 --- a/client/app/components/DatePicker.jsx +++ b/client/app/components/DatePicker.jsx @@ -161,6 +161,13 @@ class DatePicker extends React.PureComponent { apply() { const { onChange } = this.props; + if (this.state.mode === 'all') { + this.clearFilter(); + this.hideDropdown(); + + return true; + } + if (onChange) { onChange(`${this.state.mode },${ this.state.startDate },${ this.state.endDate}`); } @@ -225,6 +232,8 @@ class DatePicker extends React.PureComponent { } } else if (this.state.mode !== '') { disabled = this.state.startDate === ''; + } else if (this.state.mode === 'all') { + disabled = false; } return disabled; @@ -243,19 +252,22 @@ class DatePicker extends React.PureComponent { } updateMode = (mode) => { + const format = 'YYYY-MM-DD'; + this.setState({ mode }); if (mode !== 'between') { this.setState({ endDate: '' }); } if (mode === 'last7') { - this.setState({ startDate: moment().subtract(7, 'days') }); + this.setState({ startDate: moment().subtract(7, 'days'). + format(format) }); } else if (mode === 'last30') { - this.setState({ startDate: moment().subtract(30, 'days') }); + this.setState({ startDate: moment().subtract(30, 'days'). + format(format) }); } else if (mode === 'last365') { - this.setState({ startDate: moment().subtract(365, 'days') }); - } else if (mode === 'all') { - this.setState({ startDate: moment().subtract(300, 'years') }); + this.setState({ startDate: moment().subtract(365, 'days'). + format(format) }); } } diff --git a/client/app/nonComp/components/NonCompTabs.jsx b/client/app/nonComp/components/NonCompTabs.jsx index 46109b3097e..bbe5ea218a8 100644 --- a/client/app/nonComp/components/NonCompTabs.jsx +++ b/client/app/nonComp/components/NonCompTabs.jsx @@ -82,7 +82,7 @@ const NonCompTabsUnconnected = (props) => { return COPY.QUEUE_PAGE_COMPLETE_LAST_SEVEN_DAYS_TASKS_DESCRIPTION; } - return COPY.QUEUE_PAGE_COMPLETE_TASKS_DESCRIPTION; + return COPY.VHA_QUEUE_PAGE_COMPLETE_TASKS_DESCRIPTION; }; From 5e2ac1a4276c219556fb46ea4d4bd701506c3187 Mon Sep 17 00:00:00 2001 From: = <109369527+TylerBroyles@users.noreply.github.com> Date: Thu, 24 Oct 2024 12:43:00 -0400 Subject: [PATCH 18/21] Fixed a few jest tests. --- client/test/app/components/DatePicker.test.js | 6 +++--- client/test/app/nonComp/NonCompTabs.test.js | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/client/test/app/components/DatePicker.test.js b/client/test/app/components/DatePicker.test.js index eada26082f6..4a6996555e6 100644 --- a/client/test/app/components/DatePicker.test.js +++ b/client/test/app/components/DatePicker.test.js @@ -157,7 +157,7 @@ describe('DatePicker', () => { clickSubmissionButton('Apply Filter'); - expect(handleChange).toHaveBeenCalledWith('last7,Wed Jan 10 2024 02:00:00 GMT-0500,'); + expect(handleChange).toHaveBeenCalledWith('last7,2024-01-10,'); }); it('quick select options can select last 30 days', async () => { @@ -173,7 +173,7 @@ describe('DatePicker', () => { clickSubmissionButton('Apply Filter'); - expect(handleChange).toHaveBeenCalledWith('last30,Mon Dec 18 2023 02:00:00 GMT-0500,'); + expect(handleChange).toHaveBeenCalledWith('last30,2023-12-18,'); }); it('quick select options can select last 365 days', async () => { @@ -189,7 +189,7 @@ describe('DatePicker', () => { clickSubmissionButton('Apply Filter'); - expect(handleChange).toHaveBeenCalledWith('last365,Tue Jan 17 2023 02:00:00 GMT-0500,'); + expect(handleChange).toHaveBeenCalledWith('last365,2023-01-17,'); }); it('disables Apply Filter button if between is selected and the start date is after the end date', () => { diff --git a/client/test/app/nonComp/NonCompTabs.test.js b/client/test/app/nonComp/NonCompTabs.test.js index a85b9590731..d08de1d322f 100644 --- a/client/test/app/nonComp/NonCompTabs.test.js +++ b/client/test/app/nonComp/NonCompTabs.test.js @@ -178,7 +178,7 @@ describe('NonCompTabsVha', () => { await waitFor(() => { // expect(screen.getByText('Cases completed (last 7 days):')).toBeInTheDocument(); - expect(screen.getByText('Cases completed:')).toBeInTheDocument(); + expect(screen.getByText('Cases completed')).toBeInTheDocument(); }); // Check for the correct completed tasks header values From c1fe72dadfb70c8495555c2d1bd7872c0de6e1a6 Mon Sep 17 00:00:00 2001 From: = <109369527+TylerBroyles@users.noreply.github.com> Date: Thu, 24 Oct 2024 14:39:00 -0400 Subject: [PATCH 19/21] Fixed a bug that could occur if you are trying to filter by a column that does not exist in a different queue. --- client/app/queue/QueueTable.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/app/queue/QueueTable.jsx b/client/app/queue/QueueTable.jsx index 90f7aa53333..71a7f8d3a55 100644 --- a/client/app/queue/QueueTable.jsx +++ b/client/app/queue/QueueTable.jsx @@ -423,7 +423,7 @@ export default class QueueTable extends React.PureComponent { }); } - return filters; + return _.omit(filters, 'undefined'); }; defaultRowClassNames = () => ''; From 69655fc621c0453cb94242aa85d883ee1eca7a64 Mon Sep 17 00:00:00 2001 From: = <109369527+TylerBroyles@users.noreply.github.com> Date: Thu, 24 Oct 2024 20:12:21 -0400 Subject: [PATCH 20/21] Updated feature test with the new vha all completed cases description text without a colon. --- spec/feature/non_comp/reviews_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/feature/non_comp/reviews_spec.rb b/spec/feature/non_comp/reviews_spec.rb index b048313b660..c330b9f69c6 100644 --- a/spec/feature/non_comp/reviews_spec.rb +++ b/spec/feature/non_comp/reviews_spec.rb @@ -585,7 +585,7 @@ def current_table_rows # Verify the filter counts for the completed tab click_on "Completed Tasks" - expect(page).to have_content(COPY::QUEUE_PAGE_COMPLETE_TASKS_DESCRIPTION) + expect(page).to have_content(COPY::VHA_QUEUE_PAGE_COMPLETE_TASKS_DESCRIPTION) # Turn this back on after last 7 days prefilter is added # expect(page).to have_content(COPY::QUEUE_PAGE_COMPLETE_LAST_SEVEN_DAYS_TASKS_DESCRIPTION) find("[aria-label='Filter by issue type']").click @@ -1003,7 +1003,7 @@ def current_table_rows # expect(page).to have_content("Viewing 1-2 of 2 total") # Remove these 3 once Last 7 days pre filter is added back - expect(page).to have_content("Cases completed:") + expect(page).to have_content(COPY::VHA_QUEUE_PAGE_COMPLETE_TASKS_DESCRIPTION) expect(page).to_not have_content("Date Completed (1)") expect(page).to have_content("Viewing 1-3 of 3 total") From e6f04e1635e0a07a43dc7519675f320a3fd1ce46 Mon Sep 17 00:00:00 2001 From: = <109369527+TylerBroyles@users.noreply.github.com> Date: Fri, 25 Oct 2024 13:43:53 -0400 Subject: [PATCH 21/21] Fixed a text issue when swapping between business lines with the same user that has a filter from the vha business line. --- client/app/nonComp/components/NonCompTabs.jsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/app/nonComp/components/NonCompTabs.jsx b/client/app/nonComp/components/NonCompTabs.jsx index bbe5ea218a8..2701bc75a2b 100644 --- a/client/app/nonComp/components/NonCompTabs.jsx +++ b/client/app/nonComp/components/NonCompTabs.jsx @@ -52,7 +52,9 @@ const NonCompTabsUnconnected = (props) => { const buildCompletedTabDescriptionFromFilter = (filters) => { const completedDateFilter = filters.find((value) => value.includes('col=completedDateColumn')); - if (completedDateFilter) { + if (!isVhaBusinessLine) { + return COPY.QUEUE_PAGE_COMPLETE_LAST_SEVEN_DAYS_TASKS_DESCRIPTION; + } else if (completedDateFilter) { const match = completedDateFilter.match(/val=([^&]*)/); if (match) { @@ -78,8 +80,6 @@ const NonCompTabsUnconnected = (props) => { completedDateFilterModeHandlers[mode]); } - } else if (!isVhaBusinessLine) { - return COPY.QUEUE_PAGE_COMPLETE_LAST_SEVEN_DAYS_TASKS_DESCRIPTION; } return COPY.VHA_QUEUE_PAGE_COMPLETE_TASKS_DESCRIPTION;