-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adds a mechanisim for admins to upload a csv of known risky trns and ninos that will cause claims with these attributes to be flagged in the admin ui. Flagged values can be removed by uploading a CSV without those values. We've added some new functionality to the task/index notification banner. The banner now supports rendering multiple messages. If there is a single banner notification is falls back to the original view and renders a p tag, with multiple notifications it now renders a list.
- Loading branch information
Showing
30 changed files
with
815 additions
and
18 deletions.
There are no files selected for viewing
25 changes: 25 additions & 0 deletions
25
app/controllers/admin/fraud_risk_csv_downloads_controller.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
module Admin | ||
class FraudRiskCsvDownloadsController < BaseAdminController | ||
before_action :ensure_service_operator | ||
|
||
def show | ||
respond_to do |format| | ||
format.csv do | ||
send_data(csv, filename: "fraud_risk.csv") | ||
end | ||
end | ||
end | ||
|
||
private | ||
|
||
def csv | ||
CSV.generate do |csv| | ||
csv << %w[field value] | ||
|
||
RiskIndicator.order(created_at: :asc).pluck(:field, :value).each do |row| | ||
csv << row | ||
end | ||
end | ||
end | ||
end | ||
end |
28 changes: 28 additions & 0 deletions
28
app/controllers/admin/fraud_risk_csv_uploads_controller.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
module Admin | ||
class FraudRiskCsvUploadsController < BaseAdminController | ||
before_action :ensure_service_operator | ||
|
||
def new | ||
@form = FraudRiskCsvUploadForm.new | ||
end | ||
|
||
def create | ||
@form = FraudRiskCsvUploadForm.new(fraud_risk_csv_upload_params) | ||
|
||
if @form.save | ||
redirect_to( | ||
new_admin_fraud_risk_csv_upload_path, | ||
notice: "Fraud prevention list uploaded successfully." | ||
) | ||
else | ||
render :new | ||
end | ||
end | ||
|
||
private | ||
|
||
def fraud_risk_csv_upload_params | ||
params.fetch(:admin_fraud_risk_csv_upload_form, {}).permit(:file) | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
module Admin | ||
class FraudRiskCsvUploadForm | ||
include ActiveModel::Model | ||
|
||
attr_accessor :file | ||
|
||
validates :file, presence: {message: "CSV file is required"} | ||
|
||
validate :csv_has_required_headers, if: -> { file.present? } | ||
|
||
validate :all_records_are_valid, if: -> { file.present? && csv_has_required_headers? } | ||
|
||
def initialize(params = {}) | ||
super | ||
end | ||
|
||
def save | ||
return false unless valid? | ||
|
||
ApplicationRecord.transaction do | ||
RiskIndicator.where.not(id: records.map(&:id)).destroy_all | ||
|
||
records.each(&:save!) | ||
end | ||
|
||
true | ||
end | ||
|
||
private | ||
|
||
def csv | ||
@csv ||= CSV.parse(file.read, headers: true, skip_blanks: true) | ||
end | ||
|
||
def records | ||
@records ||= csv.map do |row| | ||
RiskIndicator.find_or_initialize_by(row.to_h) | ||
end.uniq { |record| record.attributes.slice("field", "value") } | ||
end | ||
|
||
def all_records_are_valid | ||
records.select(&:invalid?).each do |record| | ||
errors.add(:base, record.errors.map(&:message).join(", ")) | ||
end | ||
end | ||
|
||
def csv_has_required_headers | ||
unless csv_has_required_headers? | ||
errors.add(:base, "csv is missing required headers `field`, `value`") | ||
end | ||
end | ||
|
||
def csv_has_required_headers? | ||
csv.headers.include?("field") && csv.headers.include?("value") | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
module AutomatedChecks | ||
module ClaimVerifiers | ||
class FraudRisk | ||
TASK_NAME = "fraud_risk".freeze | ||
|
||
def initialize(claim:) | ||
@claim = claim | ||
end | ||
|
||
def perform | ||
return unless claim.attributes_flagged_by_risk_indicator.any? | ||
|
||
flagged_attributes = @claim | ||
.attributes_flagged_by_risk_indicator | ||
.map(&:humanize) | ||
.to_sentence | ||
.downcase | ||
|
||
plural_verbs = claim.attributes_flagged_by_risk_indicator.many? ? "are" : "is" | ||
|
||
body = "This claim has been flagged as the #{flagged_attributes} " \ | ||
"#{plural_verbs} included on the fraud prevention list." | ||
|
||
claim.notes.create!( | ||
body: body, | ||
label: TASK_NAME | ||
) | ||
end | ||
|
||
private | ||
|
||
attr_reader :claim | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
class RiskIndicator < ApplicationRecord | ||
SUPPORTED_FIELDS = %w[ | ||
teacher_reference_number | ||
national_insurance_number | ||
].freeze | ||
|
||
validates :field, presence: { | ||
message: "'field' can't be blank" | ||
} | ||
|
||
validates :value, presence: { | ||
message: "'value' can't be blank" | ||
} | ||
|
||
validates :value, uniqueness: {scope: :field} | ||
|
||
validates :field, | ||
inclusion: { | ||
in: SUPPORTED_FIELDS, | ||
message: "'%{value}' is not a valid attribute - must be one of #{SUPPORTED_FIELDS.join(", ")}" | ||
} | ||
|
||
def self.flagged_attributes(claim) | ||
where( | ||
"field = 'national_insurance_number' AND LOWER(value) = :value", | ||
value: claim.national_insurance_number&.downcase | ||
).or( | ||
where( | ||
field: "teacher_reference_number", | ||
value: claim.eligibility.try(:teacher_reference_number) | ||
) | ||
).pluck(:field).compact | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
<div class="govuk-grid-row"> | ||
<div class="govuk-grid-column-two-thirds"> | ||
<h1 class="govuk-heading-xl"> | ||
Fraud risk CSV upload | ||
</h1> | ||
|
||
<%= form_with( | ||
url: admin_fraud_risk_csv_uploads_path, | ||
model: @form, | ||
builder: GOVUKDesignSystemFormBuilder::FormBuilder | ||
) do |f| %> | ||
<%= f.govuk_error_summary %> | ||
|
||
<%= f.govuk_file_field( | ||
:file, | ||
label: { text: "Upload fraud risk CSV file" }, | ||
hint: { | ||
text: "Currently supported attributes are #{RiskIndicator::SUPPORTED_FIELDS.join(", ")}." | ||
} | ||
) %> | ||
|
||
<%= f.govuk_submit "Upload CSV" %> | ||
<% end %> | ||
|
||
<%= govuk_link_to( | ||
"Download CSV", | ||
admin_fraud_risk_csv_download_path(format: :csv), | ||
class: "govuk-button" | ||
) %> | ||
</div> | ||
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
<div class="govuk-notification-banner" role="region" aria-labelledby="govuk-notification-banner-title" data-module="govuk-notification-banner"> | ||
<div class="govuk-notification-banner__header"> | ||
<h2 class="govuk-notification-banner__title" id="govuk-notification-banner-title"> | ||
Important | ||
</h2> | ||
</div> | ||
<div class="govuk-notification-banner__content"> | ||
<% if messages.many? %> | ||
<h3 class="govuk-notification-banner__heading"> | ||
This claim requires the following to be reviewed: | ||
</h3> | ||
|
||
<ul> | ||
<% messages.each do |message| %> | ||
<li> | ||
<%= message %> | ||
</li> | ||
<% end %> | ||
</ul> | ||
<% else %> | ||
<p class="govuk-notification-banner__heading"> | ||
<%= messages.first %> | ||
</p> | ||
<% end %> | ||
</div> | ||
</div> |
Oops, something went wrong.