From f3301bd70bb2996e6d41c06a322caf9887adcf68 Mon Sep 17 00:00:00 2001
From: timpeat
Date: Fri, 6 Sep 2024 14:44:10 +0100
Subject: [PATCH 1/3] Spike means testesd decision
---
app/aggregates/deciding.rb | 22 +++++++
app/aggregates/deciding/command.rb | 31 ++++++++++
.../deciding/commands/create_draft.rb | 12 ++++
.../deciding/commands/load_decision.rb | 7 +++
.../commands/set_interests_of_justice.rb | 12 ++++
app/aggregates/deciding/decision.rb | 46 +++++++++++++++
app/aggregates/reviewing.rb | 2 +
.../reviewing/available_reviewer_actions.rb | 3 +-
app/aggregates/reviewing/command.rb | 2 +-
.../reviewing/commands/add_decision.rb | 13 +++++
app/aggregates/reviewing/review.rb | 17 +++++-
app/components/review_action_component.rb | 5 +-
.../interests_of_justices_controller.rb | 50 ++++++++++++++++
.../casework/decisions/means_controller.rb | 57 +++++++++++++++++++
.../casework/decisions_controller.rb | 51 +++++++++++++++++
.../casework/funding_decisions_controller.rb | 51 +++++++++++++++++
app/lib/types.rb | 13 +++++
app/models/crime_application.rb | 4 ++
app/models/decision.rb | 3 +
app/models/decisions/interests_of_justice.rb | 33 +++++++++++
app/models/decisions/outcome.rb | 10 ++++
app/models/interests_of_justice_decision.rb | 18 ++++++
app/views/casework/decisions/index.html.erb | 31 ++++++++++
.../interests_of_justices/edit.html.erb | 24 ++++++++
.../interests_of_justices/new.html.erb | 23 ++++++++
app/views/casework/decisions/show.html.erb | 25 ++++++++
.../casework/funding_decisions/new.html.erb | 18 ++++++
config/initializers/event_store.rb | 3 +
config/locales/en/casework.yml | 8 +++
config/locales/en/helpers.yml | 16 +++++-
config/routes.rb | 7 +++
config/settings.yml | 5 ++
spec/support/capybara_helpers.rb | 39 +++++++++++++
.../reviewing/a_non_means_application_spec.rb | 24 +++++++-
...wing_a_draft_maat_funding_decision_spec.rb | 0
35 files changed, 677 insertions(+), 8 deletions(-)
create mode 100644 app/aggregates/deciding.rb
create mode 100644 app/aggregates/deciding/command.rb
create mode 100644 app/aggregates/deciding/commands/create_draft.rb
create mode 100644 app/aggregates/deciding/commands/load_decision.rb
create mode 100644 app/aggregates/deciding/commands/set_interests_of_justice.rb
create mode 100644 app/aggregates/deciding/decision.rb
create mode 100644 app/aggregates/reviewing/commands/add_decision.rb
create mode 100644 app/controllers/casework/decisions/interests_of_justices_controller.rb
create mode 100644 app/controllers/casework/decisions/means_controller.rb
create mode 100644 app/controllers/casework/decisions_controller.rb
create mode 100644 app/controllers/casework/funding_decisions_controller.rb
create mode 100644 app/models/decision.rb
create mode 100644 app/models/decisions/interests_of_justice.rb
create mode 100644 app/models/decisions/outcome.rb
create mode 100644 app/models/interests_of_justice_decision.rb
create mode 100644 app/views/casework/decisions/index.html.erb
create mode 100644 app/views/casework/decisions/interests_of_justices/edit.html.erb
create mode 100644 app/views/casework/decisions/interests_of_justices/new.html.erb
create mode 100644 app/views/casework/decisions/show.html.erb
create mode 100644 app/views/casework/funding_decisions/new.html.erb
create mode 100644 spec/support/capybara_helpers.rb
create mode 100644 spec/system/casework/reviewing/viewing_a_draft_maat_funding_decision_spec.rb
diff --git a/app/aggregates/deciding.rb b/app/aggregates/deciding.rb
new file mode 100644
index 000000000..ae3916d8f
--- /dev/null
+++ b/app/aggregates/deciding.rb
@@ -0,0 +1,22 @@
+module Deciding
+ class DraftCreated < RailsEventStore::Event; end
+ class InterestsOfJusticeSet < RailsEventStore::Event; end
+
+ class << self
+ def stream_name(decision_id)
+ "Deciding$#{decision_id}"
+ end
+ end
+
+ class Configuration
+ def call(event_store)
+ event_store.subscribe(
+ DecisionHandler, to: [Reviewing::AddDecision]
+ )
+ end
+ end
+
+ class DecisionHandler
+ def call(event); end
+ end
+end
diff --git a/app/aggregates/deciding/command.rb b/app/aggregates/deciding/command.rb
new file mode 100644
index 000000000..198bfd8ce
--- /dev/null
+++ b/app/aggregates/deciding/command.rb
@@ -0,0 +1,31 @@
+module Deciding
+ class Command < Dry::Struct
+ attribute :decision_id, Types::Uuid
+
+ def with_decision(&block)
+ repository.with_aggregate(
+ Decision.new(decision_id),
+ stream_name,
+ &block
+ )
+ end
+
+ private
+
+ def repository
+ @repository ||= AggregateRoot::Repository.new(
+ Rails.configuration.event_store
+ )
+ end
+
+ def stream_name
+ Deciding.stream_name(decision_id)
+ end
+
+ class << self
+ def call(args)
+ new(args).call
+ end
+ end
+ end
+end
diff --git a/app/aggregates/deciding/commands/create_draft.rb b/app/aggregates/deciding/commands/create_draft.rb
new file mode 100644
index 000000000..133400247
--- /dev/null
+++ b/app/aggregates/deciding/commands/create_draft.rb
@@ -0,0 +1,12 @@
+module Deciding
+ class CreateDraft < Command
+ attribute :application_id, Types::Uuid
+ attribute :user_id, Types::Uuid
+
+ def call
+ with_decision do |decision|
+ decision.create_draft(user_id:)
+ end
+ end
+ end
+end
diff --git a/app/aggregates/deciding/commands/load_decision.rb b/app/aggregates/deciding/commands/load_decision.rb
new file mode 100644
index 000000000..df336909e
--- /dev/null
+++ b/app/aggregates/deciding/commands/load_decision.rb
@@ -0,0 +1,7 @@
+module Deciding
+ class LoadDecision < Command
+ def call
+ repository.load(Decision.new(decision_id), stream_name)
+ end
+ end
+end
diff --git a/app/aggregates/deciding/commands/set_interests_of_justice.rb b/app/aggregates/deciding/commands/set_interests_of_justice.rb
new file mode 100644
index 000000000..4ed89b088
--- /dev/null
+++ b/app/aggregates/deciding/commands/set_interests_of_justice.rb
@@ -0,0 +1,12 @@
+module Deciding
+ class SetInterestsOfJustice < Command
+ attribute :user_id, Types::Uuid
+ attribute :details, Types::InterestsOfJusticeDecision
+
+ def call
+ with_decision do |decision|
+ decision.set_interests_of_justice(user_id:, details:)
+ end
+ end
+ end
+end
diff --git a/app/aggregates/deciding/decision.rb b/app/aggregates/deciding/decision.rb
new file mode 100644
index 000000000..071a98465
--- /dev/null
+++ b/app/aggregates/deciding/decision.rb
@@ -0,0 +1,46 @@
+module Deciding
+ class Decision
+ include AggregateRoot
+
+ def initialize(decision_id)
+ @decision_id = decision_id
+ @application_id = nil
+ @case_id = nil
+ @maat_id = nil
+ @interests_of_justice = nil
+ @means = nil
+ @state = nil
+ end
+
+ attr_reader :interests_of_justice, :decision_id
+
+ def create_draft(user_id:, application_id:)
+ apply DraftCreated.new(
+ data: { decision_id:, application_id:, user_id: }
+ )
+ end
+
+ def set_interests_of_justice(user_id:, details:)
+ # TODO: ignore if not changed
+ apply InterestsOfJusticeSet.new(
+ data: { user_id:, details: }
+ )
+ end
+
+ on DraftCreated do |event|
+ @interests_of_justice = event.data.fetch(:details)
+ @application_id = event.data.fetch(:application_id)
+ @state = Types::DecisionState[:draft]
+ end
+
+ on InterestsOfJusticeSet do |event|
+ @interests_of_justice = event.data.fetch(:details)
+ end
+
+ def interests_of_justice
+ return if @interests_of_justice.nil?
+
+ Types::InterestsOfJusticeDecision[@interests_of_justice]
+ end
+ end
+end
diff --git a/app/aggregates/reviewing.rb b/app/aggregates/reviewing.rb
index e75eb17a4..a647a0ada 100644
--- a/app/aggregates/reviewing.rb
+++ b/app/aggregates/reviewing.rb
@@ -15,6 +15,8 @@ class CannotMarkAsReadyWhenSentBack < Error; end
class CannotSendBackWhenCompleted < Error; end
class NotReceived < Error; end
+ class DecisionAdded < Event; end
+
class << self
def stream_name(application_id)
"Reviewing$#{application_id}"
diff --git a/app/aggregates/reviewing/available_reviewer_actions.rb b/app/aggregates/reviewing/available_reviewer_actions.rb
index c08ca749b..e4cbd48e1 100644
--- a/app/aggregates/reviewing/available_reviewer_actions.rb
+++ b/app/aggregates/reviewing/available_reviewer_actions.rb
@@ -6,8 +6,7 @@ class AvailableReviewerActions
marked_as_ready: [:complete, :send_back],
},
non_means: {
- open: [:complete, :send_back],
- marked_as_ready: [:complete, :send_back] # TODO: remove once all non-means in this state processed
+ open: FeatureFlags.adding_decisions.enabled? ? [:add_funding_decision, :send_back] : [:complete, :send_back],
},
pse: {
open: [:complete]
diff --git a/app/aggregates/reviewing/command.rb b/app/aggregates/reviewing/command.rb
index 829e1583f..c00e6bbe4 100644
--- a/app/aggregates/reviewing/command.rb
+++ b/app/aggregates/reviewing/command.rb
@@ -17,7 +17,7 @@ def repository
end
def stream_name
- Reviewing.stream_name(application_id)
+ "Reviewing$#{application_id}"
end
class << self
diff --git a/app/aggregates/reviewing/commands/add_decision.rb b/app/aggregates/reviewing/commands/add_decision.rb
new file mode 100644
index 000000000..83cb234dd
--- /dev/null
+++ b/app/aggregates/reviewing/commands/add_decision.rb
@@ -0,0 +1,13 @@
+module Reviewing
+ class AddDecision < Command
+ attribute :application_id, Types::Uuid
+ attribute :user_id, Types::Uuid
+ attribute :decision_id, Types::Uuid
+
+ def call
+ with_review do |review|
+ review.add_decision(user_id:, decision_id:)
+ end
+ end
+ end
+end
diff --git a/app/aggregates/reviewing/review.rb b/app/aggregates/reviewing/review.rb
index e4f3fae03..2b81d641b 100644
--- a/app/aggregates/reviewing/review.rb
+++ b/app/aggregates/reviewing/review.rb
@@ -15,11 +15,12 @@ def initialize(id)
@superseded_by = nil
@parent_id = nil
@work_stream = nil
+ @decision_ids = []
end
attr_reader :id, :state, :return_reason, :reviewed_at, :reviewer_id,
:submitted_at, :superseded_by, :superseded_at, :parent_id,
- :work_stream, :application_type
+ :work_stream, :application_type, :decision_ids
alias application_id id
@@ -68,6 +69,16 @@ def mark_as_ready(user_id:)
)
end
+ def add_decision(user_id:, decision_id:)
+ # raise unless Non-means application
+ # raise if completed / decision sent
+ # raise decision_ids.include?(decision_id)
+
+ apply DecisionAdded.new(
+ data: { application_id:, user_id:, decision_id: }
+ )
+ end
+
on ApplicationReceived do |event|
@state = Types::ReviewState[:open]
@received_at = event.timestamp
@@ -77,6 +88,10 @@ def mark_as_ready(user_id:)
@work_stream = event.data.fetch(:work_stream, Types::WorkStreamType['criminal_applications_team'])
end
+ on DecisionAdded do |event|
+ @decision_ids << event.data.fetch(:decision_id)
+ end
+
on SentBack do |event|
@state = Types::ReviewState[:sent_back]
@return_reason = event.data.fetch(:reason, nil)
diff --git a/app/components/review_action_component.rb b/app/components/review_action_component.rb
index ed08301f1..0c28406c8 100644
--- a/app/components/review_action_component.rb
+++ b/app/components/review_action_component.rb
@@ -24,13 +24,16 @@ def target
complete_crime_application_path(application)
when :send_back
new_crime_application_return_path(application)
+ when :add_funding_decision
+ crime_application_decisions_path(application)
when :mark_as_ready
ready_crime_application_path(application)
end
end
def method
- return :get if action == :send_back
+ return :get if %i[send_back].include? action
+ return :post if %i[add_funding_decision].include? action
:put
end
diff --git a/app/controllers/casework/decisions/interests_of_justices_controller.rb b/app/controllers/casework/decisions/interests_of_justices_controller.rb
new file mode 100644
index 000000000..1d26cb8de
--- /dev/null
+++ b/app/controllers/casework/decisions/interests_of_justices_controller.rb
@@ -0,0 +1,50 @@
+module Casework
+ module Decisions
+ class InterestsOfJusticesController < Casework::BaseController
+ before_action :set_crime_application
+
+ def edit
+ agg = Deciding::LoadDecision.call(
+ decision_id: params[:decision_id]
+ )
+
+ @interests_of_justice = ::Decisions::InterestsOfJustice.new(agg.interests_of_justice)
+ end
+
+ def update
+ @interests_of_justice = ::Decisions::InterestsOfJustice.new(
+ interests_of_justice_params
+ )
+
+ @interests_of_justice.validate!
+
+ Deciding::SetInterestsOfJustice.new(
+ decision_id: params[:decision_id],
+ user_id: current_user_id,
+ details: @interests_of_justice.attributes.deep_symbolize_keys
+ ).call
+
+ redirect_to crime_application_decision_path(
+ crime_application_id: params[:crime_application_id], id:
+ params[:decision_id]
+ )
+ rescue ActiveModel::ValidationError
+ render :edit
+ end
+
+ private
+
+ def draft_decision
+ @crime_application.decision
+ end
+
+ def interests_of_justice_params
+ params[:decisions_interests_of_justice].permit(
+ :result, :reason, :assessed_by, :assessed_on
+ )
+ end
+
+ def set_means_decision; end
+ end
+ end
+end
diff --git a/app/controllers/casework/decisions/means_controller.rb b/app/controllers/casework/decisions/means_controller.rb
new file mode 100644
index 000000000..9991a69ca
--- /dev/null
+++ b/app/controllers/casework/decisions/means_controller.rb
@@ -0,0 +1,57 @@
+module Casework
+ module Decisions
+ class InterestsOfJusticesController < Casework::BaseController
+ before_action :set_crime_application
+
+ def edit
+ @interests_of_justice = ::Decisions::InterestsOfJustice.new
+ end
+
+ def update
+ @interests_of_justice = ::Decisions::InterestsOfJustice.new(
+ interests_of_justice_params
+ )
+
+ @interests_of_justice.validate!
+
+ Deciding::SetInterestsOfJustice.new(
+ decision_id: params[:decision_id],
+ user_id: current_user_id,
+ details: @interests_of_justice.attributes.deep_symbolize_keys
+ ).call
+
+ flash_and_redirect :success, :sent_back
+ rescue ActiveModel::ValidationError
+ render :edit
+ end
+
+ private
+
+ def draft_decision
+ @crime_application.decision
+ end
+
+ def interests_of_justice_params
+ params[:decisions_interests_of_justice].permit(
+ :result, :reason, :assessed_by, :assessed_on
+ )
+ end
+
+ def create_draft_decision
+ Reviewing::CreateDraftDecision.new(
+ application_id: params[:crime_application_id],
+ user_id: current_user_id
+ ).call
+ end
+
+ def set_ioj_decision
+ Reviewing::CreateDraftDecision.new(
+ application_id: params[:crime_application_id],
+ user_id: current_user_id
+ ).call
+ end
+
+ def set_means_decision; end
+ end
+ end
+end
diff --git a/app/controllers/casework/decisions_controller.rb b/app/controllers/casework/decisions_controller.rb
new file mode 100644
index 000000000..34c05b2b2
--- /dev/null
+++ b/app/controllers/casework/decisions_controller.rb
@@ -0,0 +1,51 @@
+module Casework
+ class DecisionsController < Casework::BaseController
+ before_action :set_crime_application
+
+ def index
+ @decisions = current_crime_application.review.decision_ids.map do |decision_id|
+ Deciding::LoadDecision.call(decision_id:)
+ end
+ end
+
+ def show
+ agg = Deciding::LoadDecision.call(
+ decision_id: params[:id]
+ )
+
+ @interests_of_justice = ::Decisions::InterestsOfJustice.new(**agg.interests_of_justice)
+ end
+
+ def edit
+ redirect_to edit_crime_application_decision_interests_of_justice_path(
+ crime_application_id: params[:crime_application_id], decision_id:
+ params[:id]
+ )
+ end
+
+ def create
+ decision_id = SecureRandom.uuid
+
+ ActiveRecord::Base.transaction do
+ Reviewing::AddDecision.new(
+ application_id: params[:crime_application_id],
+ user_id: current_user_id,
+ decision_id: decision_id
+ ).call
+
+ Deciding::CreateDraft.new(
+ application_id: params[:crime_application_id],
+ user_id: current_user_id,
+ decision_id: decision_id
+ ).call
+ end
+
+ # Should we change path to be case 1, case 2 etc
+ redirect_to edit_crime_application_decision_interests_of_justice_path(
+ crime_application_id: params[:crime_application_id], decision_id: decision_id
+ )
+ end
+
+ # TODO: scope decision by application
+ end
+end
diff --git a/app/controllers/casework/funding_decisions_controller.rb b/app/controllers/casework/funding_decisions_controller.rb
new file mode 100644
index 000000000..6aa7eec21
--- /dev/null
+++ b/app/controllers/casework/funding_decisions_controller.rb
@@ -0,0 +1,51 @@
+module Casework
+ class FundingDecisionsController < Casework::BaseController
+ before_action :set_crime_application
+
+ def new
+ render 'decisions/interests_of_justice/edit'
+ # @form_object = Decisions::InterestsOfJustice.new
+ end
+
+ def create
+ throw params
+ end
+
+ # rubocop:disable Metrics/MethodLength
+ def update
+ @return_details = Decisions::InterestsOfJustice.new(return_params)
+
+ @return_details.validate!
+
+ Reviewing::EditDecision.new(
+ application_id: params[:crime_application_id],
+ user_id: current_user_id,
+ decision_details: @return_details.attributes
+ ).call
+
+ flash_and_redirect :success, :sent_back
+ rescue ActiveModel::ValidationError
+ render :new
+ rescue Reviewing::AlreadySentBack
+ flash_and_redirect :important, :already_sent_back
+ rescue Reviewing::CannotSendBackWhenCompleted
+ flash_and_redirect :important, :cannot_send_back_when_completed
+ end
+ # rubocop:enable Metrics/MethodLength
+
+ private
+
+ def flash_and_redirect(key, message)
+ flash[key] = I18n.t(message, scope: [:flash, key])
+ if key == :success
+ redirect_to assigned_applications_path
+ else
+ redirect_to crime_application_path(params[:crime_application_id])
+ end
+ end
+
+ def step_params
+ params[:return_details].permit(:reason, :details)
+ end
+ end
+end
diff --git a/app/lib/types.rb b/app/lib/types.rb
index 48efbcfb7..4c180cae1 100644
--- a/app/lib/types.rb
+++ b/app/lib/types.rb
@@ -34,6 +34,8 @@ module Types
ReviewState = Symbol.default(:open).enum(*%i[open sent_back completed marked_as_ready])
+ DecisionState = Symbol.enum(*%i[draft])
+
ReviewType = Symbol.enum(*%i[means non_means pse])
CASEWORKER_ROLE = 'caseworker'.freeze
@@ -57,6 +59,17 @@ module Types
details: String
)
+ # MAAT also returns other result values which we may also need to handle.
+ MeansResult = String.enum('pass', 'fail')
+ InterestsOfJusticeResult = String.enum('pass', 'fail')
+
+ InterestsOfJusticeDecision = Hash.schema(
+ result: InterestsOfJusticeResult,
+ reason: String,
+ assessed_by: String,
+ assessed_on: Date
+ )
+
Report = String.enum(*%w[
caseworker_report
processed_report
diff --git a/app/models/crime_application.rb b/app/models/crime_application.rb
index f55b1cf2e..a396312a5 100644
--- a/app/models/crime_application.rb
+++ b/app/models/crime_application.rb
@@ -43,6 +43,10 @@ def history
@history ||= ApplicationHistory.new(application: self)
end
+ def funding_decisions
+ @funding_decisions ||= [Mock::FundingDecision.draft_maat]
+ end
+
def to_param
id
end
diff --git a/app/models/decision.rb b/app/models/decision.rb
new file mode 100644
index 000000000..573cbb502
--- /dev/null
+++ b/app/models/decision.rb
@@ -0,0 +1,3 @@
+class Decision < ApplicationStruct
+ attribute :interests_of_justice, Types::InterestsOfJusticeDecision
+end
diff --git a/app/models/decisions/interests_of_justice.rb b/app/models/decisions/interests_of_justice.rb
new file mode 100644
index 000000000..6ed6a05cf
--- /dev/null
+++ b/app/models/decisions/interests_of_justice.rb
@@ -0,0 +1,33 @@
+# class Decisions::InterestsOfJustice < ApplicationStruct
+# include ActiveModel::Type::Helpers::AcceptsMultiparameterTime.new
+#
+# attribute? :result, Types::Params::Nil | Types::InterestsOfJusticeResult
+# attribute? :reason, Types::Params::Nil | Types::String
+# attribute? :assessed_by, Types::Params::Nil | Types::String
+# attribute? :assessed_on, Types::Params::Date
+#
+# validates :result, inclusion: { in: Types::InterestsOfJusticeResult.values }
+# validates :reason, :assessed_by, presence: true
+# validates :assessed_on, presence: true
+#
+# # def self.new(attributes)
+# # super attributes.merge(assessed_on:
+# # end
+#
+
+module Decisions
+ class InterestsOfJustice
+ include ActiveModel::Model
+ include ActiveModel::Attributes
+ include ActiveRecord::AttributeAssignment
+
+ attribute :result, :string
+ attribute :reason, :string
+ attribute :assessed_by, :string
+ attribute :assessed_on, :date
+
+ validates :result, inclusion: { in: Types::InterestsOfJusticeResult.values }
+ validates :reason, :assessed_by, presence: true
+ validates :assessed_on, presence: true
+ end
+end
diff --git a/app/models/decisions/outcome.rb b/app/models/decisions/outcome.rb
new file mode 100644
index 000000000..c9807bb3d
--- /dev/null
+++ b/app/models/decisions/outcome.rb
@@ -0,0 +1,10 @@
+module Decisions
+ class Outcome < ApplicationStruct
+ OUTCOMES = [:failed_interests_of_justice, :granted].freeze
+
+ attribute? :outcome, Types::Nil | Types::String
+ attribute? :reason, Types::Nil | Types::String
+
+ validates :outcome, presence: true
+ end
+end
diff --git a/app/models/interests_of_justice_decision.rb b/app/models/interests_of_justice_decision.rb
new file mode 100644
index 000000000..5bc6c1516
--- /dev/null
+++ b/app/models/interests_of_justice_decision.rb
@@ -0,0 +1,18 @@
+class InterestsOfJusticeDecision < ApplicationStruct
+ attribute :interests_of_justice, InterestsOfJusticeDecision
+end
+
+class InterestsOfJusticeDecision
+ include ActiveModel::Model
+ include ActiveModel::Attributes
+ include ActiveRecord::AttributeAssignment
+
+ attribute :result, :string
+ attribute :reason, :string
+ attribute :assessed_by, :string
+ attribute :assessed_on, :date
+
+ validates :result, inclusion: { in: Types::InterestsOfJusticeResult.values }
+ validates :reason, :assessed_by, presence: true
+ validates :assessed_on, presence: true
+end
diff --git a/app/views/casework/decisions/index.html.erb b/app/views/casework/decisions/index.html.erb
new file mode 100644
index 000000000..b373f4626
--- /dev/null
+++ b/app/views/casework/decisions/index.html.erb
@@ -0,0 +1,31 @@
+<% title ':K:LKJ:LKJ:LKJ' %>
+
+
+<% @decisions.each do |decision| %>
+ <%= govuk_summary_card(title: 'Case') do |card|
+
+ interests_of_justice = Decisions::InterestsOfJustice.new(decision.interests_of_justice)
+
+ card.with_action { govuk_link_to('Change', { action: :edit, id: decision.decision_id }) }
+ card.with_summary_list do |list|
+ list.with_row do |row|
+ row.with_key { label_text(:result, scope: [:decisions, :interests_of_justice] ) }
+ row.with_value { interests_of_justice.result }
+ end
+ list.with_row do |row|
+ row.with_key { label_text(:reason, scope: [:decisions, :interests_of_justice] ) }
+ row.with_value { simple_format(interests_of_justice.reason) }
+ end
+
+ list.with_row do |row|
+ row.with_key { label_text(:assessed_by, scope: [:decisions, :interests_of_justice] ) }
+ row.with_value { interests_of_justice.assessed_by }
+ end
+ list.with_row do |row|
+ row.with_key { label_text(:assessed_on, scope: [:decisions, :interests_of_justice] ) }
+ row.with_value { l interests_of_justice.assessed_on, format: :compact }
+ end
+ end
+ end %>
+<% end %>
+
diff --git a/app/views/casework/decisions/interests_of_justices/edit.html.erb b/app/views/casework/decisions/interests_of_justices/edit.html.erb
new file mode 100644
index 000000000..d452d12f2
--- /dev/null
+++ b/app/views/casework/decisions/interests_of_justices/edit.html.erb
@@ -0,0 +1,24 @@
+<% title 'TESING' %>
+
+
+
+
+ <%= @crime_application.reference %>
+
+
+ <%= form_with model: @interests_of_justice,
+ url: crime_application_decision_interests_of_justice_path(), method: :put do |f| %>
+
+ <%= f.govuk_error_summary %>
+
+ <%= f.govuk_collection_radio_buttons :result,
+ ::Types::InterestsOfJusticeResult.values,
+ :to_s
+ %>
+ <%= f.govuk_text_area :reason %>
+ <%= f.govuk_text_field :assessed_by %>
+ <%= f.govuk_date_field :assessed_on, maxlength_enabled: true %>
+ <%= f.govuk_submit %>
+ <% end %>
+
+
diff --git a/app/views/casework/decisions/interests_of_justices/new.html.erb b/app/views/casework/decisions/interests_of_justices/new.html.erb
new file mode 100644
index 000000000..f449f6464
--- /dev/null
+++ b/app/views/casework/decisions/interests_of_justices/new.html.erb
@@ -0,0 +1,23 @@
+<% title 'TESING' %>
+
+
+
+
+ <%= @crime_application.reference %>
+
+
+ <%= form_with model: @interests_of_justice, url: crime_application_add_ioj_decision_path(@crime_application), method: :post do |f| %>
+
+ <%= f.govuk_error_summary %>
+
+ <%= f.govuk_collection_radio_buttons :result,
+ ::Types::InterestsOfJusticeResult.values,
+ :to_s
+ %>
+ <%= f.govuk_text_area :reason %>
+ <%= f.govuk_text_field :assessed_by %>
+ <%= f.govuk_date_field :assessed_on, maxlength_enabled: true %>
+ <%= f.govuk_submit %>
+ <% end %>
+
+
diff --git a/app/views/casework/decisions/show.html.erb b/app/views/casework/decisions/show.html.erb
new file mode 100644
index 000000000..b18226aac
--- /dev/null
+++ b/app/views/casework/decisions/show.html.erb
@@ -0,0 +1,25 @@
+<% title ':K:LKJ:LKJ:LKJ' %>
+
+
+<%= govuk_summary_card(title: 'Case') do |card|
+ card.with_action { govuk_link_to('Change', { action: :edit }) }
+ card.with_summary_list do |list|
+ list.with_row do |row|
+ row.with_key { label_text(:result, scope: [:decisions, :interests_of_justice] ) }
+ row.with_value { @interests_of_justice.result }
+ end
+ list.with_row do |row|
+ row.with_key { label_text(:reason, scope: [:decisions, :interests_of_justice] ) }
+ row.with_value { simple_format(@interests_of_justice.reason) }
+ end
+
+ list.with_row do |row|
+ row.with_key { label_text(:assessed_by, scope: [:decisions, :interests_of_justice] ) }
+ row.with_value { @interests_of_justice.assessed_by }
+ end
+ list.with_row do |row|
+ row.with_key { label_text(:assessed_on, scope: [:decisions, :interests_of_justice] ) }
+ row.with_value { l @interests_of_justice.assessed_on, format: :compact }
+ end
+ end
+end %>
diff --git a/app/views/casework/funding_decisions/new.html.erb b/app/views/casework/funding_decisions/new.html.erb
new file mode 100644
index 000000000..6a606254f
--- /dev/null
+++ b/app/views/casework/funding_decisions/new.html.erb
@@ -0,0 +1,18 @@
+<% title 'TESING' %>
+
+
+
+
+ <%= @crime_application.reference %>
+
+
+ <%= form_with model: @form_object, url: crime_application_funding_decisions_path(@crime_application.id) do |f| %>
+ <%= f.text_field :reason %>
+
+ <%= f.govuk_error_summary %>
+
+ <%= f.govuk_submit %>
+ <% end %>
+
+
+
diff --git a/config/initializers/event_store.rb b/config/initializers/event_store.rb
index 42f4ee4b6..4554db7a2 100644
--- a/config/initializers/event_store.rb
+++ b/config/initializers/event_store.rb
@@ -1,6 +1,8 @@
Rails.configuration.to_prepare do
event_store = Rails.configuration.event_store = RailsEventStore::Client.new
+ Deciding::Configuration.new.call(event_store)
+
#Notifying
NotifierConfiguration.new.call(event_store)
@@ -9,4 +11,5 @@
ReceivedOnReports::Configuration.new.call(event_store)
Reviews::Configuration.new.call(event_store)
CaseworkerReports::Configuration.new.call(event_store)
+
end
diff --git a/config/locales/en/casework.yml b/config/locales/en/casework.yml
index 143661235..fe0cf1676 100644
--- a/config/locales/en/casework.yml
+++ b/config/locales/en/casework.yml
@@ -180,6 +180,13 @@ en:
income_more_than: "%{prefix} more than £12,475?"
income_details: Income
income_details_partner: Partner's income
+
+ decisions:
+ interests_of_justice:
+ result: Interests of justice test results
+ reason: Interests of justice reason
+ assessed_by: Interests of justice test caseworker name
+ assessed_on: Date of interests of justice test
employments_title: Jobs
employment_title: Job
employments:
@@ -575,6 +582,7 @@ en:
calls_to_action:
abandon_reassign_to_self: No, do not reassign
+ add_funding_decision: Add a funding decision
assign_to_self: Assign to your list
clear_search: Clear
confirm_reassign_to_self: Yes, reassign
diff --git a/config/locales/en/helpers.yml b/config/locales/en/helpers.yml
index ee147de7f..205ca9306 100644
--- a/config/locales/en/helpers.yml
+++ b/config/locales/en/helpers.yml
@@ -2,10 +2,24 @@
en:
helpers:
back_link: Back
+ hint:
+ decisions_interests_of_justice:
+ assessed_on: For example, DD/MM/YYY
+ legend:
+ decisions_interests_of_justice:
+ result: What is the interests of justice test result?
+ assessed_on: Enter the date of assessment
+ label:
+ decisions_interests_of_justice:
+ result_options:
+ pass: Passed
+ fail: Refused
+ reason: What is the reason for this?
+ assessed_by: What is the name of the caseworker who assessed this?
+
submit:
save_and_continue: Save and continue
save_and_come_back_later: Save and come back later
subjects:
applicant: client
applicant_and_partner: client %{conjunction} partner
-
diff --git a/config/routes.rb b/config/routes.rb
index e41b20c05..b313269f7 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -36,6 +36,13 @@
put :ready, on: :member
resource :reassign, only: [:new, :create]
resource :return, only: [:new, :create]
+ post 'add_a_funding_decision', to: 'decisions#create'
+
+ resources :decisions do
+ scope module: :decisions do
+ resource :interests_of_justice
+ end
+ end
end
get 'applications/open/:work_stream', to: 'crime_applications#open', as: :open_work_stream
diff --git a/config/settings.yml b/config/settings.yml
index 1c4b83ee0..6504eed26 100644
--- a/config/settings.yml
+++ b/config/settings.yml
@@ -23,6 +23,11 @@ feature_flags:
local: true
staging: true
production: true
+ adding_decisions:
+ local: true
+ staging: false
+ production: false
+
# For settings that vary by HostEnv name
host_env_settings:
phase_banner_tag:
diff --git a/spec/support/capybara_helpers.rb b/spec/support/capybara_helpers.rb
new file mode 100644
index 000000000..0eb2de564
--- /dev/null
+++ b/spec/support/capybara_helpers.rb
@@ -0,0 +1,39 @@
+module CapybaraHelpers
+ def fill_in_date(date)
+ fill_in('Day', with: date.mday)
+ fill_in('Month', with: date.month)
+ fill_in('Year', with: date.year)
+ end
+
+ def fill_date(question, with: nil)
+ date = with || Time.zone.today
+
+ within(find('legend', text: question).sibling('div.govuk-date-input')) do
+ fill_in_date(date)
+ end
+ end
+
+ # radio buttons
+ def choose_answer(question, choice)
+ q = find('legend', text: question).sibling('div.govuk-radios')
+
+ within q do
+ choose(choice)
+ end
+ end
+
+ # check boxes
+ def choose_answers(question, choices = [])
+ q = find('legend', text: question).sibling('div.govuk-checkboxes')
+
+ within q do
+ choices.each do |choice|
+ check(choice)
+ end
+ end
+ end
+
+ def save_and_continue
+ click_button('Save and continue')
+ end
+end
diff --git a/spec/system/casework/reviewing/a_non_means_application_spec.rb b/spec/system/casework/reviewing/a_non_means_application_spec.rb
index 5548e6cee..5abda5034 100644
--- a/spec/system/casework/reviewing/a_non_means_application_spec.rb
+++ b/spec/system/casework/reviewing/a_non_means_application_spec.rb
@@ -2,6 +2,8 @@
RSpec.describe 'Reviewing a Non-means application' do
include_context 'with stubbed application' do
+ let(:feature_flag_enabled?) { false }
+
let(:application_data) do
JSON.parse(LaaCrimeSchemas.fixture(1.0).read).merge(
'is_means_tested' => 'no',
@@ -10,6 +12,10 @@
end
before do
+ allow(FeatureFlags).to receive(:adding_decisions) {
+ instance_double(FeatureFlags::EnabledFeature, enabled?: feature_flag_enabled?)
+ }
+
allow(DatastoreApi::Requests::UpdateApplication).to receive(:new).and_return(
instance_double(DatastoreApi::Requests::UpdateApplication, call: {})
)
@@ -20,10 +26,24 @@
it 'can be completed by the caseworker' do
expect(page).to have_button('Send back to provider')
-
click_button 'Mark as completed'
-
expect(page).to have_content('You marked the application as complete')
end
+
+ context 'when adding decisions feature flag enabled' do
+ let(:feature_flag_enabled?) { true }
+
+ before do
+ click_button 'Start'
+ choose_answer('What is the interests of justice test result?', 'Passed')
+ fill_in('What is the reason for this?', 'Test result reason details')
+ fill_in('Enter the name of the caseworker who assessed this', 'Zoe Blogs')
+ fill_date('Enter the date of assessment', Date.yesterday)
+ save_and_continue
+ end
+
+ it 'can be completed by the caseworker' do
+ end
+ end
end
end
diff --git a/spec/system/casework/reviewing/viewing_a_draft_maat_funding_decision_spec.rb b/spec/system/casework/reviewing/viewing_a_draft_maat_funding_decision_spec.rb
new file mode 100644
index 000000000..e69de29bb
From 1f3f834cbcd54fbe57358ebeff9c5a018b7a2137 Mon Sep 17 00:00:00 2001
From: timpeat
Date: Mon, 16 Sep 2024 18:18:13 +0100
Subject: [PATCH 2/3] WIP extract from spike
---
app/aggregates/deciding.rb | 4 +
.../deciding/commands/create_draft.rb | 2 +-
.../deciding/commands/set_funding_decision.rb | 13 ++++
.../commands/set_interests_of_justice.rb | 4 +-
app/aggregates/deciding/decision.rb | 29 +++++--
app/components/decision_component.rb | 77 +++++++++++++++++++
app/components/funding_decision_component.rb | 29 +++++++
.../decisions/funding_decisions_controller.rb | 23 ++++++
.../interests_of_justices_controller.rb | 45 +++--------
.../casework/decisions_controller.rb | 11 ++-
.../casework/funding_decisions_controller.rb | 51 ------------
app/controllers/concerns/editable_decision.rb | 42 ++++++++++
app/lib/types.rb | 4 +-
app/models/decision.rb | 5 +-
app/models/decisions/funding_decision_form.rb | 41 ++++++++++
app/models/decisions/interests_of_justice.rb | 35 ++-------
.../decisions/interests_of_justice_form.rb | 46 +++++++++++
app/models/interests_of_justice_decision.rb | 2 +-
.../decisions/funding_decisions/edit.html.erb | 22 ++++++
app/views/casework/decisions/index.html.erb | 33 +-------
.../interests_of_justices/edit.html.erb | 6 +-
app/views/casework/decisions/show.html.erb | 22 +-----
config/application.rb | 2 +
config/locales/en/casework.yml | 7 +-
config/locales/en/helpers.yml | 19 ++++-
config/routes.rb | 2 +
26 files changed, 382 insertions(+), 194 deletions(-)
create mode 100644 app/aggregates/deciding/commands/set_funding_decision.rb
create mode 100644 app/components/decision_component.rb
create mode 100644 app/components/funding_decision_component.rb
create mode 100644 app/controllers/casework/decisions/funding_decisions_controller.rb
delete mode 100644 app/controllers/casework/funding_decisions_controller.rb
create mode 100644 app/controllers/concerns/editable_decision.rb
create mode 100644 app/models/decisions/funding_decision_form.rb
create mode 100644 app/models/decisions/interests_of_justice_form.rb
create mode 100644 app/views/casework/decisions/funding_decisions/edit.html.erb
diff --git a/app/aggregates/deciding.rb b/app/aggregates/deciding.rb
index ae3916d8f..144bb8102 100644
--- a/app/aggregates/deciding.rb
+++ b/app/aggregates/deciding.rb
@@ -1,6 +1,10 @@
module Deciding
+ class DecisionNotFound < StandardError; end
+ class ApplicationNotAssignedToUser < StandardError; end
+
class DraftCreated < RailsEventStore::Event; end
class InterestsOfJusticeSet < RailsEventStore::Event; end
+ class FundingDecisionSet < RailsEventStore::Event; end
class << self
def stream_name(decision_id)
diff --git a/app/aggregates/deciding/commands/create_draft.rb b/app/aggregates/deciding/commands/create_draft.rb
index 133400247..fb1a1afd2 100644
--- a/app/aggregates/deciding/commands/create_draft.rb
+++ b/app/aggregates/deciding/commands/create_draft.rb
@@ -5,7 +5,7 @@ class CreateDraft < Command
def call
with_decision do |decision|
- decision.create_draft(user_id:)
+ decision.create_draft(user_id:, application_id:)
end
end
end
diff --git a/app/aggregates/deciding/commands/set_funding_decision.rb b/app/aggregates/deciding/commands/set_funding_decision.rb
new file mode 100644
index 000000000..190d8f5c3
--- /dev/null
+++ b/app/aggregates/deciding/commands/set_funding_decision.rb
@@ -0,0 +1,13 @@
+module Deciding
+ class SetFundingDecision < Command
+ attribute :user_id, Types::Uuid
+ attribute :result, Types::FundingDecisionResult
+ attribute :details, Types::String
+
+ def call
+ with_decision do |decision|
+ decision.set_funding_decision(user_id:, result:, details:)
+ end
+ end
+ end
+end
diff --git a/app/aggregates/deciding/commands/set_interests_of_justice.rb b/app/aggregates/deciding/commands/set_interests_of_justice.rb
index 4ed89b088..1709b71bb 100644
--- a/app/aggregates/deciding/commands/set_interests_of_justice.rb
+++ b/app/aggregates/deciding/commands/set_interests_of_justice.rb
@@ -1,11 +1,11 @@
module Deciding
class SetInterestsOfJustice < Command
attribute :user_id, Types::Uuid
- attribute :details, Types::InterestsOfJusticeDecision
+ attribute :interests_of_justice, Types::InterestsOfJusticeDecision
def call
with_decision do |decision|
- decision.set_interests_of_justice(user_id:, details:)
+ decision.set_interests_of_justice(user_id:, interests_of_justice:)
end
end
end
diff --git a/app/aggregates/deciding/decision.rb b/app/aggregates/deciding/decision.rb
index 071a98465..5afb20f0d 100644
--- a/app/aggregates/deciding/decision.rb
+++ b/app/aggregates/deciding/decision.rb
@@ -8,11 +8,13 @@ def initialize(decision_id)
@case_id = nil
@maat_id = nil
@interests_of_justice = nil
+ @result = nil
+ @details = nil
@means = nil
@state = nil
end
- attr_reader :interests_of_justice, :decision_id
+ attr_reader :interests_of_justice, :application_id, :decision_id, :result, :details
def create_draft(user_id:, application_id:)
apply DraftCreated.new(
@@ -20,21 +22,32 @@ def create_draft(user_id:, application_id:)
)
end
- def set_interests_of_justice(user_id:, details:)
+ def set_interests_of_justice(user_id:, interests_of_justice:)
# TODO: ignore if not changed
apply InterestsOfJusticeSet.new(
- data: { user_id:, details: }
+ data: { decision_id:, application_id:, user_id:, interests_of_justice: }
)
end
-
+
+ def set_funding_decision(user_id:, result:, details:)
+ # TODO: ignore if not changed
+ apply FundingDecisionSet.new(
+ data: { decision_id:, application_id:, user_id:, result:, details: }
+ )
+ end
+
on DraftCreated do |event|
- @interests_of_justice = event.data.fetch(:details)
@application_id = event.data.fetch(:application_id)
@state = Types::DecisionState[:draft]
end
on InterestsOfJusticeSet do |event|
- @interests_of_justice = event.data.fetch(:details)
+ @interests_of_justice = event.data.fetch(:interests_of_justice)
+ end
+
+ on FundingDecisionSet do |event|
+ @result = event.data.fetch(:result)
+ @details = event.data.fetch(:details)
end
def interests_of_justice
@@ -42,5 +55,9 @@ def interests_of_justice
Types::InterestsOfJusticeDecision[@interests_of_justice]
end
+
+ def to_param
+ decision_id
+ end
end
end
diff --git a/app/components/decision_component.rb b/app/components/decision_component.rb
new file mode 100644
index 000000000..d85e5526d
--- /dev/null
+++ b/app/components/decision_component.rb
@@ -0,0 +1,77 @@
+class DecisionComponent < ViewComponent::Base
+
+ include ActionView::Helpers
+ include AppTextHelper
+ # include StepsHelper
+
+ attr_reader :decision
+
+ def initialize(decision:, decision_iteration:)
+ @decision = decision
+ @decision_iteration = decision_iteration
+
+ super
+ end
+
+ def call
+ govuk_summary_card(title:, actions:) do |card|
+ govuk_summary_list do |list|
+ if interests_of_justice.present?
+ list.with_row do |row|
+ row.with_key { label_text(:result, scope: [:decision, :interests_of_justice] ) }
+ row.with_value { interests_of_justice[:result] }
+ end
+
+ list.with_row do |row|
+ row.with_key { label_text(:details, scope: [:decision, :interests_of_justice] ) }
+ row.with_value { simple_format(interests_of_justice[:details]) }
+ end
+
+ list.with_row do |row|
+ row.with_key { label_text(:assessed_by, scope: [:decision, :interests_of_justice] ) }
+ row.with_value { interests_of_justice[:assessed_by] }
+ end
+
+ list.with_row do |row|
+ row.with_key { label_text(:assessed_on, scope: [:decision, :interests_of_justice] ) }
+ row.with_value { l interests_of_justice[:assessed_on], format: :compact }
+ end
+ end
+
+ list.with_row do |row|
+ row.with_key { label_text(:result, scope: [:decision] ) }
+ row.with_value { decision.result }
+ end
+
+ list.with_row do |row|
+ row.with_key { label_text(:details, scope: [:decision] ) }
+ row.with_value { decision.details }
+ end
+ end
+ end
+ end
+
+ private
+
+ attr_reader :decision, :decision_iteration
+
+ delegate :means, :interests_of_justice, to: :decision
+
+ def actions
+ [
+ govuk_link_to('Change', { action: :edit, id: decision.decision_id }),
+ govuk_link_to('Remove', { action: :edit, id: decision.decision_id })
+ ]
+ end
+
+ def title
+ safe_join(['Case', count].compact, ' ')
+ end
+
+ def count
+ return unless decision_iteration
+ return unless decision_iteration.size > 1
+
+ decision_iteration.index + 1
+ end
+end
diff --git a/app/components/funding_decision_component.rb b/app/components/funding_decision_component.rb
new file mode 100644
index 000000000..9dcc2a6c5
--- /dev/null
+++ b/app/components/funding_decision_component.rb
@@ -0,0 +1,29 @@
+class FundingDecisionComponent < ViewComponent::Base
+ # Wraps the Govuk Summary Card component so that when used with
+ # .with_collection the item number is added to the card title.
+
+ def initialize(decision:, decision_iteration:)
+ @item = item
+ @item_title = title
+ @item_iteration = item_iteration
+
+ super
+ end
+
+ def call
+ app_card_list
+ end
+
+ def title
+ safe_join([@item_title, count].compact, ' ')
+ end
+
+ private
+
+ def count
+ return unless item_iteration
+ return unless item_iteration.size > 1
+
+ item_iteration.index + 1
+ end
+end
diff --git a/app/controllers/casework/decisions/funding_decisions_controller.rb b/app/controllers/casework/decisions/funding_decisions_controller.rb
new file mode 100644
index 000000000..c833964ce
--- /dev/null
+++ b/app/controllers/casework/decisions/funding_decisions_controller.rb
@@ -0,0 +1,23 @@
+module Casework
+ module Decisions
+ class FundingDecisionsController < Casework::BaseController
+ include EditableDecision
+
+ private
+
+ def form_class
+ ::Decisions::FundingDecisionForm
+ end
+
+ def permitted_params
+ params[:decisions_funding_decision_form].permit(
+ :result, :details
+ )
+ end
+
+ def next_step
+ crime_application_decisions_path
+ end
+ end
+ end
+end
diff --git a/app/controllers/casework/decisions/interests_of_justices_controller.rb b/app/controllers/casework/decisions/interests_of_justices_controller.rb
index 1d26cb8de..693e8a4f1 100644
--- a/app/controllers/casework/decisions/interests_of_justices_controller.rb
+++ b/app/controllers/casework/decisions/interests_of_justices_controller.rb
@@ -1,50 +1,23 @@
module Casework
module Decisions
class InterestsOfJusticesController < Casework::BaseController
- before_action :set_crime_application
+ include EditableDecision
- def edit
- agg = Deciding::LoadDecision.call(
- decision_id: params[:decision_id]
- )
-
- @interests_of_justice = ::Decisions::InterestsOfJustice.new(agg.interests_of_justice)
- end
-
- def update
- @interests_of_justice = ::Decisions::InterestsOfJustice.new(
- interests_of_justice_params
- )
-
- @interests_of_justice.validate!
-
- Deciding::SetInterestsOfJustice.new(
- decision_id: params[:decision_id],
- user_id: current_user_id,
- details: @interests_of_justice.attributes.deep_symbolize_keys
- ).call
+ private
- redirect_to crime_application_decision_path(
- crime_application_id: params[:crime_application_id], id:
- params[:decision_id]
- )
- rescue ActiveModel::ValidationError
- render :edit
+ def form_class
+ ::Decisions::InterestsOfJusticeForm
end
- private
-
- def draft_decision
- @crime_application.decision
+ def next_step
+ edit_crime_application_decision_funding_decision_path
end
- def interests_of_justice_params
- params[:decisions_interests_of_justice].permit(
- :result, :reason, :assessed_by, :assessed_on
+ def permitted_params
+ params[:decisions_interests_of_justice_form].permit(
+ :result, :details, :assessed_by, :assessed_on
)
end
-
- def set_means_decision; end
end
end
end
diff --git a/app/controllers/casework/decisions_controller.rb b/app/controllers/casework/decisions_controller.rb
index 34c05b2b2..0bd3823be 100644
--- a/app/controllers/casework/decisions_controller.rb
+++ b/app/controllers/casework/decisions_controller.rb
@@ -1,19 +1,18 @@
module Casework
class DecisionsController < Casework::BaseController
before_action :set_crime_application
+ before_action :set_decision, only: [:show]
def index
@decisions = current_crime_application.review.decision_ids.map do |decision_id|
- Deciding::LoadDecision.call(decision_id:)
+ agg = Deciding::LoadDecision.call(
+ application_id: params[:crime_application_id],
+ decision_id:
+ )
end
end
def show
- agg = Deciding::LoadDecision.call(
- decision_id: params[:id]
- )
-
- @interests_of_justice = ::Decisions::InterestsOfJustice.new(**agg.interests_of_justice)
end
def edit
diff --git a/app/controllers/casework/funding_decisions_controller.rb b/app/controllers/casework/funding_decisions_controller.rb
deleted file mode 100644
index 6aa7eec21..000000000
--- a/app/controllers/casework/funding_decisions_controller.rb
+++ /dev/null
@@ -1,51 +0,0 @@
-module Casework
- class FundingDecisionsController < Casework::BaseController
- before_action :set_crime_application
-
- def new
- render 'decisions/interests_of_justice/edit'
- # @form_object = Decisions::InterestsOfJustice.new
- end
-
- def create
- throw params
- end
-
- # rubocop:disable Metrics/MethodLength
- def update
- @return_details = Decisions::InterestsOfJustice.new(return_params)
-
- @return_details.validate!
-
- Reviewing::EditDecision.new(
- application_id: params[:crime_application_id],
- user_id: current_user_id,
- decision_details: @return_details.attributes
- ).call
-
- flash_and_redirect :success, :sent_back
- rescue ActiveModel::ValidationError
- render :new
- rescue Reviewing::AlreadySentBack
- flash_and_redirect :important, :already_sent_back
- rescue Reviewing::CannotSendBackWhenCompleted
- flash_and_redirect :important, :cannot_send_back_when_completed
- end
- # rubocop:enable Metrics/MethodLength
-
- private
-
- def flash_and_redirect(key, message)
- flash[key] = I18n.t(message, scope: [:flash, key])
- if key == :success
- redirect_to assigned_applications_path
- else
- redirect_to crime_application_path(params[:crime_application_id])
- end
- end
-
- def step_params
- params[:return_details].permit(:reason, :details)
- end
- end
-end
diff --git a/app/controllers/concerns/editable_decision.rb b/app/controllers/concerns/editable_decision.rb
new file mode 100644
index 000000000..0322a82c5
--- /dev/null
+++ b/app/controllers/concerns/editable_decision.rb
@@ -0,0 +1,42 @@
+module EditableDecision
+ extend ActiveSupport::Concern
+
+ included do
+ before_action :set_crime_application
+ before_action :set_decision
+ before_action :confirm_assigned
+ before_action :set_form
+ end
+
+ def edit; end
+
+ def update
+ @form_object.update_with_user!(
+ permitted_params, current_user_id
+ )
+
+ redirect_to next_step
+ rescue ActiveModel::ValidationError
+ render :edit
+ end
+
+ private
+
+ def set_decision
+ decision = Deciding::LoadDecision.call(
+ decision_id: params[:decision_id]
+ )
+
+ raise Deciding::DecisionNotFound unless decision.application_id == current_crime_application.id
+
+ @decision = decision
+ end
+
+ def set_form
+ @form_object = form_class.build(@decision)
+ end
+
+ def confirm_assigned
+ raise Deciding::DecisionNotFound unless @crime_application.reviewable_by?(current_user_id)
+ end
+end
diff --git a/app/lib/types.rb b/app/lib/types.rb
index 4c180cae1..60f5a8218 100644
--- a/app/lib/types.rb
+++ b/app/lib/types.rb
@@ -62,13 +62,15 @@ module Types
# MAAT also returns other result values which we may also need to handle.
MeansResult = String.enum('pass', 'fail')
InterestsOfJusticeResult = String.enum('pass', 'fail')
+ FundingDecisionResult = String.enum(*%w[granted_on_ioj fail_on_ioj])
InterestsOfJusticeDecision = Hash.schema(
result: InterestsOfJusticeResult,
- reason: String,
+ details: String,
assessed_by: String,
assessed_on: Date
)
+
Report = String.enum(*%w[
caseworker_report
diff --git a/app/models/decision.rb b/app/models/decision.rb
index 573cbb502..2520d8317 100644
--- a/app/models/decision.rb
+++ b/app/models/decision.rb
@@ -1,3 +1,6 @@
class Decision < ApplicationStruct
- attribute :interests_of_justice, Types::InterestsOfJusticeDecision
+ attribute? :interests_of_justice, Decisions::InterestsOfJustice
+ attribute? :result, Types::String
+ attribute? :details, Types::String
+ attribute? :decision_id, Types::Uuid
end
diff --git a/app/models/decisions/funding_decision_form.rb b/app/models/decisions/funding_decision_form.rb
new file mode 100644
index 000000000..9422770d7
--- /dev/null
+++ b/app/models/decisions/funding_decision_form.rb
@@ -0,0 +1,41 @@
+module Decisions
+ class FundingDecisionForm
+ include ActiveModel::Model
+ include ActiveModel::Attributes
+ include ActiveRecord::AttributeAssignment
+ include ActiveModel::Dirty
+
+ attribute :application_id, :immutable_string
+ attribute :decision_id, :immutable_string
+
+ attribute :result, :string
+ attribute :details, :string
+
+ validates :result, inclusion: { in: :possible_results }
+
+ def possible_results
+ Types::FundingDecisionResult.values
+ end
+
+ def update_with_user!(attributes, user_id)
+ assign_attributes(attributes)
+ validate!
+ return unless changed?
+
+ Deciding::SetFundingDecision.new(
+ decision_id:, user_id:, result:, details:
+ ).call
+ end
+
+ class << self
+ def build(decision)
+ new(
+ application_id: decision.application_id,
+ decision_id: decision.decision_id,
+ result: decision.result,
+ details: decision.details
+ )
+ end
+ end
+ end
+end
diff --git a/app/models/decisions/interests_of_justice.rb b/app/models/decisions/interests_of_justice.rb
index 6ed6a05cf..2aa237334 100644
--- a/app/models/decisions/interests_of_justice.rb
+++ b/app/models/decisions/interests_of_justice.rb
@@ -1,33 +1,8 @@
-# class Decisions::InterestsOfJustice < ApplicationStruct
-# include ActiveModel::Type::Helpers::AcceptsMultiparameterTime.new
-#
-# attribute? :result, Types::Params::Nil | Types::InterestsOfJusticeResult
-# attribute? :reason, Types::Params::Nil | Types::String
-# attribute? :assessed_by, Types::Params::Nil | Types::String
-# attribute? :assessed_on, Types::Params::Date
-#
-# validates :result, inclusion: { in: Types::InterestsOfJusticeResult.values }
-# validates :reason, :assessed_by, presence: true
-# validates :assessed_on, presence: true
-#
-# # def self.new(attributes)
-# # super attributes.merge(assessed_on:
-# # end
-#
-
module Decisions
- class InterestsOfJustice
- include ActiveModel::Model
- include ActiveModel::Attributes
- include ActiveRecord::AttributeAssignment
-
- attribute :result, :string
- attribute :reason, :string
- attribute :assessed_by, :string
- attribute :assessed_on, :date
-
- validates :result, inclusion: { in: Types::InterestsOfJusticeResult.values }
- validates :reason, :assessed_by, presence: true
- validates :assessed_on, presence: true
+ class InterestsOfJustice < ApplicationStruct
+ attribute :result, Types::InterestsOfJusticeResult
+ attribute :details, Types::String
+ attribute :assessed_by, Types::String
+ attribute :assessed_on, Types::Date
end
end
diff --git a/app/models/decisions/interests_of_justice_form.rb b/app/models/decisions/interests_of_justice_form.rb
new file mode 100644
index 000000000..6824514ca
--- /dev/null
+++ b/app/models/decisions/interests_of_justice_form.rb
@@ -0,0 +1,46 @@
+module Decisions
+ class InterestsOfJusticeForm
+ include ActiveModel::Model
+ include ActiveModel::Attributes
+ include ActiveRecord::AttributeAssignment
+ include ActiveModel::Dirty
+
+ attribute :application_id, :immutable_string
+ attribute :decision_id, :immutable_string
+
+ attribute :result, :string
+ attribute :details, :string
+ attribute :assessed_by, :string
+ attribute :assessed_on, :date
+
+ validates :result, inclusion: { in: :possible_results }
+ validates :details, :assessed_by, presence: true
+ validates :assessed_on, presence: true
+
+ def possible_results
+ Types::InterestsOfJusticeResult.values
+ end
+
+ def update_with_user!(attributes, user_id)
+ assign_attributes(attributes)
+ validate!
+ return unless changed?
+
+ Deciding::SetInterestsOfJustice.new(
+ decision_id: decision_id,
+ user_id: user_id,
+ interests_of_justice: self.attributes.deep_symbolize_keys
+ ).call
+ end
+
+ class << self
+ def build(decision)
+ new(
+ **(decision.interests_of_justice || {}),
+ application_id: decision.application_id,
+ decision_id: decision.decision_id
+ )
+ end
+ end
+ end
+end
diff --git a/app/models/interests_of_justice_decision.rb b/app/models/interests_of_justice_decision.rb
index 5bc6c1516..1cc300315 100644
--- a/app/models/interests_of_justice_decision.rb
+++ b/app/models/interests_of_justice_decision.rb
@@ -8,7 +8,7 @@ class InterestsOfJusticeDecision
include ActiveRecord::AttributeAssignment
attribute :result, :string
- attribute :reason, :string
+ attribute :details, :string
attribute :assessed_by, :string
attribute :assessed_on, :date
diff --git a/app/views/casework/decisions/funding_decisions/edit.html.erb b/app/views/casework/decisions/funding_decisions/edit.html.erb
new file mode 100644
index 000000000..d63aaeab9
--- /dev/null
+++ b/app/views/casework/decisions/funding_decisions/edit.html.erb
@@ -0,0 +1,22 @@
+<% title 'TESING' %>
+
+
+
+
+ <%= @crime_application.reference %>
+
+
+ <%= form_with model: @form_object,
+ url: crime_application_decision_funding_decision_path(), method: :put do |f| %>
+
+ <%= f.govuk_error_summary %>
+
+ <%= f.govuk_collection_radio_buttons :result,
+ @form_object.possible_results,
+ :to_s
+ %>
+ <%= f.govuk_text_area :details %>
+ <%= f.govuk_submit %>
+ <% end %>
+
+
diff --git a/app/views/casework/decisions/index.html.erb b/app/views/casework/decisions/index.html.erb
index b373f4626..da29690d4 100644
--- a/app/views/casework/decisions/index.html.erb
+++ b/app/views/casework/decisions/index.html.erb
@@ -1,31 +1,6 @@
<% title ':K:LKJ:LKJ:LKJ' %>
-
-
-<% @decisions.each do |decision| %>
- <%= govuk_summary_card(title: 'Case') do |card|
-
- interests_of_justice = Decisions::InterestsOfJustice.new(decision.interests_of_justice)
-
- card.with_action { govuk_link_to('Change', { action: :edit, id: decision.decision_id }) }
- card.with_summary_list do |list|
- list.with_row do |row|
- row.with_key { label_text(:result, scope: [:decisions, :interests_of_justice] ) }
- row.with_value { interests_of_justice.result }
- end
- list.with_row do |row|
- row.with_key { label_text(:reason, scope: [:decisions, :interests_of_justice] ) }
- row.with_value { simple_format(interests_of_justice.reason) }
- end
-
- list.with_row do |row|
- row.with_key { label_text(:assessed_by, scope: [:decisions, :interests_of_justice] ) }
- row.with_value { interests_of_justice.assessed_by }
- end
- list.with_row do |row|
- row.with_key { label_text(:assessed_on, scope: [:decisions, :interests_of_justice] ) }
- row.with_value { l interests_of_justice.assessed_on, format: :compact }
- end
- end
- end %>
-<% end %>
+<%= render(
+ DecisionComponent.with_collection(
+ @decisions
+ )) %>
diff --git a/app/views/casework/decisions/interests_of_justices/edit.html.erb b/app/views/casework/decisions/interests_of_justices/edit.html.erb
index d452d12f2..05e6ad3f6 100644
--- a/app/views/casework/decisions/interests_of_justices/edit.html.erb
+++ b/app/views/casework/decisions/interests_of_justices/edit.html.erb
@@ -6,16 +6,16 @@
<%= @crime_application.reference %>
- <%= form_with model: @interests_of_justice,
+ <%= form_with model: @form_object,
url: crime_application_decision_interests_of_justice_path(), method: :put do |f| %>
<%= f.govuk_error_summary %>
<%= f.govuk_collection_radio_buttons :result,
- ::Types::InterestsOfJusticeResult.values,
+ @form_object.possible_results,
:to_s
%>
- <%= f.govuk_text_area :reason %>
+ <%= f.govuk_text_area :details %>
<%= f.govuk_text_field :assessed_by %>
<%= f.govuk_date_field :assessed_on, maxlength_enabled: true %>
<%= f.govuk_submit %>
diff --git a/app/views/casework/decisions/show.html.erb b/app/views/casework/decisions/show.html.erb
index b18226aac..a982539ca 100644
--- a/app/views/casework/decisions/show.html.erb
+++ b/app/views/casework/decisions/show.html.erb
@@ -1,25 +1,5 @@
<% title ':K:LKJ:LKJ:LKJ' %>
-<%= govuk_summary_card(title: 'Case') do |card|
- card.with_action { govuk_link_to('Change', { action: :edit }) }
- card.with_summary_list do |list|
- list.with_row do |row|
- row.with_key { label_text(:result, scope: [:decisions, :interests_of_justice] ) }
- row.with_value { @interests_of_justice.result }
- end
- list.with_row do |row|
- row.with_key { label_text(:reason, scope: [:decisions, :interests_of_justice] ) }
- row.with_value { simple_format(@interests_of_justice.reason) }
- end
+<%= render @decision %>
- list.with_row do |row|
- row.with_key { label_text(:assessed_by, scope: [:decisions, :interests_of_justice] ) }
- row.with_value { @interests_of_justice.assessed_by }
- end
- list.with_row do |row|
- row.with_key { label_text(:assessed_on, scope: [:decisions, :interests_of_justice] ) }
- row.with_value { l @interests_of_justice.assessed_on, format: :compact }
- end
- end
-end %>
diff --git a/config/application.rb b/config/application.rb
index 37dcaf4df..84017ab61 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -79,6 +79,8 @@ class Application < Rails::Application
config.action_dispatch.rescue_responses.merge!(
'Reporting::ReportNotFound' => :not_found,
'Allocating::WorkStreamNotFound' => :not_found,
+ 'Deciding::DecisionNotFound' => :not_found,
+ 'Deciding::ApplicationNotAssignedToUser' => :forbidden,
'ApplicationController::ForbiddenError' => :forbidden
)
end
diff --git a/config/locales/en/casework.yml b/config/locales/en/casework.yml
index fe0cf1676..9540786ca 100644
--- a/config/locales/en/casework.yml
+++ b/config/locales/en/casework.yml
@@ -181,12 +181,15 @@ en:
income_details: Income
income_details_partner: Partner's income
- decisions:
+ decision:
+ card_title: Case
interests_of_justice:
result: Interests of justice test results
- reason: Interests of justice reason
+ details: Interests of justice reason
assessed_by: Interests of justice test caseworker name
assessed_on: Date of interests of justice test
+ result: Overall result
+ details: Further information about the decision
employments_title: Jobs
employment_title: Job
employments:
diff --git a/config/locales/en/helpers.yml b/config/locales/en/helpers.yml
index 205ca9306..a6417188b 100644
--- a/config/locales/en/helpers.yml
+++ b/config/locales/en/helpers.yml
@@ -2,21 +2,32 @@
en:
helpers:
back_link: Back
+
hint:
- decisions_interests_of_justice:
+ decisions_interests_of_justice_form:
assessed_on: For example, DD/MM/YYY
+
legend:
- decisions_interests_of_justice:
+ decisions_interests_of_justice_form:
result: What is the interests of justice test result?
assessed_on: Enter the date of assessment
+ decisions_funding_decision_form:
+ result: What is the funding decision for this application?
+
label:
- decisions_interests_of_justice:
+ decisions_interests_of_justice_form:
result_options:
pass: Passed
fail: Refused
- reason: What is the reason for this?
+ details: What is the reason for this?
assessed_by: What is the name of the caseworker who assessed this?
+ decisions_funding_decision_form:
+ result_options:
+ granted_on_ioj: Granted
+ fail_on_ioj: Failed interests of justice test
+ details: Additional comments for the provider (optional)
+
submit:
save_and_continue: Save and continue
save_and_come_back_later: Save and come back later
diff --git a/config/routes.rb b/config/routes.rb
index b313269f7..9a7f47959 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -1,5 +1,6 @@
Rails.application.routes.draw do
mount DatastoreApi::HealthEngine::Engine => '/datastore'
+ mount RailsEventStore::Browser => "/res" if Rails.env.development?
get :health, to: 'healthcheck#show'
get :ping, to: 'healthcheck#ping'
@@ -41,6 +42,7 @@
resources :decisions do
scope module: :decisions do
resource :interests_of_justice
+ resource :funding_decision
end
end
end
From 3eb2bc9d2d5e5f0d3867933abbf650fc6353da25 Mon Sep 17 00:00:00 2001
From: timpeat
Date: Tue, 17 Sep 2024 16:31:46 +0100
Subject: [PATCH 3/3] wip
---
app/aggregates/deciding/decision.rb | 15 ++----
app/aggregates/reviewing.rb | 1 +
.../reviewing/commands/remove_decision.rb | 13 +++++
app/aggregates/reviewing/review.rb | 40 +++++++---------
app/components/decision_component.rb | 41 +++++++++-------
app/components/decision_result_component.rb | 29 +++++++++++
app/components/review_action_component.rb | 16 +++++--
.../decisions/funding_decisions_controller.rb | 3 ++
.../interests_of_justices_controller.rb | 10 ++--
.../casework/decisions_controller.rb | 48 +++++++++++--------
app/controllers/concerns/editable_decision.rb | 7 ++-
app/helpers/components_helper.rb | 4 ++
app/lib/types.rb | 1 -
app/models/decisions/funding_decision_form.rb | 4 +-
.../decisions/interests_of_justice_form.rb | 2 +-
.../decisions/funding_decisions/edit.html.erb | 17 ++++---
app/views/casework/decisions/index.html.erb | 25 ++++++++--
.../interests_of_justices/edit.html.erb | 10 +++-
app/views/casework/decisions/show.html.erb | 5 --
config/locales/en/casework.yml | 20 +++++++-
config/routes.rb | 6 ++-
21 files changed, 207 insertions(+), 110 deletions(-)
create mode 100644 app/aggregates/reviewing/commands/remove_decision.rb
create mode 100644 app/components/decision_result_component.rb
delete mode 100644 app/views/casework/decisions/show.html.erb
diff --git a/app/aggregates/deciding/decision.rb b/app/aggregates/deciding/decision.rb
index 5afb20f0d..537e082c6 100644
--- a/app/aggregates/deciding/decision.rb
+++ b/app/aggregates/deciding/decision.rb
@@ -4,17 +4,10 @@ class Decision
def initialize(decision_id)
@decision_id = decision_id
- @application_id = nil
- @case_id = nil
- @maat_id = nil
@interests_of_justice = nil
- @result = nil
- @details = nil
- @means = nil
- @state = nil
end
- attr_reader :interests_of_justice, :application_id, :decision_id, :result, :details
+ attr_accessor :application_id, :decision_id, :result, :details, :state
def create_draft(user_id:, application_id:)
apply DraftCreated.new(
@@ -23,19 +16,17 @@ def create_draft(user_id:, application_id:)
end
def set_interests_of_justice(user_id:, interests_of_justice:)
- # TODO: ignore if not changed
apply InterestsOfJusticeSet.new(
data: { decision_id:, application_id:, user_id:, interests_of_justice: }
)
end
-
+
def set_funding_decision(user_id:, result:, details:)
- # TODO: ignore if not changed
apply FundingDecisionSet.new(
data: { decision_id:, application_id:, user_id:, result:, details: }
)
end
-
+
on DraftCreated do |event|
@application_id = event.data.fetch(:application_id)
@state = Types::DecisionState[:draft]
diff --git a/app/aggregates/reviewing.rb b/app/aggregates/reviewing.rb
index a647a0ada..8692bebea 100644
--- a/app/aggregates/reviewing.rb
+++ b/app/aggregates/reviewing.rb
@@ -16,6 +16,7 @@ class CannotSendBackWhenCompleted < Error; end
class NotReceived < Error; end
class DecisionAdded < Event; end
+ class DecisionRemoved < Event; end
class << self
def stream_name(application_id)
diff --git a/app/aggregates/reviewing/commands/remove_decision.rb b/app/aggregates/reviewing/commands/remove_decision.rb
new file mode 100644
index 000000000..3b3ef061d
--- /dev/null
+++ b/app/aggregates/reviewing/commands/remove_decision.rb
@@ -0,0 +1,13 @@
+module Reviewing
+ class RemoveDecision < Command
+ attribute :application_id, Types::Uuid
+ attribute :user_id, Types::Uuid
+ attribute :decision_id, Types::Uuid
+
+ def call
+ with_review do |review|
+ review.remove_decision(user_id:, decision_id:)
+ end
+ end
+ end
+end
diff --git a/app/aggregates/reviewing/review.rb b/app/aggregates/reviewing/review.rb
index 2b81d641b..64184458f 100644
--- a/app/aggregates/reviewing/review.rb
+++ b/app/aggregates/reviewing/review.rb
@@ -4,23 +4,13 @@ class Review
def initialize(id)
@id = id
- @application_type = nil
- @state = nil
- @return_reason = nil
- @reviewer_id = nil
- @reviewed_at = nil
- @received_at = nil
- @submitted_at = nil
- @superseded_at = nil
- @superseded_by = nil
- @parent_id = nil
- @work_stream = nil
@decision_ids = []
end
- attr_reader :id, :state, :return_reason, :reviewed_at, :reviewer_id,
- :submitted_at, :superseded_by, :superseded_at, :parent_id,
- :work_stream, :application_type, :decision_ids
+ attr_accessor :state, :return_reason, :reviewed_at, :reviewer_id, :submitted_at, :superseded_by,
+ :superseded_at, :parent_id, :work_stream, :application_type
+
+ attr_reader :id, :decision_ids
alias application_id id
@@ -70,15 +60,17 @@ def mark_as_ready(user_id:)
end
def add_decision(user_id:, decision_id:)
- # raise unless Non-means application
- # raise if completed / decision sent
- # raise decision_ids.include?(decision_id)
-
apply DecisionAdded.new(
data: { application_id:, user_id:, decision_id: }
)
end
+ def remove_decision(user_id:, decision_id:)
+ apply DecisionRemoved.new(
+ data: { application_id:, user_id:, decision_id: }
+ )
+ end
+
on ApplicationReceived do |event|
@state = Types::ReviewState[:open]
@received_at = event.timestamp
@@ -92,6 +84,10 @@ def add_decision(user_id:, decision_id:)
@decision_ids << event.data.fetch(:decision_id)
end
+ on DecisionRemoved do |event|
+ @decision_ids -= [event.data.fetch(:decision_id)]
+ end
+
on SentBack do |event|
@state = Types::ReviewState[:sent_back]
@return_reason = event.data.fetch(:reason, nil)
@@ -123,15 +119,11 @@ def received?
end
def business_day
- return nil unless @submitted_at
-
- BusinessDay.new(day_zero: @submitted_at)
+ BusinessDay.new(day_zero: @submitted_at) if @submitted_at.present?
end
def reviewed_on
- return nil unless @reviewed_at
-
- @reviewed_at.in_time_zone('London').to_date
+ @reviewed_at.in_time_zone('London').to_date if @reviewed_at.present?
end
def available_reviewer_actions
diff --git a/app/components/decision_component.rb b/app/components/decision_component.rb
index d85e5526d..9363b116f 100644
--- a/app/components/decision_component.rb
+++ b/app/components/decision_component.rb
@@ -1,10 +1,6 @@
class DecisionComponent < ViewComponent::Base
-
include ActionView::Helpers
include AppTextHelper
- # include StepsHelper
-
- attr_reader :decision
def initialize(decision:, decision_iteration:)
@decision = decision
@@ -14,37 +10,37 @@ def initialize(decision:, decision_iteration:)
end
def call
- govuk_summary_card(title:, actions:) do |card|
+ govuk_summary_card(title:, actions:) do |_card|
govuk_summary_list do |list|
if interests_of_justice.present?
list.with_row do |row|
- row.with_key { label_text(:result, scope: [:decision, :interests_of_justice] ) }
- row.with_value { interests_of_justice[:result] }
+ row.with_key { label_text(:result, scope: [:decision, :interests_of_justice]) }
+ row.with_value { ioj_result }
end
list.with_row do |row|
- row.with_key { label_text(:details, scope: [:decision, :interests_of_justice] ) }
+ row.with_key { label_text(:details, scope: [:decision, :interests_of_justice]) }
row.with_value { simple_format(interests_of_justice[:details]) }
end
list.with_row do |row|
- row.with_key { label_text(:assessed_by, scope: [:decision, :interests_of_justice] ) }
+ row.with_key { label_text(:assessed_by, scope: [:decision, :interests_of_justice]) }
row.with_value { interests_of_justice[:assessed_by] }
end
list.with_row do |row|
- row.with_key { label_text(:assessed_on, scope: [:decision, :interests_of_justice] ) }
+ row.with_key { label_text(:assessed_on, scope: [:decision, :interests_of_justice]) }
row.with_value { l interests_of_justice[:assessed_on], format: :compact }
end
end
list.with_row do |row|
- row.with_key { label_text(:result, scope: [:decision] ) }
- row.with_value { decision.result }
+ row.with_key { label_text(:result, scope: [:decision]) }
+ row.with_value { render DecisionResultComponent.new(result: decision.result) }
end
-
+
list.with_row do |row|
- row.with_key { label_text(:details, scope: [:decision] ) }
+ row.with_key { label_text(:details, scope: [:decision]) }
row.with_value { decision.details }
end
end
@@ -53,15 +49,24 @@ def call
private
+ def ioj_result
+ t(interests_of_justice[:result], scope: [:values, :decision_result])
+ end
+
attr_reader :decision, :decision_iteration
delegate :means, :interests_of_justice, to: :decision
def actions
- [
- govuk_link_to('Change', { action: :edit, id: decision.decision_id }),
- govuk_link_to('Remove', { action: :edit, id: decision.decision_id })
- ]
+ [change_link, remove_link].compact
+ end
+
+ def remove_link
+ button_to('Remove', { action: :destroy, id: decision.decision_id }, method: :delete)
+ end
+
+ def change_link
+ govuk_link_to('Change', { action: :edit, id: decision.decision_id })
end
def title
diff --git a/app/components/decision_result_component.rb b/app/components/decision_result_component.rb
new file mode 100644
index 000000000..d3447e6ef
--- /dev/null
+++ b/app/components/decision_result_component.rb
@@ -0,0 +1,29 @@
+class DecisionResultComponent < ViewComponent::Base
+ def initialize(result: nil)
+ @result = result
+
+ super
+ end
+
+ def call
+ return if result.nil?
+
+ govuk_tag(
+ text: t(result, scope: [:values, :decision_result]),
+ colour: colour
+ )
+ end
+
+ private
+
+ attr_reader :result
+
+ def colour
+ case result
+ when /fail/
+ 'red'
+ else
+ 'green'
+ end
+ end
+end
diff --git a/app/components/review_action_component.rb b/app/components/review_action_component.rb
index 0c28406c8..48cddfa40 100644
--- a/app/components/review_action_component.rb
+++ b/app/components/review_action_component.rb
@@ -32,10 +32,20 @@ def target
end
def method
- return :get if %i[send_back].include? action
- return :post if %i[add_funding_decision].include? action
+ case action
+ when :send_back
+ :get
+ when :add_funding_decision
+ add_funding_decision_method
+ else
+ :put
+ end
+ end
+
+ def add_funding_decision_method
+ return :get unless application.review.decision_ids.empty?
- :put
+ :post
end
def warning
diff --git a/app/controllers/casework/decisions/funding_decisions_controller.rb b/app/controllers/casework/decisions/funding_decisions_controller.rb
index c833964ce..634ad9f49 100644
--- a/app/controllers/casework/decisions/funding_decisions_controller.rb
+++ b/app/controllers/casework/decisions/funding_decisions_controller.rb
@@ -1,8 +1,11 @@
module Casework
module Decisions
+ # rename overall result?
class FundingDecisionsController < Casework::BaseController
include EditableDecision
+ before_action :set_form
+
private
def form_class
diff --git a/app/controllers/casework/decisions/interests_of_justices_controller.rb b/app/controllers/casework/decisions/interests_of_justices_controller.rb
index 693e8a4f1..45992f3a4 100644
--- a/app/controllers/casework/decisions/interests_of_justices_controller.rb
+++ b/app/controllers/casework/decisions/interests_of_justices_controller.rb
@@ -3,21 +3,23 @@ module Decisions
class InterestsOfJusticesController < Casework::BaseController
include EditableDecision
+ before_action :set_form
+
private
def form_class
::Decisions::InterestsOfJusticeForm
end
- def next_step
- edit_crime_application_decision_funding_decision_path
- end
-
def permitted_params
params[:decisions_interests_of_justice_form].permit(
:result, :details, :assessed_by, :assessed_on
)
end
+
+ def next_step
+ edit_crime_application_decision_funding_decision_path
+ end
end
end
end
diff --git a/app/controllers/casework/decisions_controller.rb b/app/controllers/casework/decisions_controller.rb
index 0bd3823be..6ded05759 100644
--- a/app/controllers/casework/decisions_controller.rb
+++ b/app/controllers/casework/decisions_controller.rb
@@ -1,20 +1,18 @@
module Casework
class DecisionsController < Casework::BaseController
- before_action :set_crime_application
- before_action :set_decision, only: [:show]
+ include EditableDecision
+
+ before_action :set_decision, except: [:index, :create]
def index
@decisions = current_crime_application.review.decision_ids.map do |decision_id|
- agg = Deciding::LoadDecision.call(
+ Deciding::LoadDecision.call(
application_id: params[:crime_application_id],
- decision_id:
+ decision_id: decision_id
)
end
end
- def show
- end
-
def edit
redirect_to edit_crime_application_decision_interests_of_justice_path(
crime_application_id: params[:crime_application_id], decision_id:
@@ -22,29 +20,39 @@ def edit
)
end
+ def confirm_destroy; end
+
def create
decision_id = SecureRandom.uuid
- ActiveRecord::Base.transaction do
- Reviewing::AddDecision.new(
- application_id: params[:crime_application_id],
- user_id: current_user_id,
- decision_id: decision_id
- ).call
+ args = {
+ application_id: @crime_application.id,
+ user_id: current_user_id,
+ decision_id: decision_id
+ }
- Deciding::CreateDraft.new(
- application_id: params[:crime_application_id],
- user_id: current_user_id,
- decision_id: decision_id
- ).call
+ ActiveRecord::Base.transaction do
+ Reviewing::AddDecision.call(**args)
+ Deciding::CreateDraft.call(**args)
end
- # Should we change path to be case 1, case 2 etc
redirect_to edit_crime_application_decision_interests_of_justice_path(
crime_application_id: params[:crime_application_id], decision_id: decision_id
)
end
- # TODO: scope decision by application
+ def destroy
+ args = {
+ application_id: @crime_application.id,
+ user_id: current_user_id,
+ decision_id: @decision.decision_id
+ }
+
+ ActiveRecord::Base.transaction do
+ Reviewing::RemoveDecision.new(**args).call
+ end
+
+ redirect_to action: :index
+ end
end
end
diff --git a/app/controllers/concerns/editable_decision.rb b/app/controllers/concerns/editable_decision.rb
index 0322a82c5..743ed598d 100644
--- a/app/controllers/concerns/editable_decision.rb
+++ b/app/controllers/concerns/editable_decision.rb
@@ -1,11 +1,10 @@
-module EditableDecision
+module EditableDecision
extend ActiveSupport::Concern
included do
before_action :set_crime_application
before_action :set_decision
before_action :confirm_assigned
- before_action :set_form
end
def edit; end
@@ -24,10 +23,10 @@ def update
def set_decision
decision = Deciding::LoadDecision.call(
- decision_id: params[:decision_id]
+ decision_id: params[:decision_id] || params[:id]
)
- raise Deciding::DecisionNotFound unless decision.application_id == current_crime_application.id
+ raise Deciding::DecisionNotFound unless decision.application_id == current_crime_application.id
@decision = decision
end
diff --git a/app/helpers/components_helper.rb b/app/helpers/components_helper.rb
index 712e8a332..ff84f1f48 100644
--- a/app/helpers/components_helper.rb
+++ b/app/helpers/components_helper.rb
@@ -11,6 +11,10 @@ def offence_dates(offence)
render OffenceDatesComponent.new(offence:)
end
+ def decision_result(result)
+ render DecisionResultComponent.new(result:)
+ end
+
def conflict_of_interest(codefendant)
render ConflictOfInterestComponent.new(codefendant:)
end
diff --git a/app/lib/types.rb b/app/lib/types.rb
index 60f5a8218..ee3005bb5 100644
--- a/app/lib/types.rb
+++ b/app/lib/types.rb
@@ -70,7 +70,6 @@ module Types
assessed_by: String,
assessed_on: Date
)
-
Report = String.enum(*%w[
caseworker_report
diff --git a/app/models/decisions/funding_decision_form.rb b/app/models/decisions/funding_decision_form.rb
index 9422770d7..bc5c7ef3d 100644
--- a/app/models/decisions/funding_decision_form.rb
+++ b/app/models/decisions/funding_decision_form.rb
@@ -11,14 +11,14 @@ class FundingDecisionForm
attribute :result, :string
attribute :details, :string
- validates :result, inclusion: { in: :possible_results }
+ validates :result, inclusion: { in: :possible_results }
def possible_results
Types::FundingDecisionResult.values
end
def update_with_user!(attributes, user_id)
- assign_attributes(attributes)
+ assign_attributes(attributes)
validate!
return unless changed?
diff --git a/app/models/decisions/interests_of_justice_form.rb b/app/models/decisions/interests_of_justice_form.rb
index 6824514ca..5bddd89ec 100644
--- a/app/models/decisions/interests_of_justice_form.rb
+++ b/app/models/decisions/interests_of_justice_form.rb
@@ -22,7 +22,7 @@ def possible_results
end
def update_with_user!(attributes, user_id)
- assign_attributes(attributes)
+ assign_attributes(attributes)
validate!
return unless changed?
diff --git a/app/views/casework/decisions/funding_decisions/edit.html.erb b/app/views/casework/decisions/funding_decisions/edit.html.erb
index d63aaeab9..e2e0a67ae 100644
--- a/app/views/casework/decisions/funding_decisions/edit.html.erb
+++ b/app/views/casework/decisions/funding_decisions/edit.html.erb
@@ -1,4 +1,4 @@
-<% title 'TESING' %>
+<% title t '.title' %>
@@ -6,15 +6,18 @@
<%= @crime_application.reference %>
+
+ <%= @crime_application.applicant.full_name %>
+
+
+
+ <%= t '.title' %>
+
+
<%= form_with model: @form_object,
url: crime_application_decision_funding_decision_path(), method: :put do |f| %>
-
<%= f.govuk_error_summary %>
-
- <%= f.govuk_collection_radio_buttons :result,
- @form_object.possible_results,
- :to_s
- %>
+ <%= f.govuk_collection_radio_buttons :result, @form_object.possible_results, :to_s %>
<%= f.govuk_text_area :details %>
<%= f.govuk_submit %>
<% end %>
diff --git a/app/views/casework/decisions/index.html.erb b/app/views/casework/decisions/index.html.erb
index da29690d4..5db967c53 100644
--- a/app/views/casework/decisions/index.html.erb
+++ b/app/views/casework/decisions/index.html.erb
@@ -1,6 +1,21 @@
-<% title ':K:LKJ:LKJ:LKJ' %>
-<%= render(
- DecisionComponent.with_collection(
- @decisions
- )) %>
+<% title t '.title', count: @decisions.size %>
+
+
+
+ <%= @crime_application.reference %>
+
+
+
+ <%= @crime_application.applicant.full_name %>
+
+
+
+ <%= t '.title', count: @decisions.size %>
+
+
+
+
+<%= render(DecisionComponent.with_collection(@decisions)) %>
+
+<%= govuk_button_to(t(:add_funding_decision, scope: 'calls_to_action')) %>
diff --git a/app/views/casework/decisions/interests_of_justices/edit.html.erb b/app/views/casework/decisions/interests_of_justices/edit.html.erb
index 05e6ad3f6..73f0698c5 100644
--- a/app/views/casework/decisions/interests_of_justices/edit.html.erb
+++ b/app/views/casework/decisions/interests_of_justices/edit.html.erb
@@ -1,4 +1,4 @@
-<% title 'TESING' %>
+<% title t '.title' %>
@@ -6,6 +6,14 @@
<%= @crime_application.reference %>
+
+ <%= @crime_application.applicant.full_name %>
+
+
+
+ <%= t '.title' %>
+
+
<%= form_with model: @form_object,
url: crime_application_decision_interests_of_justice_path(), method: :put do |f| %>
diff --git a/app/views/casework/decisions/show.html.erb b/app/views/casework/decisions/show.html.erb
deleted file mode 100644
index a982539ca..000000000
--- a/app/views/casework/decisions/show.html.erb
+++ /dev/null
@@ -1,5 +0,0 @@
-<% title ':K:LKJ:LKJ:LKJ' %>
-
-
-<%= render @decision %>
-
diff --git a/config/locales/en/casework.yml b/config/locales/en/casework.yml
index 9540786ca..e65641067 100644
--- a/config/locales/en/casework.yml
+++ b/config/locales/en/casework.yml
@@ -425,6 +425,13 @@ en:
change_in_financial_circumstances: Change in financial circumstances
committal: Committal for sentence
deleted_user_name: '[deleted]'
+ decision_result:
+ pass: Passed
+ fail: Failed
+ granted_on_ioj: Granted
+ fail_on_ioj: Rejected
+
+
either_way: Either way
esa: Income-related Employment and Support Allowance (ESA)
guarantee_pension: Guarantee Credit element of Pension Credit
@@ -656,7 +663,6 @@ en:
casework:
-
assigned_applications:
index:
page_title: Your list
@@ -736,3 +742,15 @@ en:
<<: *LABELS
values:
<<: *VALUES
+ decisions:
+ index:
+ title:
+ zero: Add a funding decision
+ one: Check the funding decision
+ other: You have added %{count} case
+ interests_of_justices:
+ edit:
+ title: Interests of justice test
+ funding_decisions:
+ edit:
+ title: Overall result
diff --git a/config/routes.rb b/config/routes.rb
index 9a7f47959..634437d84 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -38,11 +38,13 @@
resource :reassign, only: [:new, :create]
resource :return, only: [:new, :create]
post 'add_a_funding_decision', to: 'decisions#create'
+ post 'add_a_funding_decision', to: 'decisions#create'
resources :decisions do
+ get :confirm_destroy, on: :member
scope module: :decisions do
- resource :interests_of_justice
- resource :funding_decision
+ resource :interests_of_justice, only: [:edit, :update]
+ resource :funding_decision, only: [:edit, :update]
end
end
end