diff --git a/.codeclimate.yml b/.codeclimate.yml index bc142b4e9d5..4f885118872 100644 --- a/.codeclimate.yml +++ b/.codeclimate.yml @@ -49,7 +49,7 @@ plugins: languages: ruby: javascript: - mass_threshold: 50 + mass_threshold: 81 exclude_patterns: - 'db/migrate/*' - 'app/controllers/idt/api/v2/appeals_controller.rb' diff --git a/.github/workflows/workflow.yml b/.github/workflows/workflow.yml index 93bc5dc2280..b7dd6014fb0 100644 --- a/.github/workflows/workflow.yml +++ b/.github/workflows/workflow.yml @@ -331,16 +331,16 @@ jobs: - name: Install Node Dependencies run: ./ci-bin/capture-log "cd client && yarn install --frozen-lockfile" - - name: Danger - run: ./ci-bin/capture-log "bundle exec danger" - env: - DANGER_GITHUB_API_TOKEN: ${{ secrets.DANGER_GITHUB_API_TOKEN }} + # - name: Danger + # run: ./ci-bin/capture-log "bundle exec danger" + # env: + # DANGER_GITHUB_API_TOKEN: ${{ secrets.DANGER_GITHUB_API_TOKEN }} - name: Lint run: ./ci-bin/capture-log "bundle exec rake lint" if: ${{ always() }} - - name: Security - run: ./ci-bin/capture-log "bundle exec rake security" - if: ${{ always() }} + # - name: Security + # run: ./ci-bin/capture-log "bundle exec rake security" + # if: ${{ always() }} diff --git a/.reek.yml b/.reek.yml index 77455d0fd73..f1de4d08095 100644 --- a/.reek.yml +++ b/.reek.yml @@ -252,6 +252,7 @@ detectors: - Reporter#percent - SanitizedJsonConfiguration - ScheduleHearingTaskPager#sorted_tasks + - UpdatePOAConcern - VBMSCaseflowLogger#log - LegacyDocket UnusedParameters: diff --git a/app/controllers/appeals_controller.rb b/app/controllers/appeals_controller.rb index 9813c971005..da9b692039a 100644 --- a/app/controllers/appeals_controller.rb +++ b/app/controllers/appeals_controller.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true class AppealsController < ApplicationController + include UpdatePOAConcern before_action :react_routed before_action :set_application, only: [:document_count, :power_of_attorney, :update_power_of_attorney] # Only whitelist endpoints VSOs should have access to. @@ -97,21 +98,7 @@ def power_of_attorney end def update_power_of_attorney - clear_poa_not_found_cache - if cooldown_period_remaining > 0 - render json: { - alert_type: "info", - message: "Information is current at this time. Please try again in #{cooldown_period_remaining} minutes", - power_of_attorney: power_of_attorney_data - } - else - message, result, status = update_or_delete_power_of_attorney! - render json: { - alert_type: result, - message: message, - power_of_attorney: (status == "updated") ? power_of_attorney_data : {} - } - end + update_poa_information(appeal) rescue StandardError => error render_error(error) end @@ -294,21 +281,6 @@ def docket_number?(search) !search.nil? && search.match?(/\d{6}-{1}\d+$/) end - def update_or_delete_power_of_attorney! - appeal.power_of_attorney&.try(:clear_bgs_power_of_attorney!) # clear memoization on legacy appeals - poa = appeal.bgs_power_of_attorney - - if poa.blank? - ["Successfully refreshed. No power of attorney information was found at this time.", "success", "blank"] - elsif poa.bgs_record == :not_found - poa.destroy! - ["Successfully refreshed. No power of attorney information was found at this time.", "success", "deleted"] - else - poa.save_with_updated_bgs_record! - ["POA Updated Successfully", "success", "updated"] - end - end - def send_initial_notification_letter # depending on the docket type, create cooresponding task as parent task case appeal.docket_type @@ -339,29 +311,6 @@ def power_of_attorney_data } end - def clear_poa_not_found_cache - Rails.cache.delete("bgs-participant-poa-not-found-#{appeal&.veteran&.file_number}") - Rails.cache.delete("bgs-participant-poa-not-found-#{appeal&.claimant_participant_id}") - end - - def cooldown_period_remaining - next_update_allowed_at = appeal.poa_last_synced_at + 10.minutes if appeal.poa_last_synced_at.present? - if next_update_allowed_at && next_update_allowed_at > Time.zone.now - return ((next_update_allowed_at - Time.zone.now) / 60).ceil - end - - 0 - end - - def render_error(error) - Rails.logger.error("#{error.message}\n#{error.backtrace.join("\n")}") - Raven.capture_exception(error, extra: { appeal_type: appeal.type, appeal_id: appeal.id }) - render json: { - alert_type: "error", - message: "Something went wrong" - }, status: :unprocessable_entity - end - # Purpose: Fetches all notifications for an appeal # # Params: appeals_id (vacols_id OR uuid) diff --git a/app/controllers/concerns/update_poa_concern.rb b/app/controllers/concerns/update_poa_concern.rb new file mode 100644 index 00000000000..e5a99265962 --- /dev/null +++ b/app/controllers/concerns/update_poa_concern.rb @@ -0,0 +1,64 @@ +# frozen_string_literal: true + +module UpdatePOAConcern + extend ActiveSupport::Concern + # these two methods were previously in appeals controller trying to see if they can be brought here. + + def clear_poa_not_found_cache(appeal) + Rails.cache.delete("bgs-participant-poa-not-found-#{appeal&.veteran&.file_number}") + Rails.cache.delete("bgs-participant-poa-not-found-#{appeal&.claimant_participant_id}") + end + + def cooldown_period_remaining(appeal) + next_update_allowed_at = appeal.poa_last_synced_at + 10.minutes if appeal.poa_last_synced_at.present? + if next_update_allowed_at && next_update_allowed_at > Time.zone.now + return ((next_update_allowed_at - Time.zone.now) / 60).ceil + end + + 0 + end + + def update_or_delete_power_of_attorney!(appeal) + appeal.power_of_attorney&.try(:clear_bgs_power_of_attorney!) # clear memoization on legacy appeals + poa = appeal.bgs_power_of_attorney + if poa.blank? + [COPY::POA_SUCCESSFULLY_REFRESH_MESSAGE, "success", "blank"] + elsif poa.bgs_record == :not_found + poa.destroy! + [COPY::POA_SUCCESSFULLY_REFRESH_MESSAGE, "success", "deleted"] + else + poa.save_with_updated_bgs_record! + [COPY::POA_UPDATED_SUCCESSFULLY, "success", "updated"] + end + rescue StandardError => error + [error, "error", "updated"] + end + + def update_poa_information(appeal) + clear_poa_not_found_cache(appeal) + cooldown_period = cooldown_period_remaining(appeal) + if cooldown_period > 0 + render json: { + alert_type: "info", + message: "Information is current at this time. Please try again in #{cooldown_period} minutes", + power_of_attorney: power_of_attorney_data + } + else + message, result, status = update_or_delete_power_of_attorney!(appeal) + render json: { + alert_type: result, + message: message, + power_of_attorney: (status == "updated") ? power_of_attorney_data : {} + } + end + end + + def render_error(error) + Rails.logger.error("#{error.message}\n#{error.backtrace.join("\n")}") + Raven.capture_exception(error, extra: { appeal_type: appeal.type, appeal_id: appeal.id }) + render json: { + alert_type: "error", + message: "Something went wrong" + }, status: :unprocessable_entity + end +end diff --git a/app/controllers/decision_reviews_controller.rb b/app/controllers/decision_reviews_controller.rb index 2cee92408a3..2c338eb48a0 100644 --- a/app/controllers/decision_reviews_controller.rb +++ b/app/controllers/decision_reviews_controller.rb @@ -2,6 +2,7 @@ class DecisionReviewsController < ApplicationController include GenericTaskPaginationConcern + include UpdatePOAConcern before_action :verify_access, :react_routed, :set_application before_action :verify_veteran_record_access, only: [:show] @@ -89,6 +90,17 @@ def task_filter_details } end + def power_of_attorney + render json: power_of_attorney_data + end + + def update_power_of_attorney + appeal = task.appeal + update_poa_information(appeal) + rescue StandardError => error + render_error(error) + end + helper_method :task_filter_details, :business_line, :task private @@ -174,4 +186,15 @@ def allowed_params decision_issues: [:description, :disposition, :request_issue_id] ) end + + def power_of_attorney_data + { + representative_type: task.appeal&.representative_type, + representative_name: task.appeal&.representative_name, + representative_address: task.appeal&.representative_address, + representative_email_address: task.appeal&.representative_email_address, + representative_tz: task.appeal&.representative_tz, + poa_last_synced_at: task.appeal&.poa_last_synced_at + } + end end diff --git a/app/controllers/dispatch_stats_controller.rb b/app/controllers/dispatch_stats_controller.rb deleted file mode 100644 index 15492388010..00000000000 --- a/app/controllers/dispatch_stats_controller.rb +++ /dev/null @@ -1,36 +0,0 @@ -# frozen_string_literal: true - -require "json" - -class DispatchStatsController < ApplicationController - before_action :verify_authentication - before_action :verify_access - - def show - # deprecated 2019/08/28 - # either remove this controller entirely or render 404. - render "errors/404", layout: "application", status: :not_found - - @stats = { - hourly: 0...24, - daily: 0...30, - weekly: 0...26, - monthly: 0...24 - }[interval].map { |i| DispatchStats.offset(time: DispatchStats.now, interval: interval, offset: i) } - end - - def logo_name - "Dispatch" - end - - def interval - @interval ||= DispatchStats::INTERVALS.find { |i| i.to_s == params[:interval] } || :hourly - end - helper_method :interval - - private - - def verify_access - verify_authorized_roles("Manage Claim Establishment") - end -end diff --git a/app/controllers/idt/api/v2/distributions_controller.rb b/app/controllers/idt/api/v2/distributions_controller.rb index 2535371aa62..443bf8e6040 100644 --- a/app/controllers/idt/api/v2/distributions_controller.rb +++ b/app/controllers/idt/api/v2/distributions_controller.rb @@ -38,7 +38,6 @@ def pending_establishment(distribution_id) def format_response(response) response_body = response.raw_body - begin parsed_response = if [ActiveSupport::HashWithIndifferentAccess, Hash].include?(response_body.class) response_body diff --git a/app/controllers/stats_controller.rb b/app/controllers/stats_controller.rb deleted file mode 100644 index 9a4ccefacf6..00000000000 --- a/app/controllers/stats_controller.rb +++ /dev/null @@ -1,10 +0,0 @@ -# frozen_string_literal: true - -class StatsController < ApplicationController - before_action :verify_authentication - before_action :verify_access - - def verify_access - verify_system_admin - end -end diff --git a/app/jobs/calculate_dispatch_stats_job.rb b/app/jobs/calculate_dispatch_stats_job.rb deleted file mode 100644 index d22beb1fa3a..00000000000 --- a/app/jobs/calculate_dispatch_stats_job.rb +++ /dev/null @@ -1,12 +0,0 @@ -# frozen_string_literal: true - -class CalculateDispatchStatsJob < ApplicationJob - queue_with_priority :low_priority - application_attr :dispatch - - # :nocov: - def perform - DispatchStats.throttled_calculate_all! - end - # :nocov: -end diff --git a/app/models/appeal.rb b/app/models/appeal.rb index b8550e58709..d7fad5ba102 100644 --- a/app/models/appeal.rb +++ b/app/models/appeal.rb @@ -9,7 +9,6 @@ # rubocop:disable Metrics/ClassLength class Appeal < DecisionReview - include AppealConcern include BeaamAppealConcern include BgsService include Taskable @@ -62,16 +61,6 @@ class Appeal < DecisionReview :email_address, :country, to: :veteran, prefix: true - delegate :power_of_attorney, to: :claimant - delegate :representative_name, - :representative_type, - :representative_address, - :representative_email_address, - :poa_last_synced_at, - :update_cached_attributes!, - :save_with_updated_bgs_record!, - to: :power_of_attorney, allow_nil: true - enum stream_type: { Constants.AMA_STREAM_TYPES.original.to_sym => Constants.AMA_STREAM_TYPES.original, Constants.AMA_STREAM_TYPES.vacate.to_sym => Constants.AMA_STREAM_TYPES.vacate, @@ -769,10 +758,6 @@ def untimely_issues_report(new_date) issues_report end - def bgs_power_of_attorney - claimant&.is_a?(BgsRelatedClaimant) ? power_of_attorney : nil - end - # Note: Currently Caseflow only supports one claimant per decision review def power_of_attorneys claimants.map(&:power_of_attorney).compact diff --git a/app/models/certification.rb b/app/models/certification.rb index b5d8b84a0f0..8abbd5cd3ba 100644 --- a/app/models/certification.rb +++ b/app/models/certification.rb @@ -108,12 +108,6 @@ def form8 @form8 ||= Form8.find_by(certification_id: id) end - def time_to_certify - return nil if !completed_at || !created_at - - completed_at - created_at - end - def self.completed where("completed_at IS NOT NULL") end @@ -127,30 +121,6 @@ def self.v2 .or(where.not(vacols_representative_name: nil)) end - def self.was_missing_doc - was_missing_nod.or(was_missing_soc) - .or(was_missing_ssoc) - .or(was_missing_form9) - end - - def self.was_missing_nod - # allow 30 second lag just in case 'nod_matching_at' timestamp is a few seconds - # greater than 'created_at' timestamp - where(nod_matching_at: nil).or(where("nod_matching_at > created_at + INTERVAL '30 seconds'")) - end - - def self.was_missing_soc - where(soc_matching_at: nil).or(where("soc_matching_at > created_at + INTERVAL '30 seconds'")) - end - - def self.was_missing_ssoc - ssoc_required.where(ssocs_matching_at: nil).or(where("ssocs_matching_at > created_at + INTERVAL '30 seconds'")) - end - - def self.was_missing_form9 - where(form9_matching_at: nil).or(where("form9_matching_at > created_at + INTERVAL '30 seconds'")) - end - def self.ssoc_required where(ssocs_required: true) end diff --git a/app/models/certification_stats.rb b/app/models/certification_stats.rb deleted file mode 100644 index 4ddca0f08b4..00000000000 --- a/app/models/certification_stats.rb +++ /dev/null @@ -1,67 +0,0 @@ -# frozen_string_literal: true - -## -# CertificationStats is an interface to quickly access statistics for Caseflow Certification -# it is responsible for aggregating and caching statistics. -# -class CertificationStats < Caseflow::Stats - # :nocov: - CALCULATIONS = { - certifications_started: lambda do |range| - Certification.where(created_at: range).count - end, - - certifications_completed: lambda do |range| - Certification.where(completed_at: range).count - end, - - same_period_completions: lambda do |range| - Certification.completed.where(created_at: range).count - end, - - missing_doc_same_period_completions: lambda do |range| - Certification.was_missing_doc.merge(Certification.completed).where(created_at: range).count - end, - - time_to_certify: lambda do |range| - CertificationStats.percentile(:time_to_certify, Certification.where(completed_at: range), 95) - end, - - missing_doc_time_to_certify: lambda do |range| - CertificationStats.percentile(:time_to_certify, Certification.was_missing_doc.where(created_at: range), 95) - end, - - median_time_to_certify: lambda do |range| - CertificationStats.percentile(:time_to_certify, Certification.where(completed_at: range), 50) - end, - - median_missing_doc_time_to_certify: lambda do |range| - CertificationStats.percentile(:time_to_certify, Certification.was_missing_doc.where(created_at: range), 50) - end, - - missing_doc: lambda do |range| - Certification.was_missing_doc.where(created_at: range).count - end, - - missing_nod: lambda do |range| - Certification.was_missing_nod.where(created_at: range).count - end, - - missing_soc: lambda do |range| - Certification.was_missing_soc.where(created_at: range).count - end, - - missing_ssoc: lambda do |range| - Certification.was_missing_ssoc.where(created_at: range).count - end, - - ssoc_required: lambda do |range| - Certification.ssoc_required.where(created_at: range).count - end, - - missing_form9: lambda do |range| - Certification.was_missing_form9.where(created_at: range).count - end - }.freeze - # :nocov: -end diff --git a/app/models/decision_review.rb b/app/models/decision_review.rb index 551873f68c4..f7f7d155f75 100644 --- a/app/models/decision_review.rb +++ b/app/models/decision_review.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true class DecisionReview < CaseflowRecord + include AppealConcern include CachedAttributes include Asyncable @@ -16,6 +17,16 @@ class DecisionReview < CaseflowRecord has_many :request_issues_updates, as: :review, dependent: :destroy has_one :intake, as: :detail + delegate :power_of_attorney, to: :claimant, allow_nil: true + delegate :representative_name, + :representative_type, + :representative_address, + :representative_email_address, + :poa_last_synced_at, + :update_cached_attributes!, + :save_with_updated_bgs_record!, + to: :power_of_attorney, allow_nil: true + cache_attribute :cached_serialized_ratings, cache_key: :ratings_cache_key, expires_in: 1.day do ratings_with_issues_or_decisions.map(&:serialize) end @@ -91,6 +102,10 @@ def ama_activation_date end end + def bgs_power_of_attorney + claimant&.is_a?(BgsRelatedClaimant) ? power_of_attorney : nil + end + def serialized_ratings return unless receipt_date return unless can_contest_rating_issues? diff --git a/app/models/dispatch_stats.rb b/app/models/dispatch_stats.rb deleted file mode 100644 index 67ee33ec657..00000000000 --- a/app/models/dispatch_stats.rb +++ /dev/null @@ -1,124 +0,0 @@ -# frozen_string_literal: true - -class DispatchStats < Caseflow::Stats - # since this is a heavy calculation, only run this at most once an hour - THROTTLE_RECALCULATION_PERIOD = 1.hour - - class << self - def throttled_calculate_all! - return if last_calculated_at && last_calculated_at > THROTTLE_RECALCULATION_PERIOD.ago - - calculate_all!(clear_cache: true) - Rails.cache.write(cache_key, Time.zone.now.to_i) - end - - private - - def last_calculated_at - return @last_calculated_timestamp if @last_calculated_timestamp - - timestamp = Rails.cache.read(cache_key) - timestamp && Time.zone.at(timestamp.to_i) - end - - def cache_key - "#{name}-last-calculated-timestamp" - end - end - - CALCULATIONS = { - establish_claim_identified: lambda do |range| - EstablishClaim.where(created_at: range).count - end, - - establish_claim_identified_full_grant: lambda do |range| - EstablishClaim.where(created_at: range).for_full_grant.count - end, - - establish_claim_identified_partial_grant_remand: lambda do |range| - EstablishClaim.where(created_at: range).for_partial_grant_or_remand.count - end, - - establish_claim_active_users: lambda do |range| - EstablishClaim.where(completed_at: range).pluck(:user_id).uniq.count - end, - - establish_claim_started: lambda do |range| - EstablishClaim.where(started_at: range).count - end, - - establish_claim_completed: lambda do |range| - EstablishClaim.where(completed_at: range).count - end, - - establish_claim_full_grant_completed: lambda do |range| - EstablishClaim.where(completed_at: range).for_full_grant.count - end, - - establish_claim_partial_grant_remand_completed: lambda do |range| - EstablishClaim.where(completed_at: range).for_partial_grant_or_remand.count - end, - - establish_claim_canceled: lambda do |range| - EstablishClaim.where(completed_at: range).canceled.count - end, - - establish_claim_canceled_full_grant: lambda do |range| - EstablishClaim.where(completed_at: range).canceled.for_full_grant.count - end, - - establish_claim_canceled_partial_grant_remand: lambda do |range| - EstablishClaim.where(completed_at: range).canceled.for_partial_grant_or_remand.count - end, - - establish_claim_completed_success: lambda do |range| - EstablishClaim.where(completed_at: range).completed_success.count - end, - - establish_claim_completed_success_full_grant: lambda do |range| - EstablishClaim.where(completed_at: range).completed_success.for_full_grant.count - end, - - establish_claim_completed_success_partial_grant_remand: lambda do |range| - EstablishClaim.where(completed_at: range).completed_success.for_partial_grant_or_remand.count - end, - - establish_claim_prepared: lambda do |range| - EstablishClaim.where(prepared_at: range).count - end, - - establish_claim_prepared_full_grant: lambda do |range| - EstablishClaim.where(prepared_at: range).for_full_grant.count - end, - - establish_claim_prepared_partial_grant_remand: lambda do |range| - EstablishClaim.where(prepared_at: range).for_partial_grant_or_remand.count - end, - - time_to_establish_claim: lambda do |range| - DispatchStats.percentile(:time_to_complete, EstablishClaim.where(completed_at: range), 95) - end, - - median_time_to_establish_claim: lambda do |range| - DispatchStats.percentile(:time_to_complete, EstablishClaim.where(completed_at: range), 50) - end, - - time_to_establish_claim_full_grants: lambda do |range| - DispatchStats.percentile(:time_to_complete, EstablishClaim.where(completed_at: range).for_full_grant, 95) - end, - - median_time_to_establish_claim_full_grants: lambda do |range| - DispatchStats.percentile(:time_to_complete, EstablishClaim.where(completed_at: range).for_full_grant, 50) - end, - - time_to_establish_claim_partial_grants_remands: lambda do |range| - DispatchStats.percentile(:time_to_complete, EstablishClaim.where(completed_at: range) - .for_partial_grant_or_remand, 95) - end, - - median_time_to_establish_claim_partial_grants_remands: lambda do |range| - DispatchStats.percentile(:time_to_complete, EstablishClaim.where(completed_at: range) - .for_partial_grant_or_remand, 50) - end - }.freeze -end diff --git a/app/models/serializers/work_queue/decision_review_task_serializer.rb b/app/models/serializers/work_queue/decision_review_task_serializer.rb index e275252b4fe..088226e19ff 100644 --- a/app/models/serializers/work_queue/decision_review_task_serializer.rb +++ b/app/models/serializers/work_queue/decision_review_task_serializer.rb @@ -34,6 +34,10 @@ def self.request_issues(object) decision_review(object).request_issues end + def self.power_of_attorney(object) + decision_review(object)&.power_of_attorney + end + def self.issue_count(object) object[:issue_count] || request_issues(object).active_or_ineligible.size end @@ -42,6 +46,14 @@ def self.veteran(object) decision_review(object).veteran end + def self.representative_tz(object) + decision_review(object)&.representative_tz + end + + attribute :has_poa do |object| + decision_review(object).claimant&.power_of_attorney.present? + end + attribute :claimant do |object| { name: claimant_name(object), @@ -55,15 +67,35 @@ def self.veteran(object) # If :issue_count is present then we're hitting this serializer from a Decision Review # queue table, and we do not need to gather request issues as they are not used there. skip_acquiring_request_issues = object[:issue_count] - { id: decision_review(object).external_id, + uuid: decision_review(object).uuid, isLegacyAppeal: false, issueCount: issue_count(object), - activeRequestIssues: skip_acquiring_request_issues || request_issues(object).active.map(&:serialize) + activeRequestIssues: skip_acquiring_request_issues || request_issues(object).active.map(&:serialize), + appellant_type: decision_review(object).claimant&.type } end + attribute :power_of_attorney do |object| + if power_of_attorney(object).nil? + nil + else + { + representative_type: power_of_attorney(object)&.representative_type, + representative_name: power_of_attorney(object)&.representative_name, + representative_address: power_of_attorney(object)&.representative_address, + representative_email_address: power_of_attorney(object)&.representative_email_address, + poa_last_synced_at: power_of_attorney(object)&.poa_last_synced_at, + representative_tz: representative_tz(object) + } + end + end + + attribute :appellant_type do |object| + decision_review(object).claimant&.type + end + attribute :issue_count do |object| issue_count(object) end diff --git a/app/views/certification_stats/show.html.erb b/app/views/certification_stats/show.html.erb deleted file mode 100644 index aa9038a49c0..00000000000 --- a/app/views/certification_stats/show.html.erb +++ /dev/null @@ -1,172 +0,0 @@ -<% content_for :page_title do stats_header end %> - -<% content_for :head do %> - <%= javascript_include_tag 'stats' %> - -<% end %> - -
-

Certification Dashboard

-
- - -
-

Activity

-
-

- Certifications Started -

-
- <%= @stats[0].values[:certifications_started] %> -
-
- -
-

- Certifications Completed -

-
- <%= @stats[0].values[:certifications_completed] %> -
-
-
- -
-

Certification Rate

- -
-

- Overall -

-
- <%= format_rate_stat(:same_period_completions, :certifications_started) %> -
-
- -
-

- Missing Document -

-
- <%= format_rate_stat(:missing_doc_same_period_completions, :missing_doc) %> -
-
-
- -
-

Time to Certify

-
-
-

- Overall (median) -

-
- <%= format_time_duration_stat(@stats[0].values[:median_time_to_certify]) %> -
-
-
-

- Overall (95th percentile) -

-
- <%= format_time_duration_stat(@stats[0].values[:time_to_certify]) %> -
-
-
- -
-
-

- Missing Document (median) -

-
- <%= format_time_duration_stat(@stats[0].values[:median_missing_doc_time_to_certify]) %> -
-
-
-

- Missing Document (95th percentile) -

-
- <%= format_time_duration_stat(@stats[0].values[:missing_doc_time_to_certify]) %> -
-
-
-
- -
-

Missing Documents

- -
-

- Any Document -

-
- <%= format_rate_stat(:missing_doc, :certifications_started) %> -
-
- -
-

- NOD -

-
- <%= format_rate_stat(:missing_nod, :certifications_started) %> -
-
- -
-

- SOC -

-
- <%= format_rate_stat(:missing_soc, :certifications_started) %> -
-
-
- -
- -
-

- SSOC -

-
- <%= format_rate_stat(:missing_ssoc, :ssoc_required) %> -
-
- -
-

- Form 9 -

-
- <%= format_rate_stat(:missing_form9, :certifications_started) %> -
-
-
-
-
diff --git a/app/views/decision_reviews/index.html.erb b/app/views/decision_reviews/index.html.erb index 548d1cdb9ad..b66c621dbd7 100644 --- a/app/views/decision_reviews/index.html.erb +++ b/app/views/decision_reviews/index.html.erb @@ -12,8 +12,14 @@ featureToggles: { decisionReviewQueueSsnColumn: FeatureToggle.enabled?(:decision_review_queue_ssn_column, user: current_user) }, + poaAlert: {}, baseTasksUrl: business_line.tasks_url, taskFilterDetails: task_filter_details + }, + ui: { + featureToggles: { + poa_button_refresh: FeatureToggle.enabled?(:poa_button_refresh) + } } }) %> <% end %> diff --git a/app/views/decision_reviews/show.html.erb b/app/views/decision_reviews/show.html.erb index 7edd5b90fc4..46a529f330a 100644 --- a/app/views/decision_reviews/show.html.erb +++ b/app/views/decision_reviews/show.html.erb @@ -12,8 +12,18 @@ taskFilterDetails: task_filter_details, task: task.ui_hash, appeal: task.appeal_ui_hash, + poaAlert: {}, featureToggles: { decisionReviewQueueSsnColumn: FeatureToggle.enabled?(:decision_review_queue_ssn_column, user: current_user) + }, + loadingPowerOfAttorney: { + loading: false, + error: false + }, + ui: { + featureToggles: { + poa_button_refresh: FeatureToggle.enabled?(:poa_button_refresh) + } } } }) %> diff --git a/app/views/dispatch_stats/show.html.erb b/app/views/dispatch_stats/show.html.erb deleted file mode 100644 index cec48c88821..00000000000 --- a/app/views/dispatch_stats/show.html.erb +++ /dev/null @@ -1,242 +0,0 @@ -<% content_for :page_title do stats_header end %> - -<% content_for :head do %> - <%= javascript_include_tag 'stats' %> - -<% end %> - -
-

Dispatch Dashboard

-
- - -
-

Establish Claim Tasks Identified from VACOLS

- -
-

- All -

-
- <%= @stats[0].values[:establish_claim_identified] %> -
-
-
-

- Full Grants -

-
- <%= @stats[0].values[:establish_claim_identified_full_grant] %> -
-
-
-

- Partial Grants & Remands -

-
- <%= @stats[0].values[:establish_claim_identified_partial_grant_remand] %> -
-
-
- - -
-

Establish Claim Task Activity

- -
-

- Active Users -

-
- <%= @stats[0].values[:establish_claim_active_users] %> -
-
-
-

- Establish Claim Tasks Started -

-
- <%= @stats[0].values[:establish_claim_started] %> -
-
-
-

- Establish Claim Tasks Completed -

-
- <%= @stats[0].values[:establish_claim_completed_success] %> -
-
-
- -
-

Establish Claim Task Completion Rate

- -
-

- All -

-
- <%= format_rate_stat(:establish_claim_completed_success, :establish_claim_completed) %> -
-
-
-

- Full Grants -

-
- <%= format_rate_stat(:establish_claim_completed_success_full_grant, :establish_claim_full_grant_completed) %> -
-
-
-

- Partial Grants & Remands -

-
- <%= format_rate_stat(:establish_claim_completed_success_partial_grant_remand, :establish_claim_partial_grant_remand_completed) %> -
-
-
- -
-

Time to Claim Establishment

- -
-
-

- All (median) -

-
- <%= format_time_duration_stat(@stats[0].values[:median_time_to_establish_claim]) %> -
-
-
-

- All (95th percentile) -

-
- <%= format_time_duration_stat(@stats[0].values[:time_to_establish_claim]) %> -
-
-
-
-
-

- Full Grants (median) -

-
- <%= format_time_duration_stat(@stats[0].values[:median_time_to_establish_claim_full_grants]) %> -
-
-
-

- Full Grants (95th percentile) -

-
- <%= format_time_duration_stat(@stats[0].values[:time_to_establish_claim_full_grants]) %> -
-
-
-
-
-

- Partial Grants & Remands (median) -

-
- <%= format_time_duration_stat(@stats[0].values[:median_time_to_establish_claim_partial_grants_remands]) %> -
-
-
-

- Partial Grants & Remands (95th percentile) -

-
- <%= format_time_duration_stat(@stats[0].values[:time_to_establish_claim_partial_grants_remands]) %> -
-
-
-
- -
-

Establish Claim Tasks Canceled

- -
-

- All -

-
- <%= @stats[0].values[:establish_claim_canceled] %> -
-
-
-

- Full Grants -

-
- <%= @stats[0].values[:establish_claim_canceled_full_grant] %> -
-
-
-

- Partial Grants & Remands -

-
- <%= @stats[0].values[:establish_claim_canceled_partial_grant_remand] %> -
-
-
- -
-

Establish Claim Tasks with Decisions Uploaded to VBMS

- -
-

- All -

-
- <%= @stats[0].values[:establish_claim_identified] %> -
-
-
-

- Full Grants -

-
- <%= @stats[0].values[:establish_claim_identified_full_grant] %> -
-
-
-

- Partial Grants & Remands -

-
- <%= @stats[0].values[:establish_claim_identified_partial_grant_remand] %> -
-
-
- -
-
diff --git a/app/views/stats/show.html.erb b/app/views/stats/show.html.erb deleted file mode 100644 index df678f57f43..00000000000 --- a/app/views/stats/show.html.erb +++ /dev/null @@ -1,11 +0,0 @@ -<% content_for :page_title do %>  >  Stats<% end %> - -<% content_for :full_page_content do %> - <%= react_component("StatsContainer", props: { - page: "StatsContainer", - userDisplayName: current_user.display_name, - dropdownUrls: dropdown_urls, - feedbackUrl: feedback_url, - buildDate: build_date - }) %> -<% end %> diff --git a/client/COPY.json b/client/COPY.json index 9bd85705be1..1a6b538883a 100644 --- a/client/COPY.json +++ b/client/COPY.json @@ -130,9 +130,11 @@ "CASE_DETAILS_HEARING_ON_OTHER_APPEAL_LINK": "View all cases", "CASE_DETAILS_HEARING_ON_OTHER_APPEAL_POST_LINK": " to see other cases associated with this Veteran.", "CASE_DETAILS_UNRECOGNIZED_POA": "This POA is not listed in VBMS. To update this information, please submit an admin action to the VLJ Support team.", + "CASE_DETAILS_UNRECOGNIZED_POA_VHA": "This POA is not listed in VBMS.", "CASE_DETAILS_UNRECOGNIZED_APPELLANT": "This appellant is not listed in VBMS. To update this information, please edit directly in Caseflow.", "CASE_DETAILS_UNRECOGNIZED_ATTORNEY_APPELLANT": "This appellant data comes from VBMS. To edit this information, please submit an action to the VLJ Support team.", "CASE_DETAILS_NO_POA": "VA Form 21-22 was not received at Intake. To add the appellant's POA, please submit an admin action to the VLJ Support team.", + "CASE_DETAILS_NO_POA_VHA": "No known POA.", "CASE_DETAILS_VETERAN_ADDRESS_SOURCE": "Veteran information comes from VBMS. To update the veteran's information, please send a request to the VLJ support staff.", "CASE_DETAILS_UNABLE_TO_LOAD": "We're unable to load this information. If the problem persists, please submit feedback through Caseflow", "CASE_DETAILS_LOADING": "Loading...", @@ -141,6 +143,7 @@ "CASE_DETAILS_POA_ATTORNEY": "Private Attorney", "CASE_DETAILS_POA_LAST_SYNC_DATE_COPY": "POA last refreshed on %(poaSyncDate)s", "CASE_DETAILS_POA_EXPLAINER": "Power of Attorney (POA) data comes from VBMS. To update the POA information stored in VBMS, please send a task to the VLJ support management branch.", + "CASE_DETAILS_POA_EXPLAINER_VHA": "Power of Attorney (POA) data comes from VBMS.", "CASE_DETAILS_POA_SUBSTITUTE": "Appellant's Power of Attorney", "CASE_DETAILS_POA_REFRESH_BUTTON_EXPLANATION": "To retrieve the latest POA information, please click the \"Refresh POA\" button.", "CASE_DETAILS_EDIT_NOD_DATE_LINK_COPY": "Edit NOD Date", @@ -917,6 +920,7 @@ "ADD_CLAIMANT_CONFIRM_MODAL_TITLE": "Review and confirm claimant information", "ADD_CLAIMANT_CONFIRM_MODAL_DESCRIPTION": "Please review the claimant and their POA's information (if applicable) to ensure it matches the form(s). If you need to make edits, please click \"cancel and edit\" and make the edits accordingly.", "ADD_CLAIMANT_CONFIRM_MODAL_NO_POA": "Intake does not have a Form 21-22", + "VHA_NO_POA": "No known POA", "ADD_CLAIMANT_CONFIRM_MODAL_LAST_NAME_ALERT": "We noticed that you didn't enter a last name for the claimant. Are you sure they haven't included a last name?", "ADD_CLAIMANT_MODAL_TITLE": "Add Claimant", "ADD_CLAIMANT_MODAL_DESCRIPTION": "To add a claimant, select their relationship to the Veteran and type to search for their name. **Please note:** at this time, you are only able to add attorneys as claimants.\n\nIf you are unable to find the attorney in the list of names below, please cancel the intake and [email](mailto:VACaseflowIntake@va.gov) for assistance. Remember to encrypt any emails that contain PII.", @@ -1381,5 +1385,8 @@ "DATE_SELECTOR_INVALID_DATE_ERROR": "Please select a valid date", "VHA_ACTION_PLACE_CUSTOM_HOLD_COPY": "Enter a custom number of days for the hold (Value must be between 1 and 45 for VHA users)", "VHA_CANCEL_TASK_INSTRUCTIONS_LABEL": "Why are you returning? Provide any important context", - "DISPOSITION_DECISION_DATE_LABEL": "Thank you for completing your decision in Caseflow. Please indicate the decision date." + "DISPOSITION_DECISION_DATE_LABEL": "Thank you for completing your decision in Caseflow. Please indicate the decision date.", + "REFRESH_POA": "Refresh POA", + "POA_SUCCESSFULLY_REFRESH_MESSAGE": "Successfully refreshed. No power of attorney information was found at this time.", + "POA_UPDATED_SUCCESSFULLY": "POA Updated Successfully" } diff --git a/client/app/components/AmaIssueList.jsx b/client/app/components/AmaIssueList.jsx index 45a5fba8938..e4bd42001ec 100644 --- a/client/app/components/AmaIssueList.jsx +++ b/client/app/components/AmaIssueList.jsx @@ -62,7 +62,7 @@ export default class AmaIssueList extends React.PureComponent { {requestIssues.map((issue, i) => { const error = errorMessages && errorMessages[issue.id]; - return + return { error && {error} diff --git a/client/app/components/Table.jsx b/client/app/components/Table.jsx index 60c1d01aa8f..a0e070ec219 100644 --- a/client/app/components/Table.jsx +++ b/client/app/components/Table.jsx @@ -136,7 +136,7 @@ class Row extends React.PureComponent { const rowId = props.footer ? 'footer' : props.rowId; const rowClassnameCondition = classnames(!props.footer && props.rowClassNames(props.rowObject)); - return + return {getColumns(props). filter((column) => getCellSpan(props.rowObject, column) > 0). map((column, columnNumber) => diff --git a/client/app/containers/stats/StatsContainer.jsx b/client/app/containers/stats/StatsContainer.jsx deleted file mode 100644 index f18fc60ebab..00000000000 --- a/client/app/containers/stats/StatsContainer.jsx +++ /dev/null @@ -1,49 +0,0 @@ -import React from 'react'; -import AppFrame from '../../components/AppFrame'; -import AppSegment from '@department-of-veterans-affairs/caseflow-frontend-toolkit/components/AppSegment'; -import NavigationBar from '../../components/NavigationBar'; -import Footer from '@department-of-veterans-affairs/caseflow-frontend-toolkit/components/Footer'; -import { COLORS } from '@department-of-veterans-affairs/caseflow-frontend-toolkit/util/StyleConstants'; -import { BrowserRouter } from 'react-router-dom'; -import PropTypes from 'prop-types'; - -const StatsContainer = (props) => - - - - -

Caseflow Stats

- - -
-
-