Skip to content

Commit

Permalink
Merge pull request #19764 from department-of-veterans-affairs/feature…
Browse files Browse the repository at this point in the history
…/APPEALS-26499

Feature/appeals 26499 VHA Change History Report
  • Loading branch information
craigrva authored Jan 11, 2024
2 parents 42df79f + b5a9474 commit 7dc0614
Show file tree
Hide file tree
Showing 105 changed files with 10,361 additions and 263 deletions.
2 changes: 1 addition & 1 deletion .codeclimate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ plugins:
rubocop:
enabled: true
channel: rubocop-0-79
scss-lint:
stylelint:
enabled: true
grep:
enabled: true
Expand Down
9 changes: 4 additions & 5 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ GEM
fasterer (0.6.0)
colorize (~> 0.7)
ruby_parser (>= 3.13.0)
ffi (1.11.1)
ffi (1.16.3)
foreman (0.85.0)
thor (~> 0.19.1)
formatador (0.2.5)
Expand Down Expand Up @@ -513,8 +513,8 @@ GEM
thor (>= 0.19.0, < 2.0)
rainbow (3.0.0)
rake (12.3.3)
rb-fsevent (0.10.3)
rb-inotify (0.10.0)
rb-fsevent (0.11.2)
rb-inotify (0.10.1)
ffi (~> 1.0)
rb-readline (0.5.5)
rchardet (1.8.0)
Expand Down Expand Up @@ -632,8 +632,7 @@ GEM
sawyer (0.8.2)
addressable (>= 2.3.5)
faraday (> 0.8, < 2.0)
scss_lint (0.58.0)
rake (>= 0.9, < 13)
scss_lint (0.60.0)
sass (~> 3.5, >= 3.5.5)
selenium-webdriver (4.9.0)
rexml (~> 3.2, >= 3.2.5)
Expand Down
118 changes: 104 additions & 14 deletions app/controllers/decision_reviews_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ class DecisionReviewsController < ApplicationController

before_action :verify_access, :react_routed, :set_application
before_action :verify_veteran_record_access, only: [:show]
before_action :verify_business_line, only: [:index, :generate_report]

delegate :incomplete_tasks,
:incomplete_tasks_type_counts,
Expand All @@ -17,6 +18,7 @@ class DecisionReviewsController < ApplicationController
:completed_tasks_type_counts,
:completed_tasks_issue_type_counts,
:included_tabs,
:can_generate_claim_history?,
to: :business_line

SORT_COLUMN_MAPPINGS = {
Expand All @@ -30,19 +32,13 @@ class DecisionReviewsController < ApplicationController
}.freeze

def index
if business_line
respond_to do |format|
format.html { render "index" }
format.csv do
jobs_as_csv = BusinessLineReporter.new(business_line).as_csv
filename = Time.zone.now.strftime("#{business_line.url}-%Y%m%d.csv")
send_data jobs_as_csv, filename: filename
end
format.json { queue_tasks }
respond_to do |format|
format.html { render "index" }
format.csv do
jobs_as_csv = BusinessLineReporter.new(business_line).as_csv
send_data jobs_as_csv, filename: csv_filename
end
else
# TODO: make index show error message
render json: { error: "#{business_line_slug} not found" }, status: :not_found
format.json { queue_tasks }
end
end

Expand All @@ -56,7 +52,7 @@ def show

def update
if task
if task.complete_with_payload!(decision_issue_params, decision_date)
if task.complete_with_payload!(decision_issue_params, decision_date, current_user)
business_line.tasks.reload
render json: { task_filter_details: task_filter_details }, status: :ok
else
Expand All @@ -69,6 +65,29 @@ def update
end
end

def generate_report
return render "errors/404" unless can_generate_claim_history?
return requires_admin_access_redirect unless business_line.user_is_admin?(current_user)

respond_to do |format|
format.html { render "index" }
format.csv do
filter_params = change_history_params

unless filter_params[:report_type]
fail ActionController::ParameterMissing.new(:report_type), report_type_missing_message
end

parsed_filters = ChangeHistoryFilterParser.new(filter_params).parse_filters
events_as_csv = create_change_history_csv(parsed_filters)
filename = Time.zone.now.strftime("taskreport-%Y%m%d_%H%M.csv")
send_data events_as_csv, filename: filename, type: "text/csv", disposition: "attachment"
end
end
rescue ActionController::ParameterMissing => error
render json: { error: error.message }, status: :bad_request, content_type: "application/json"
end

def business_line_slug
allowed_params[:business_line_slug] || allowed_params[:decision_review_business_line_slug]
end
Expand Down Expand Up @@ -107,7 +126,8 @@ def task_filter_details

def business_line_config_options
{
tabs: included_tabs
tabs: included_tabs,
canGenerateClaimHistory: can_generate_claim_history?
}
end

Expand Down Expand Up @@ -184,6 +204,12 @@ def verify_access
redirect_to "/unauthorized"
end

def verify_business_line
unless business_line
render json: { error: "#{business_line_slug} not found" }, status: :not_found
end
end

def verify_veteran_record_access
if task.type == VeteranRecordRequest.name && !task.appeal.veteran&.accessible?
render(Caseflow::Error::ActionForbiddenError.new(
Expand All @@ -192,6 +218,21 @@ def verify_veteran_record_access
end
end

def csv_filename
Time.zone.now.strftime("#{business_line.url}-%Y%m%d.csv")
end

def report_type_missing_message
"param is missing or the value is empty: reportType"
end

def requires_admin_access_redirect
Rails.logger.info("User without admin access to the business line #{business_line} "\
"couldn't access #{request.original_url}")
session["return_to"] = request.original_url
redirect_to "/unauthorized"
end

def allowed_params
params.permit(
:decision_review_business_line_slug,
Expand All @@ -209,6 +250,22 @@ def allowed_params
)
end

def change_history_params
params.permit(
:report_type,
:status_report_type,
events: {},
timing: {},
statuses: {},
days_waiting: {},
decision_review_type: {},
issue_type: {},
issue_disposition: {},
personnel: {},
facility: {}
)
end

def power_of_attorney_data
{
representative_type: task.appeal&.representative_type,
Expand All @@ -219,4 +276,37 @@ def power_of_attorney_data
poa_last_synced_at: task.appeal&.poa_last_synced_at
}
end

def create_change_history_csv(filter_params)
create_metric_log do
base_url = "#{request.base_url}/decision_reviews/#{business_line.url}/tasks/"
events = ClaimHistoryService.new(business_line, filter_params).build_events
ChangeHistoryReporter.new(events, base_url, filter_params.to_h).as_csv
end
end

def create_metric_log
start_time = Time.zone.now
return_data = yield
end_time = Time.zone.now

MetricsService.store_record_metric(
SecureRandom.uuid,
{
name: "generate_report",
message: "Generate Change History Report #{Time.zone.today} #{RequestStore[:current_user].css_id}",
type: "info",
product: "vha",
attrs: { service: "decision_reviews", endpoint: "generate_report" },
sent_to: "rails_console",
start: start_time,
end: end_time,
duration: (end_time - start_time) * 1000,
additional_info: params[:filters].as_json
},
nil
)

return_data
end
end
8 changes: 8 additions & 0 deletions app/controllers/users_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ class UsersController < ApplicationController
def index
return filter_by_role if params[:role]
return filter_by_css_id_or_name if css_id
return filter_by_organization if params[:organization]

render json: {}, status: :ok
end
Expand Down Expand Up @@ -79,6 +80,13 @@ def filter_by_css_id_or_name
render json: { users: json_users(users) }
end

def filter_by_organization
finder = UserFinder.new(organization: params[:organization])
users = finder.users || []

render json: { users: json_users(users) }
end

# Depending on the route and the requested resource, the requested user's id could be sent as :id or :user_id
# ex from rake routes: user GET /users/:id or user_task_pages GET /users/:user_id/task_pages
def id
Expand Down
6 changes: 4 additions & 2 deletions app/models/claim_review.rb
Original file line number Diff line number Diff line change
Expand Up @@ -102,11 +102,13 @@ def handle_issues_with_no_decision_date!
# Guard clause to only perform this update for VHA claim reviews for now
return nil if benefit_type != "vha"

review_task = tasks.find { |task| task.is_a?(DecisionReviewTask) }

return nil unless review_task&.open?

if request_issues_without_decision_dates?
review_task = tasks.find { |task| task.is_a?(DecisionReviewTask) }
review_task&.on_hold!
elsif !request_issues_without_decision_dates?
review_task = tasks.find { |task| task.is_a?(DecisionReviewTask) }
review_task&.assigned!
end
end
Expand Down
4 changes: 2 additions & 2 deletions app/models/concerns/business_line_task.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
module BusinessLineTask
extend ActiveSupport::Concern

def complete_with_payload!(_decision_issue_params, _decision_date)
def complete_with_payload!(_decision_issue_params, _decision_date, user)
return false unless validate_task

update!(status: Constants.TASK_STATUSES.completed, closed_at: Time.zone.now)
update!(status: Constants.TASK_STATUSES.completed, closed_at: Time.zone.now, completed_by: user)
end

private
Expand Down
Loading

0 comments on commit 7dc0614

Please sign in to comment.