Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

CRIMAPP-1357 caseworker can add MAAT decisions #726

Draft
wants to merge 16 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .env.test
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ MAAT_API_OAUTH_URL='https://oauth.example.com'
MAAT_API_CLIENT_ID='TestMaatApiClientID'
MAAT_API_CLIENT_SECRET='TestMaatApiClientSecret'
MAAT_API_API_URL='https://example.com'
MAAT_API_STARTING_MAAT_ID=3
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This constant is set on a per environment basis and is used to prevent unsupported applications being retrieved.



DEV_AUTH_ENABLED=true
Expand Down
4 changes: 3 additions & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ gem 'laa-criminal-applications-datastore-api-client',

gem 'laa-criminal-legal-aid-schemas',
github: 'ministryofjustice/laa-criminal-legal-aid-schemas',
tag: 'v1.3.5'
ref: 'a13795e8b302e7fdd3bbec1e5e09ddb7ffa9c0e8'
# branch: 'CRIMAPP-1357-maat-decisions'
# tag: 'v1.3.5'

# The original asset pipeline for Rails [https://github.com/rails/sprockets-rails]
gem 'sprockets-rails'
Expand Down
4 changes: 2 additions & 2 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ GIT

GIT
remote: https://github.com/ministryofjustice/laa-criminal-legal-aid-schemas.git
revision: 0dd33b6c788ac531ed825d3436334b4bf96393f2
tag: v1.3.5
revision: a13795e8b302e7fdd3bbec1e5e09ddb7ffa9c0e8
ref: a13795e8b302e7fdd3bbec1e5e09ddb7ffa9c0e8
specs:
laa-criminal-legal-aid-schemas (1.3.5)
dry-schema (~> 1.13)
Expand Down
25 changes: 21 additions & 4 deletions app/aggregates/deciding.rb
Original file line number Diff line number Diff line change
@@ -1,11 +1,28 @@
module Deciding
class DecisionNotFound < StandardError; end
class AlreadyCreated < StandardError; end
class ApplicationNotAssignedToUser < StandardError; end
class DecisionNotFound < StandardError; end
class MaatRecordNotChanged < StandardError; end

class Event < RailsEventStore::Event
class << self
def build(decision, data = {})
args = {
application_id: decision.application_id,
decision_id: decision.decision_id
}

new(data: args.merge(data))
end
end
end

class DraftCreated < RailsEventStore::Event; end
class InterestsOfJusticeSet < RailsEventStore::Event; end
class FundingDecisionSet < RailsEventStore::Event; end
class CommentSet < RailsEventStore::Event; end
class DraftCreatedFromMaat < RailsEventStore::Event; end
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All of these should use Event, just don't call with build the creating events.

class InterestsOfJusticeSet < Event; end
class FundingDecisionSet < Event; end
class SynchedWithMaat < Event; end
class CommentSet < Event; end

class << self
def stream_name(decision_id)
Expand Down
2 changes: 1 addition & 1 deletion app/aggregates/deciding/command.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module Deciding
class Command < Dry::Struct
attribute :decision_id, Types::Uuid
attribute :decision_id, Types::Uuid | Types::Integer
Copy link
Member Author

@timpeat timpeat Oct 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We use the MAAT ID for the decision_id of MAAT decisions. This is used to create a unique event stream for the decision and ensure idempotency. (NB: we may start receiving notifications from MAAT relating to decisions.)


def with_decision(&block)
repository.with_aggregate(
Expand Down
3 changes: 2 additions & 1 deletion app/aggregates/deciding/commands/create_draft.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ module Deciding
class CreateDraft < Command
attribute :application_id, Types::Uuid
attribute :user_id, Types::Uuid
attribute :reference, Types::Integer

def call
with_decision do |decision|
decision.create_draft(user_id:, application_id:)
decision.create_draft(user_id:, application_id:, reference:)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Including reference in all deciding events simplifies linking to streams based on reference for submission history.

end
end
end
Expand Down
15 changes: 15 additions & 0 deletions app/aggregates/deciding/commands/create_draft_from_maat.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
module Deciding
class CreateDraftFromMaat < Command
attribute :application_id, Types::Uuid
attribute :maat_decision, Maat::Decision
attribute :user_id, Types::Uuid

def call
with_decision do |decision|
decision.create_draft_from_maat(
application_id:, maat_decision:, user_id:
)
end
end
end
end
12 changes: 12 additions & 0 deletions app/aggregates/deciding/commands/update_from_maat_decision.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
module Deciding
class UpdateFromMaatDecision < Command
attribute :maat_decision, Maat::Decision
attribute :user_id, Types::Uuid

def call
with_decision do |decision|
decision.sync_with_maat(maat_decision:, user_id:)
end
end
end
end
74 changes: 61 additions & 13 deletions app/aggregates/deciding/decision.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,37 +6,67 @@ def initialize(decision_id)
@decision_id = decision_id
end

attr_reader :application_id, :decision_id, :funding_decision, :comment, :state
attr_reader :application_id, :decision_id, :funding_decision, :comment,
:state, :reference, :maat_id, :checksum, :case_id

# For decisions entered on CrimeReview by the caseworker
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TYPO

def create_draft(user_id:, application_id:, reference:)
raise AlreadyCreated unless @state.nil?

def create_draft(user_id:, application_id:)
apply DraftCreated.new(
data: { decision_id:, application_id:, user_id: }
data: { decision_id:, application_id:, user_id:, reference: }
)
end

def set_interests_of_justice(user_id:, interests_of_justice:)
apply InterestsOfJusticeSet.new(
data: { decision_id:, application_id:, user_id:, interests_of_justice: }
def create_draft_from_maat(application_id:, maat_decision:, user_id:)
maat_decision = maat_decision.to_h
raise AlreadyCreated unless @state.nil?

apply DraftCreatedFromMaat.new(
data: { decision_id:, application_id:, maat_decision:, user_id: }
)
end

def sync_with_maat(maat_decision:, user_id:)
raise MaatRecordNotChanged unless maat_decision&.checksum != checksum

apply SynchedWithMaat.build(self, maat_decision:, user_id:)
end

def set_interests_of_justice(user_id:, interests_of_justice:)
apply InterestsOfJusticeSet.build(self, user_id:, interests_of_justice:)
end

def set_funding_decision(user_id:, funding_decision:)
apply FundingDecisionSet.new(
data: { decision_id:, application_id:, user_id:, funding_decision: }
)
apply FundingDecisionSet.build(self, user_id:, funding_decision:)
end

def set_comment(user_id:, comment:)
apply CommentSet.new(
data: { decision_id:, application_id:, user_id:, comment: }
)
apply CommentSet.build(self, user_id:, comment:)
end

# When decision is drafted on Review by the caseworker (e.g. Non-means tested)
on DraftCreated do |event|
@application_id = event.data.fetch(:application_id)
@reference = event.data.fetch(:reference, nil)
@state = Types::DecisionState[:draft]
end

# When the decision is linked to a decision drafted on MAAT
on DraftCreatedFromMaat do |event|
@application_id = event.data.fetch(:application_id)

update_from_maat(event.data.fetch(:maat_decision))

@state = Types::DecisionState[:draft]
end

on SynchedWithMaat do |event|
return if event.data[:maat_decision].blank?

update_from_maat(event.data.fetch(:maat_decision))
end

on InterestsOfJusticeSet do |event|
@interests_of_justice = event.data.fetch(:interests_of_justice)
end
Expand All @@ -49,8 +79,26 @@ def set_comment(user_id:, comment:)
@comment = event.data.fetch(:comment)
end

def update_from_maat(maat_attributes)
decision = Maat::Decision.new(maat_attributes)

@maat_id = decision.maat_id
@reference = decision.reference
@case_id = decision.case_id
@interests_of_justice = decision.interests_of_justice
@means = decision.means
@funding_decision = decision.funding_decision
@checksum = decision.checksum
end

def means
return if @means.nil?

Types::MeansDecision[@means]
end

def interests_of_justice
return {} if @interests_of_justice.nil?
return if @interests_of_justice.nil?
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review this


Types::InterestsOfJusticeDecision[@interests_of_justice]
end
Expand Down
4 changes: 3 additions & 1 deletion app/aggregates/reviewing.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,16 @@ class AlreadyCompleted < Error; end
class AlreadyMarkedAsReady < Error; end
class AlreadyReceived < Error; end
class AlreadySentBack < Error; end
class DecisionAlreadyLinked < Error; end
class CannotCompleteWhenSentBack < Error; end
class CannotMarkAsReadyWhenCompleted < Error; end
class CannotMarkAsReadyWhenSentBack < Error; end
class CannotSendBackWhenCompleted < Error; end
class NotReceived < Error; end
class IncompleteDecisions < Error; end
class NotReceived < Error; end

class DecisionAdded < Event; end
class MaatDecisionAdded < Event; end

class << self
def stream_name(application_id)
Expand Down
11 changes: 11 additions & 0 deletions app/aggregates/reviewing/commands/add_maat_decision.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module Reviewing
class AddMaatDecision < Command
attribute :decision_id, Types::Uuid | Types::Integer

def call
with_review do |review|
review.add_maat_decision(decision_id:)
end
end
end
end
13 changes: 12 additions & 1 deletion app/aggregates/reviewing/review.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ class Review
def initialize(id)
@id = id
@decision_ids = []
@maat_ids = []
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove maat_ids for now

end

attr_reader :id, :decision_ids, :state, :return_reason, :reviewed_at, :reviewer_id, :submitted_at, :superseded_by,
Expand Down Expand Up @@ -52,10 +53,16 @@ def mark_as_ready(user_id:)
apply MarkedAsReady.build(self, user_id:)
end

def add_decision(user_id:, decision_id:)
def add_decision(decision_id:, user_id: nil)
apply DecisionAdded.build(self, user_id:, decision_id:)
end

def add_maat_decision(decision_id:)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are using this?

raise DecisionAlreadyLinked if @decision_ids.include?(decision_id)

apply MaatDecisionAdded.build(self, decision_id:)
end

on ApplicationReceived do |event|
@state = Types::ReviewState[:open]
@received_at = event.timestamp
Expand All @@ -70,6 +77,10 @@ def add_decision(user_id:, decision_id:)
@decision_ids << event.data.fetch(:decision_id)
end

on MaatDecisionAdded 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)
Expand Down
12 changes: 12 additions & 0 deletions app/components/_decision_result_component.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<%= govuk_summary_list(card: { title:, actions: }, rows: rows) do |list|
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this used?

list.with_row do |row|
row.with_key { label_text(:funding_decision, scope: [:decision]) }
row.with_value { decision_result(decision.funding_decision) }
end

list.with_row do |row|
row.with_key { label_text(:comment, scope: [:decision]) }
row.with_value { decision.comment }
end
end %>

58 changes: 58 additions & 0 deletions app/components/decision_component.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<%= govuk_summary_list(card: { title:, actions: }) do |list|
if linked_to_maat?
list.with_row do |row|
row.with_key { label_text(:maat_id) }
row.with_value { decision.maat_id.to_s }
end

list.with_row do |row|
row.with_key { label_text(:case_number) }
row.with_value { decision.case_id }
end
end

if interests_of_justice.present?
list.with_row do |row|
row.with_key { label_text(:ioj_result) }
row.with_value { ioj_result }
end
list.with_row do |row|
row.with_key { label_text(:ioj_details) }
row.with_value { simple_format(interests_of_justice.details) }
end
list.with_row do |row|
row.with_key { label_text(:ioj_assessed_by) }
row.with_value { interests_of_justice.assessed_by }
end
list.with_row do |row|
row.with_key { label_text(:ioj_assessed_on) }
row.with_value { date(interests_of_justice.assessed_on) }
end
end

if means.present?
list.with_row do |row|
row.with_key { label_text(:means_result) }
row.with_value { ioj_result }
end
list.with_row do |row|
row.with_key { label_text(:means_assessed_by) }
row.with_value { means.assessed_by }
end
list.with_row do |row|
row.with_key { label_text(:means_assessed_on) }
row.with_value { date(means.assessed_on) }
end
end

list.with_row do |row|
row.with_key { label_text(:overall_result) }
row.with_value { decision_result(decision.funding_decision) }
end

list.with_row do |row|
row.with_key { label_text(:decision_comment) }
row.with_value { decision.comment }
end
end %>

Loading
Loading