-
<%= t(".page_caption", reference: @claim.reference) %>
-
<%= @claim.school.name %> <%= render Claim::StatusTagComponent.new(claim: @claim) %>
+
<%= t(".page_caption", reference: @claim.reference) %>
+
<%= @claim.school_name %> <%= render Claim::StatusTagComponent.new(claim: @claim) %>
+
+ <%= govuk_button_link_to("Request clawback", new_request_clawback_claims_support_claims_clawbacks_path(@claim)) %>
<% if @claim.submitted? %>
<%= t(".submitted_by", name: @claim.submitted_by.full_name, date: l(@claim.submitted_on, format: :long)) %>
diff --git a/app/views/claims/support/claims/request_clawback/edit.html.erb b/app/views/claims/support/claims/request_clawback/edit.html.erb
new file mode 100644
index 000000000..f7167e1da
--- /dev/null
+++ b/app/views/claims/support/claims/request_clawback/edit.html.erb
@@ -0,0 +1,14 @@
+<%= render "claims/support/primary_navigation", current: :claims %>
+<%= content_for(:before_content) do %>
+ <%= govuk_back_link(href: back_link_path) %>
+<% end %>
+
+
+
<%= t(".caption", reference: @claim.reference) %>
+
+ <%= render_wizard(@wizard) %>
+
+
+ <%= govuk_link_to(t(".cancel"), claims_support_claims_clawbacks_path, no_visited_state: true) %>
+
+
diff --git a/app/views/wizards/claims/request_clawback_wizard/_check_your_answers_step.html.erb b/app/views/wizards/claims/request_clawback_wizard/_check_your_answers_step.html.erb
new file mode 100644
index 000000000..05c805229
--- /dev/null
+++ b/app/views/wizards/claims/request_clawback_wizard/_check_your_answers_step.html.erb
@@ -0,0 +1,47 @@
+<% content_for(:page_title) { sanitize t(".page_title", school_name: @claim.school_name, reference: @claim.reference) } %>
+
+
+
+ <%= form_with(model: current_step, url: current_step_path, method: :put) do |f| %>
+ <%= f.govuk_error_summary %>
+
+
<%= t(".title") %>
+
+ <%= govuk_summary_list do |summary_list| %>
+ <% summary_list.with_row do |row| %>
+ <% row.with_key(text: t(".hours")) %>
+ <% row.with_value %>
+ <% row.with_action(text: t(".change"),
+ href: step_path(:clawback),
+ visually_hidden_text: t(".hours"),
+ classes: ["govuk-link--no-visited-state"]) %>
+ <% end %>
+ <% summary_list.with_row do |row| %>
+ <% row.with_key(text: t(".rate")) %>
+ <% row.with_value(text: humanized_money_with_symbol(@claim.school.region.funding_available_per_hour)) %>
+ <% end %>
+ <% summary_list.with_row do |row| %>
+ <% row.with_key(text: t(".amount")) %>
+ <% row.with_value %>
+ <% end %>
+ <% summary_list.with_row do |row| %>
+ <% row.with_key(text: t(".reason")) %>
+ <% row.with_value %>
+ <% row.with_action(text: t(".change"),
+ href: step_path(:clawback),
+ visually_hidden_text: t(".reason"),
+ classes: ["govuk-link--no-visited-state"]) %>
+ <% end %>
+ <% end %>
+
+
+ !
+ <%= t(".warning") %>
+
+
+ <%= f.submit t(".submit"), class: "govuk-button" %>
+
+
+
+
+<% end %>
diff --git a/app/views/wizards/claims/request_clawback_wizard/_clawback_step.html.erb b/app/views/wizards/claims/request_clawback_wizard/_clawback_step.html.erb
new file mode 100644
index 000000000..c4ce4dd56
--- /dev/null
+++ b/app/views/wizards/claims/request_clawback_wizard/_clawback_step.html.erb
@@ -0,0 +1,26 @@
+<% content_for(:page_title) { sanitize t(".page_title", school_name: @claim.school_name, reference: @claim.reference) } %>
+
+ <%= form_with(model: current_step, url: current_step_path, method: :put) do |f| %>
+ <%= f.govuk_error_summary %>
+
+
+
<%= t(".title") %>
+
+
+ <%= f.govuk_text_field :number_of_hours,
+ width: 2,
+ label: { text: t(".hours"), size: "s" },
+ hint: { text: t(".hours_hint") } %>
+
+
+
+ <%= f.govuk_text_area :reason_for_clawback,
+ width: "govuk-text-area",
+ label: { text: t(".reason"), size: "s" },
+ hint: { text: t(".reason_hint") } %>
+
+
+ <%= f.govuk_submit t(".continue") %>
+
+
+ <% end %>
diff --git a/app/wizards/claims/request_clawback_wizard.rb b/app/wizards/claims/request_clawback_wizard.rb
new file mode 100644
index 000000000..cef4433e7
--- /dev/null
+++ b/app/wizards/claims/request_clawback_wizard.rb
@@ -0,0 +1,20 @@
+module Claims
+ class RequestClawbackWizard < BaseWizard
+ attr_reader :claim
+
+ def initialize(claim:, params:, state:, current_step: nil)
+ @claim = claim
+ super(state:, params:, current_step:)
+ end
+
+ def define_steps
+ add_step(ClawbackStep)
+ add_step(CheckYourAnswersStep)
+ end
+
+ def update_status
+ @claim.status = :clawback_requested
+ @claim.save!
+ end
+ end
+end
diff --git a/app/wizards/claims/request_clawback_wizard/check_your_answers_step.rb b/app/wizards/claims/request_clawback_wizard/check_your_answers_step.rb
new file mode 100644
index 000000000..f65686560
--- /dev/null
+++ b/app/wizards/claims/request_clawback_wizard/check_your_answers_step.rb
@@ -0,0 +1,2 @@
+class Claims::RequestClawbackWizard::CheckYourAnswersStep < BaseStep
+end
diff --git a/app/wizards/claims/request_clawback_wizard/clawback_step.rb b/app/wizards/claims/request_clawback_wizard/clawback_step.rb
new file mode 100644
index 000000000..7fd222b83
--- /dev/null
+++ b/app/wizards/claims/request_clawback_wizard/clawback_step.rb
@@ -0,0 +1,10 @@
+class Claims::RequestClawbackWizard::ClawbackStep < BaseStep
+ attribute :number_of_hours, :integer
+ attribute :reason_for_clawback
+
+ validates :number_of_hours, presence: true, numericality: { only_integer: true, less_than_or_equal_to: 40 }
+ validates :reason_for_clawback, presence: true
+
+ # TODO: Add methods for assigning attributes to relevant clawback fields on the claim model instance
+ # TODO: Add tailored error messages to activerecord yml file when attributes are in use
+end
diff --git a/config/locales/en/claims/support/claims.yml b/config/locales/en/claims/support/claims.yml
index 80329df9d..dc766f325 100644
--- a/config/locales/en/claims/support/claims.yml
+++ b/config/locales/en/claims/support/claims.yml
@@ -2,6 +2,10 @@ en:
claims:
support:
claims:
+ request_clawback:
+ edit:
+ caption: Clawbacks - Claim %{reference}
+ cancel: Cancel
index:
heading: Claims
sub_heading: Claims (%{count})
diff --git a/config/locales/en/claims/support/claims/request_clawback.yml b/config/locales/en/claims/support/claims/request_clawback.yml
new file mode 100644
index 000000000..4df108e7e
--- /dev/null
+++ b/config/locales/en/claims/support/claims/request_clawback.yml
@@ -0,0 +1,7 @@
+en:
+ claims:
+ support:
+ claims:
+ request_clawback:
+ update:
+ success_heading: Clawback requested
diff --git a/config/locales/en/wizards/claims/request_clawback_wizard.yml b/config/locales/en/wizards/claims/request_clawback_wizard.yml
new file mode 100644
index 000000000..c0f8ce773
--- /dev/null
+++ b/config/locales/en/wizards/claims/request_clawback_wizard.yml
@@ -0,0 +1,23 @@
+en:
+ wizards:
+ claims:
+ request_clawback_wizard:
+ clawback_step:
+ page_title: Clawback details - %{school_name} - Claim %{reference}
+ title: Clawback details
+ hours: Number of hours to clawback
+ hours_hint: Enter whole numbers up to a maximum of 40 hours
+ reason: Reason for clawback
+ reason_hint: Explain why the clawback is being requested. For example, include details of which mentor has received a deduction.
+ continue: Continue
+ description: Personal details
+ check_your_answers_step:
+ page_title: Check your answers - %{school_name} - Claim %{reference}
+ title: Check your answers
+ hours: Number of hours
+ rate: Hourly rate
+ amount: Clawback amount
+ reason: Reason for clawback
+ submit: Request clawback
+ warning: We will show clawback details to the school.
+ change: Change
diff --git a/config/routes/claims.rb b/config/routes/claims.rb
index 7819af893..ba202a454 100644
--- a/config/routes/claims.rb
+++ b/config/routes/claims.rb
@@ -93,7 +93,16 @@
end
end
- resources :clawbacks, path: "clawbacks/claims", only: %i[index show]
+ resources :clawbacks, path: "clawbacks/claims", only: %i[index show] do
+ get :remove, on: :member
+
+ collection do
+ get "new/:claim_id", to: "request_clawback#new", as: :new_request_clawback
+ get "new/:claim_id/:step", to: "request_clawback#edit", as: :request_clawback
+ put "new/:claim_id/:step", to: "request_clawback#update"
+ end
+ end
+
resources :activity_logs, path: "activity", only: %i[index]
end
diff --git a/spec/support/govuk_component_matchers.rb b/spec/support/govuk_component_matchers.rb
index 0d8bef3be..dcb6fc6a7 100644
--- a/spec/support/govuk_component_matchers.rb
+++ b/spec/support/govuk_component_matchers.rb
@@ -200,10 +200,6 @@ def secondary_navigation
right.find("div.govuk-body-s:nth-of-type(1)", text: expected_claim_details["submitted_date"])
right.find("div.govuk-body-s:nth-of-type(2)", text: expected_claim_details["amount"])
- if expected_claim_details["status"] == "Clawback requested"
- body.find("div.claim-card__body__right").find("div.govuk-body-s govuk-!-font-weight-bold", text: "Clawback requested")
- # TODO: Correct clawback amount to be tested when implemented
- end
true
rescue Capybara::ElementNotFound
false
diff --git a/spec/system/claims/support/claims/clawbacks/support_user_requests_a_clawback_spec.rb b/spec/system/claims/support/claims/clawbacks/support_user_requests_a_clawback_spec.rb
new file mode 100644
index 000000000..e228e056e
--- /dev/null
+++ b/spec/system/claims/support/claims/clawbacks/support_user_requests_a_clawback_spec.rb
@@ -0,0 +1,174 @@
+require "rails_helper"
+
+RSpec.describe "Support user requests a clawback on a claim", service: :claims, type: :system do
+ scenario do
+ given_claims_exist
+ and_i_am_signed_in
+
+ when_i_navigate_to_the_clawbacks_index_page
+ and_i_click_on_claim_one
+ then_i_see_the_show_page_for_claim_one
+
+ when_i_click_on_request_clawback
+ then_i_see_the_clawback_details_page
+
+ when_i_enter_fifty_hours
+ and_i_click_on_continue
+ # then_i_see_a_validation_error_for_entering_too_many_hours
+
+ when_i_leave_all_fields_blank
+ and_i_click_on_continue
+ # then_i_see_validation_errors_for_not_providing_required_data
+
+ when_i_enter_valid_data
+ and_i_click_on_continue
+ then_i_see_the_check_your_answers_page
+
+ when_i_click_on_change
+ then_i_see_the_clawback_details_page
+
+ when_i_click_on_continue
+ then_i_see_the_check_your_answers_page
+
+ when_i_click_on_request_clawback
+ then_i_see_a_success_message
+ and_i_see_the_clawbacks_index_page
+ and_i_see_the_claim_status_is_clawback_requested
+ end
+
+ private
+
+ def given_claims_exist
+ @claim_one = create(:claim,
+ :submitted,
+ status: :sampling_not_approved,
+ reference: 11_111_111)
+ @claim_two = create(:claim,
+ :submitted,
+ status: :sampling_not_approved,
+ reference: 22_222_222)
+ end
+
+ def and_i_am_signed_in
+ sign_in_claims_support_user
+ end
+
+ def when_i_navigate_to_the_clawbacks_index_page
+ within primary_navigation do
+ click_on "Claims"
+ end
+
+ within secondary_navigation do
+ click_on "Clawbacks"
+ end
+ end
+
+ def and_i_click_on_claim_one
+ click_on "11111111 - #{@claim_one.school_name}"
+ end
+
+ def then_i_see_the_show_page_for_claim_one
+ expect(page).to have_title("Clawbacks - #{@claim_one.school_name} - Claim 11111111 - Claim funding for mentor training - GOV.UK")
+ expect(primary_navigation).to have_current_item("Claims")
+ expect(page).to have_element(:span, text: "Clawbacks - Claim 11111111", class: "govuk-caption-l")
+ expect(page).to have_h1(@claim_one.school_name)
+ expect(page).to have_element(:strong, text: "Claim not approved", class: "govuk-tag govuk-tag--pink")
+ expect(page).to have_link("Request clawback", href: "/support/claims/clawbacks/claims/new/#{@claim_one.id}")
+ expect(page).to have_summary_list_row("School", @claim_one.school_name)
+ expect(page).to have_summary_list_row("Academic year", @claim_one.academic_year_name)
+ expect(page).to have_summary_list_row("Accredited provider", @claim_one.provider.name)
+ expect(page).to have_summary_list_row("Mentors") do |row|
+ @claim_one.mentors.each do |mentor|
+ expect(row).to have_css("ul.govuk-list li", text: mentor.full_name)
+ end
+ end
+ expect(page).to have_h2("Hours of training")
+ @claim_one.mentor_trainings.order_by_mentor_full_name.each do |mentor_training|
+ expect(page).to have_summary_list_row(mentor_training.mentor.full_name, "#{mentor_training.hours_completed} hours")
+ end
+ expect(page).to have_h2("Grant funding")
+ expect(page).to have_summary_list_row("Total hours", "#{@claim_one.mentor_trainings.sum(:hours_completed)} hours")
+ expect(page).to have_summary_list_row("Hourly rate", @claim_one.school.region.funding_available_per_hour)
+ expect(page).to have_summary_list_row("Claim amount", @claim_one.amount)
+ end
+
+ def when_i_click_on_request_clawback
+ click_on "Request clawback"
+ end
+
+ def then_i_see_the_clawback_details_page
+ expect(page).to have_title("Clawback details - #{@claim_one.school_name} - Claim 11111111 - Claim funding for mentor training - GOV.UK")
+ expect(primary_navigation).to have_current_item("Claims")
+
+ expect(page).to have_element(:span, text: "Clawbacks - Claim 11111111", class: "govuk-caption-l")
+ expect(page).to have_h1("Clawback details")
+ expect(page).to have_element(:label, text: "Number of hours to clawback", class: "govuk-label")
+ expect(page).to have_element(:div, text: "Enter whole numbers up to a maximum of 40 hours", class: "govuk-hint")
+ expect(page).to have_element(:label, text: "Reason for clawback", class: "govuk-label")
+ expect(page).to have_element(:div, text: "Explain why the clawback is being requested. For example, include details of which mentor has received a deduction.", class: "govuk-hint")
+ expect(page).to have_button("Continue")
+ expect(page).to have_link("Cancel", href: "/support/claims/clawbacks/claims")
+ end
+
+ def when_i_enter_fifty_hours
+ fill_in "claims_request_clawback_wizard_clawback_step[number_of_hours]", with: 50
+ end
+
+ def and_i_click_on_continue
+ click_on "Continue"
+ end
+ alias_method :when_i_click_on_continue, :and_i_click_on_continue
+
+ # def then_i_see_a_validation_error_for_entering_too_many_hours; end
+
+ def when_i_leave_all_fields_blank
+ fill_in "claims_request_clawback_wizard_clawback_step[number_of_hours]", with: ""
+ end
+
+ # def then_i_see_validation_errors_for_not_providing_required_data; end
+
+ def when_i_enter_valid_data
+ fill_in "claims_request_clawback_wizard_clawback_step[number_of_hours]", with: "8"
+ fill_in "claims_request_clawback_wizard_clawback_step[reason_for_clawback]", with: "Mismatch in hours recorded compared with hours claimed."
+ end
+
+ def then_i_see_the_check_your_answers_page
+ expect(page).to have_title("Check your answers - #{@claim_one.school_name} - Claim 11111111 - Claim funding for mentor training - GOV.UK")
+ expect(primary_navigation).to have_current_item("Claims")
+ expect(page).to have_element(:span, text: "Clawbacks - Claim 11111111", class: "govuk-caption-l")
+ expect(page).to have_h1("Check your answers")
+ expect(page).to have_summary_list_row("Number of hours", "")
+ expect(page).to have_summary_list_row("Hourly rate", @claim_one.school.region.funding_available_per_hour)
+ expect(page).to have_summary_list_row("Clawback amount", "")
+ expect(page).to have_summary_list_row("Reason for clawback", "")
+ expect(page).to have_element(:strong, text: "We will show clawback details to the school.", class: "govuk-warning-text__text")
+ expect(page).to have_button("Request clawback")
+ expect(page).to have_link("Cancel", href: "/support/claims/clawbacks/claims")
+ end
+
+ def when_i_click_on_change
+ first("a", text: "Change").click
+ end
+
+ def then_i_see_a_success_message
+ expect(page).to have_success_banner("Clawback requested")
+ end
+
+ def and_i_see_the_clawbacks_index_page
+ expect(page).to have_title("Claims - Claim funding for mentor training - GOV.UK")
+ expect(primary_navigation).to have_current_item("Claims")
+ expect(secondary_navigation).to have_current_item("Clawbacks")
+ end
+
+ def and_i_see_the_claim_status_is_clawback_requested
+ expect(page).to have_claim_card({
+ "title" => "#{@claim_one.reference} - #{@claim_one.school_name}",
+ "url" => "/support/claims/clawbacks/claims/#{@claim_one.id}",
+ "status" => "Clawback requested",
+ "academic_year" => @claim_one.academic_year.name,
+ "provider_name" => @claim_one.provider.name,
+ "submitted_at" => I18n.l(@claim_one.submitted_at.to_date, format: :long),
+ "amount" => @claim_one.amount,
+ })
+ end
+end
diff --git a/spec/system/claims/support/claims/clawbacks/support_user_views_clawbacks_index_spec.rb b/spec/system/claims/support/claims/clawbacks/support_user_views_clawbacks_index_spec.rb
index 68863d017..92b7672b2 100644
--- a/spec/system/claims/support/claims/clawbacks/support_user_views_clawbacks_index_spec.rb
+++ b/spec/system/claims/support/claims/clawbacks/support_user_views_clawbacks_index_spec.rb
@@ -178,7 +178,7 @@ def then_i_see_the_details_of_the_clawback_requested_claim
expect(page).to have_title(
"Clawbacks - #{@clawback_requested_claim.school.name} - Claim #{@clawback_requested_claim.reference} - Claim funding for mentor training - GOV.UK",
)
- expect(page).to have_element(:p, text: "Clawbacks - Claim #{@clawback_requested_claim.reference}", class: "govuk-caption-l")
+ expect(page).to have_element(:span, text: "Clawbacks - Claim #{@clawback_requested_claim.reference}", class: "govuk-caption-l")
expect(page).to have_h1(@clawback_requested_claim.school.name)
expect(page).to have_element(:strong, text: "Clawback requested", class: "govuk-tag govuk-tag--orange")
end
diff --git a/spec/wizards/claims/request_clawback_wizard_spec.rb b/spec/wizards/claims/request_clawback_wizard_spec.rb
new file mode 100644
index 000000000..cd86b1848
--- /dev/null
+++ b/spec/wizards/claims/request_clawback_wizard_spec.rb
@@ -0,0 +1,31 @@
+require "rails_helper"
+
+# TODO: Support user tries to request a clawback of more hours than were claimed
+# TODO: Support user tries to request a clawback of more hours than are available to clawback
+
+RSpec.describe Claims::RequestClawbackWizard do
+ subject(:wizard) { described_class.new(claim:, state:, params:, current_step: nil) }
+
+ let(:state) { {} }
+ let(:params_data) { {} }
+ let(:params) { ActionController::Parameters.new(params_data) }
+ let(:claim) { create(:claim, status: "sampling_in_progress") }
+
+ before do
+ allow(claim).to receive(:save!).and_return(true)
+ end
+
+ describe "#steps" do
+ subject { wizard.steps.keys }
+
+ it { is_expected.to eq %i[clawback check_your_answers] }
+ end
+
+ describe "#update_status" do
+ it "updates the claim status to 'clawback_requested' and saves the claim" do
+ wizard.update_status
+ expect(claim.status).to eq("clawback_requested")
+ expect(claim).to have_received(:save!)
+ end
+ end
+end