Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create sampling send and deliver #1269

Merged
merged 10 commits into from
Dec 24, 2024
30 changes: 30 additions & 0 deletions app/controllers/claims/sampling/claims_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
class Claims::Sampling::ClaimsController < Claims::ApplicationController
skip_before_action :authenticate_user!

before_action :skip_authorization
before_action :validate_token
before_action :set_provider_sampling

def download
provider_name = @provider_sampling.provider_name.parameterize
send_data @provider_sampling.csv_file.download, filename: "sampling-claims-#{provider_name}-#{Time.current.iso8601}.csv"
end

private

def validate_token
@provider_sampling_id = Rails.application.message_verifier(:sampling).verify(token_param)
rescue ActiveSupport::MessageVerifier::InvalidSignature
render "error"
end

def set_provider_sampling
@provider_sampling = Claims::ProviderSampling.find(@provider_sampling_id)
rescue ActiveRecord::RecordNotFound
render "error"
end

def token_param
params.fetch(:token, nil)
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ def update
def set_wizard
state = session[state_key] ||= {}
current_step = params[:step]&.to_sym
@wizard = Claims::UploadSamplingDataWizard.new(params:, state:, current_step:)
@wizard = Claims::UploadSamplingDataWizard.new(params:, state:, current_step:, current_user:)
end

def step_path(step)
Expand Down
22 changes: 22 additions & 0 deletions app/jobs/claims/sampling/create_and_deliver_job.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
class Claims::Sampling::CreateAndDeliverJob < ApplicationJob
queue_as :default

def perform(current_user_id:, claim_ids:)
@current_user_id = current_user_id
@claim_ids = claim_ids

Claims::Sampling::CreateAndDeliver.call(current_user:, claims:)
end

private

attr_reader :current_user_id, :claim_ids

def claims
@claims ||= Claims::Claim.find(claim_ids)
end

def current_user
@current_user ||= User.find(current_user_id)
end
end
21 changes: 18 additions & 3 deletions app/mailers/claims/provider_mailer.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,22 @@
class Claims::ProviderMailer < Claims::ApplicationMailer
def sampling_checks_required(provider, url_for_csv)
notify_email to: provider.email_address,
def sampling_checks_required(provider_sampling)
@provider_sampling = provider_sampling

notify_email to: @provider_sampling.provider_email_address,
subject: t(".subject"),
body: t(".body", provider_name: provider.name, url_for_csv:, support_email:, service_name:)
body: t(
".body",
provider_name: @provider_sampling.provider_name,
download_csv_url: claims_sampling_claims_url(token:),
support_email:, service_name:
)
end

private

attr_reader :provider_sampling

def token
Rails.application.message_verifier(:sampling).generate(provider_sampling.id, expires_in: 7.days)
end
end
5 changes: 4 additions & 1 deletion app/models/claims/claim_activity.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,8 @@ class Claims::ClaimActivity < ApplicationRecord
belongs_to :user
belongs_to :record, polymorphic: true

enum :action, { payment_delivered: "payment_delivered" }
enum :action, {
payment_delivered: "payment_delivered",
sampling_in_progress: "sampling_in_progress",
}
end
2 changes: 2 additions & 0 deletions app/models/claims/provider_sampling.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,6 @@ class Claims::ProviderSampling < ApplicationRecord
has_many :claims, through: :provider_sampling_claims

has_one_attached :csv_file

delegate :email_address, :name, to: :provider, prefix: true
end
36 changes: 36 additions & 0 deletions app/services/claims/sampling/create_and_deliver.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
class Claims::Sampling::CreateAndDeliver < ApplicationService
def initialize(current_user:, claims:)
@current_user = current_user
@claims = claims
end

attr_reader :current_user, :claims

def call
claims.group_by(&:provider).each do |provider, provider_claims|
ActiveRecord::Base.transaction do |transaction|
provider_claims.each do |claim|
Claims::Sampling::FlagForSamplingJob.perform_now(claim)
end

provider_sampling = Claims::ProviderSampling.create!(provider:, claims: provider_claims, sampling:, csv_file: File.open(csv_for_provider.to_io))

transaction.after_commit do
Claims::ProviderMailer.sampling_checks_required(provider_sampling).deliver_later
end
end
end

Claims::ClaimActivity.create!(action: :sampling_in_progress, user: current_user, record: sampling)
end

private

def csv_for_provider
Claims::Sampling::GenerateCSVFile.call(claims:)
end

def sampling
@sampling ||= Claims::Sampling.new
end
end
35 changes: 35 additions & 0 deletions app/services/claims/sampling/generate_csv_file.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
require "csv"

class Claims::Sampling::GenerateCSVFile < ApplicationService
HEADERS = %w[
claim_reference
sampling_reason
].freeze

def initialize(claims:)
@claims = claims
end

def call
CSV.open(file_name, "w", headers: true) do |csv|
csv << HEADERS

claims.each do |claim|
csv << [
claim.reference,
claim.sampling_reason,
]
end

csv
end
end

private

attr_reader :claims

def file_name
Rails.root.join("tmp/sampling-claims-#{Time.current}.csv")
end
end
13 changes: 13 additions & 0 deletions app/views/claims/sampling/claims/error.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<% content_for :page_title, t(".page_title") %>

<div class="govuk-width-container">
Kizr marked this conversation as resolved.
Show resolved Hide resolved
<div class="govuk-grid-row">
<div class="govuk-grid-column-two-thirds">
<h1 class="govuk-heading-l"><%= t(".page_title") %></h1>

<p class="govuk-body"><%= t(".description") %></p>

<p class="govuk-body"><%= t(".support_html", mail_to: govuk_mail_to(t("claims.support_email"), t("claims.support_email_html"))) %></p>
</div>
</div>
</div>
15 changes: 15 additions & 0 deletions app/views/claims/sampling/claims/index.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<% content_for :page_title, t(".page_title") %>

<div class="govuk-width-container">
Kizr marked this conversation as resolved.
Show resolved Hide resolved
<div class="govuk-grid-row">
<div class="govuk-grid-column-two-thirds">
<h1 class="govuk-heading-l"><%= t(".page_title") %></h1>

<p class="govuk-body"><%= t(".description_html") %></p>

<p class="govuk-body"><%= t(".support_html", mail_to: govuk_mail_to(t("claims.support_email"), t("claims.support_email_html"))) %></p>

<%= govuk_button_link_to t(".submit"), download_claims_sampling_claims_path(token: params[:token]) %>
</div>
</div>
</div>
10 changes: 9 additions & 1 deletion app/wizards/claims/upload_sampling_data_wizard.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
module Claims
class UploadSamplingDataWizard < BaseWizard
def initialize(current_user:, params:, state:, current_step: nil)
@current_user = current_user

super(state:, params:, current_step:)
end

attr_reader :current_user

def define_steps
if paid_claims.present?
add_step(UploadStep)
Expand All @@ -12,7 +20,7 @@ def define_steps
def upload_data
raise "Invalid wizard state" unless valid?

Claims::Sampling::FlagCollectionForSamplingJob.perform_later(uploaded_claim_ids)
Claims::Sampling::CreateAndDeliverJob.perform_later(current_user_id: current_user.id, claim_ids: uploaded_claim_ids)
end

def paid_claims
Expand Down
2 changes: 1 addition & 1 deletion config/locales/en/claims/provider_mailer.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ en:

These claims from the Claim funding for mentor training service (Claim) are ready for post-payment assurance. The link to the latest CSV file is valid for 7 days.

%{url_for_csv}
%{download_csv_url}

What you need to do:

Expand Down
13 changes: 13 additions & 0 deletions config/locales/en/claims/sampling/claims.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
en:
claims:
sampling:
claims:
index:
page_title: Download the sampling CSV
description_html: Download the Claim funding for mentor training sampling <span title="Comma separated values">CSV</span> file.
support_html: If you have any questions, email %{mail_to}.
submit: Download CSV file
error:
page_title: Sorry, there is a problem with the download link
description: You are seeing this page because the download link is not working. It may have timed out or contained an invalid security token.
support_html: Email %{mail_to} to request a new download link.
6 changes: 6 additions & 0 deletions config/routes/claims.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@
end
end

namespace :sampling do
resources :claims, only: %i[index] do
get :download, on: :collection
end
end

resources :schools, only: %i[index show] do
scope module: :schools do
resources :claims do
Expand Down
23 changes: 23 additions & 0 deletions spec/jobs/claims/sampling/create_and_deliver_job_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
require "rails_helper"

RSpec.describe Claims::Sampling::CreateAndDeliverJob, type: :job do
let(:current_user) { create(:claims_user) }
let(:claims) { create_list(:claim, 3) }

describe "#perform" do
before do
allow(Claims::Sampling::CreateAndDeliver).to receive(:call).and_return(true)
end

it "calls the Claims::Sampling::CreateAndDeliver service" do
described_class.perform_now(current_user_id: current_user.id, claim_ids: claims.map(&:id))
expect(Claims::Sampling::CreateAndDeliver).to have_received(:call).with(current_user:, claims:).once
end

it "enqueues the job in the default queue" do
expect {
described_class.perform_later(current_user_id: current_user.id, claim_ids: claims.map(&:id))
}.to have_enqueued_job(described_class).on_queue("default")
end
end
end
11 changes: 8 additions & 3 deletions spec/mailers/claims/provider_mailer_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,18 @@

RSpec.describe Claims::ProviderMailer, type: :mailer do
describe "#sampling_checks_required" do
subject(:sampling_checks_required_email) { described_class.sampling_checks_required(provider, url_for_csv) }
subject(:sampling_checks_required_email) { described_class.sampling_checks_required(provider_sampling) }

let(:provider) { create(:claims_provider, email_address: "aes_sedai_trust@example.com") }
let(:provider) { build(:claims_provider, email_address: "aes_sedai_trust@example.com") }
let(:provider_sampling) { create(:provider_sampling, provider:) }
let(:url_for_csv) { "https://example.com" }
let(:service_name) { "Claim funding for mentor training" }
let(:support_email) { "ittmentor.funding@education.gov.uk" }

before do
allow(Rails.application.message_verifier(:sampling)).to receive(:generate).and_return("token")
end

it "sends the sampling checks required email" do
expect(sampling_checks_required_email.to).to contain_exactly(provider.email_address)
expect(sampling_checks_required_email.subject).to eq("ITT mentor claims need to be assured")
Expand All @@ -17,7 +22,7 @@

These claims from the Claim funding for mentor training service (Claim) are ready for post-payment assurance. The link to the latest CSV file is valid for 7 days.

#{url_for_csv}
http://claims.localhost/sampling/claims?token=token

What you need to do:

Expand Down
5 changes: 5 additions & 0 deletions spec/models/claims/provider_sampling_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,9 @@
describe "attachments" do
it { is_expected.to have_one_attached(:csv_file) }
end

describe "delegations" do
it { is_expected.to delegate_method(:email_address).to(:provider).with_prefix }
it { is_expected.to delegate_method(:name).to(:provider).with_prefix }
end
end
19 changes: 19 additions & 0 deletions spec/services/claims/sampling/create_and_deliver_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
require "rails_helper"

describe Claims::Sampling::CreateAndDeliver do
subject(:create_and_deliver) { described_class.call(current_user:, claims:) }

let(:current_user) { create(:claims_support_user) }
let!(:claims) { [create(:claim, :paid)] }

describe "#call" do
context "when there are submitted claims" do
it "does a thing" do
expect { create_and_deliver }.to change(Claims::Sampling, :count).by(1)
.and change(Claims::ClaimActivity, :count).by(1)
.and change { Claims::Claim.pluck(:status).uniq }.from(%w[paid]).to(%w[sampling_in_progress])
.and enqueue_mail(Claims::ProviderMailer, :sampling_checks_required)
end
end
end
end
25 changes: 25 additions & 0 deletions spec/services/claims/sampling/generate_csv_file_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
require "rails_helper"

describe Claims::Sampling::GenerateCSVFile do
subject(:generate_csv_file) { described_class.call(claims:) }

let(:claims) { create_list(:claim, 3) }

describe "#call" do
it "generates a CSV file of claims" do
expect(generate_csv_file).to be_a(CSV)
expect(generate_csv_file).to be_closed

csv = CSV.read(generate_csv_file.path)

expect(csv.first).to eq(%w[claim_reference sampling_reason])

claims.each_with_index do |claim, index|
expect(csv[index + 1]).to eq([
claim.reference,
claim.sampling_reason,
])
end
end
end
end
Loading
Loading