diff --git a/app/controllers/case_workers/claims_controller.rb b/app/controllers/case_workers/claims_controller.rb index 484ad4b673..6061416712 100644 --- a/app/controllers/case_workers/claims_controller.rb +++ b/app/controllers/case_workers/claims_controller.rb @@ -10,7 +10,8 @@ class ClaimsController < CaseWorkers::ApplicationController respond_to :html # callback order is important (must set claims before filtering and sorting) - before_action :set_claims, only: %i[index archived] + before_action :set_claims, only: %i[index archived] + before_action :set_presenters before_action :filter_current_claims, only: [:index] before_action :filter_archived_claims, only: [:archived] before_action :sort_claims, only: %i[index archived] @@ -84,6 +85,10 @@ def set_claims @claims = Claims::CaseWorkerClaims.new(current_user:, action: tab, criteria: criteria_params).claims end + def set_presenters + @defendant_presenter = CaseWorkers::DefendantPresenter + end + # Only these 2 actions are handle in this controller. Rest of actions in the admin-namespaced controller. def tab %w[current archived].include?(params[:tab]) ? params[:tab] : 'current' diff --git a/app/controllers/external_users/claims_controller.rb b/app/controllers/external_users/claims_controller.rb index 1235bdb993..e9cb879e0d 100644 --- a/app/controllers/external_users/claims_controller.rb +++ b/app/controllers/external_users/claims_controller.rb @@ -14,6 +14,7 @@ class ResourceClassNotDefined < StandardError; end prepend_before_action :clean_multiparameter_dates, only: %i[create update] before_action :set_user_and_provider + before_action :set_presenters before_action :set_claims_context, only: %i[index archived outstanding authorised] before_action :set_financial_summary, only: %i[index outstanding authorised] @@ -212,6 +213,10 @@ def set_user_and_provider @provider = @external_user.provider end + def set_presenters + @defendant_presenter = ExternalUsers::DefendantPresenter + end + def set_claims_context context = Claims::ContextMapper.new(@external_user, scheme:) @claims_context = context.available_claims diff --git a/app/presenters/case_workers/defendant_presenter.rb b/app/presenters/case_workers/defendant_presenter.rb new file mode 100644 index 0000000000..94bbf5a47e --- /dev/null +++ b/app/presenters/case_workers/defendant_presenter.rb @@ -0,0 +1,9 @@ +module CaseWorkers + class DefendantPresenter < BasePresenter + presents :defendant + + def representation_orders + defendant.representation_orders.map { |rep_order| RepresentationOrder.new(rep_order, @view) } + end + end +end diff --git a/app/presenters/case_workers/representation_order.rb b/app/presenters/case_workers/representation_order.rb new file mode 100644 index 0000000000..98a1d769e5 --- /dev/null +++ b/app/presenters/case_workers/representation_order.rb @@ -0,0 +1,6 @@ +module CaseWorkers + class RepresentationOrder < BasePresenter + presents :representation_order + def maat_details = @maat_details ||= MaatService.call(maat_reference:) + end +end diff --git a/app/presenters/external_users/defendant_presenter.rb b/app/presenters/external_users/defendant_presenter.rb new file mode 100644 index 0000000000..0a2b561f40 --- /dev/null +++ b/app/presenters/external_users/defendant_presenter.rb @@ -0,0 +1,9 @@ +module ExternalUsers + class DefendantPresenter < BasePresenter + presents :defendant + + def representation_orders + defendant.representation_orders.map { |rep_order| RepresentationOrder.new(rep_order, @view) } + end + end +end diff --git a/app/presenters/external_users/representation_order.rb b/app/presenters/external_users/representation_order.rb new file mode 100644 index 0000000000..b34c19d19f --- /dev/null +++ b/app/presenters/external_users/representation_order.rb @@ -0,0 +1,9 @@ +module ExternalUsers + class RepresentationOrder < BasePresenter + presents :representation_order + + def maat_details + { case_number: '???' } + end + end +end diff --git a/app/services/maat_service.rb b/app/services/maat_service.rb new file mode 100644 index 0000000000..8ac57929a5 --- /dev/null +++ b/app/services/maat_service.rb @@ -0,0 +1,17 @@ +class MaatService + def self.call(...) = new(...).call + + def initialize(**kwargs) + @connection = MaatService::Connection.instance + @maat_reference = kwargs[:maat_reference] + end + + def call + data = @connection.fetch(@maat_reference) + + { + case_number: data['caseId'], + representation_order_date: data['crownRepOrderDate'] + } + end +end diff --git a/app/services/maat_service/connection.rb b/app/services/maat_service/connection.rb new file mode 100644 index 0000000000..be84ccd3b3 --- /dev/null +++ b/app/services/maat_service/connection.rb @@ -0,0 +1,37 @@ +class MaatService + class Connection + include Singleton + + def fetch(maat_reference) + JSON.parse(client.get("assessment/rep-orders/#{maat_reference}").body) + rescue Faraday::ConnectionFailed + {} + end + + private + + def client + @client ||= Faraday.new(Settings.maat_api_url, request: { timeout: 2 }) do |conn| + conn.headers['Authorization'] = "Bearer #{oauth_token}" + end + end + + def oauth_token + response = Faraday.post(Settings.maat_api_oauth_url, request_params, request_headers) + JSON.parse(response.body)['access_token'] + end + + def request_params + { + client_id: Settings.maat_api_oauth_client_id, + client_secret: Settings.maat_api_oauth_client_secret, + scope: Settings.maat_api_oauth_scope, + grant_type: 'client_credentials' + } + end + + def request_headers + { content_type: 'application/x-www-form-urlencoded' } + end + end +end diff --git a/app/views/shared/_claim_defendants.html.haml b/app/views/shared/_claim_defendants.html.haml index 820c36556a..7d89a46759 100644 --- a/app/views/shared/_claim_defendants.html.haml +++ b/app/views/shared/_claim_defendants.html.haml @@ -1,3 +1,3 @@ - defendants.each_with_index do | defendant, index | .govuk-grid-column-one-half - = render partial: 'shared/claim_defendant_details', locals: { defendant: defendant, index: index += 1 } + = render partial: 'shared/claim_defendant_details', locals: { defendant: present(defendant, CaseWorkers::DefendantPresenter), index: index += 1 } diff --git a/app/views/shared/_representation_order_details.html.haml b/app/views/shared/_representation_order_details.html.haml new file mode 100644 index 0000000000..fabb26eb16 --- /dev/null +++ b/app/views/shared/_representation_order_details.html.haml @@ -0,0 +1,11 @@ += govuk_table do |table| + - table.with_caption(size: 's', text: 'Details from MAAT (beta)') + + - table.with_body do |body| + - body.with_row do |row| + - row.with_cell(header: true, text: 'Case number') + - row.with_cell(text: representation_order.maat_details[:case_number]) + + - body.with_row do |row| + - row.with_cell(header: true, text: 'Date') + - row.with_cell(text: representation_order.maat_details[:representation_order_date]) diff --git a/config/settings.yml b/config/settings.yml index 9e619fefc1..1d70990202 100644 --- a/config/settings.yml +++ b/config/settings.yml @@ -230,3 +230,9 @@ notify_report_errors: <%= ENV["ENV"].in?(%w[api-sandbox production]) %> postcode_regexp: !ruby/regexp '/\A([Gg][Ii][Rr] 0[Aa]{2})|((([A-Za-z][0-9]{1,2})|(([A-Za-z][A-Ha-hJ-Yj-y][0-9]{1,2})|(([A-Za-z][0-9][A-Za-z])|([A-Za-z][A-Ha-hJ-Yj-y][0-9]?[A-Za-z])))) [0-9][A-Za-z]{2})\z/' maat_regexp: !ruby/regexp <%= ENV['MAAT_REGEXP'] || '/^[2-9][0-9]{6}$/' %> + +maat_api_url: <%= ENV['MAAT_API_URL'] %> +maat_api_oauth_client_id: <%= ENV['OAUTH_CLIENT_ID'] %> +maat_api_oauth_client_secret: <%= ENV['OAUTH_CLIENT_SECRET'] %> +maat_api_oauth_scope: <%=ENV['OAUTH_SCOPE'] %> +maat_api_oauth_url: <%=ENV['OAUTH_URL']%> diff --git a/spec/presenters/case_workers/defendant_presenter_spec.rb b/spec/presenters/case_workers/defendant_presenter_spec.rb new file mode 100644 index 0000000000..60bf1d343d --- /dev/null +++ b/spec/presenters/case_workers/defendant_presenter_spec.rb @@ -0,0 +1,20 @@ +RSpec.describe CaseWorkers::DefendantPresenter do + subject(:defendant_presenter) { described_class.new(defendant, view) } + + describe '#representation_orders' do + subject(:representation_orders) { defendant_presenter.representation_orders } + + context 'when there are representation orders' do + let(:defendant) { build(:defendant, representation_orders: build_list(:representation_order, 3)) } + + it { expect(representation_orders.length).to eq 3 } + it { is_expected.to all(be_a(CaseWorkers::RepresentationOrder)) } + end + + context 'when there are no representation orders' do + let(:defendant) { build(:defendant, representation_orders: []) } + + it { is_expected.to be_empty } + end + end +end diff --git a/spec/presenters/external_users/defendant_presenter_spec.rb b/spec/presenters/external_users/defendant_presenter_spec.rb new file mode 100644 index 0000000000..67f43669d6 --- /dev/null +++ b/spec/presenters/external_users/defendant_presenter_spec.rb @@ -0,0 +1,20 @@ +RSpec.describe ExternalUsers::DefendantPresenter do + subject(:defendant_presenter) { described_class.new(defendant, view) } + + describe '#representation_orders' do + subject(:representation_orders) { defendant_presenter.representation_orders } + + context 'when there are representation orders' do + let(:defendant) { build(:defendant, representation_orders: build_list(:representation_order, 3)) } + + it { expect(representation_orders.length).to eq 3 } + it { is_expected.to all(be_a(ExternalUsers::RepresentationOrder)) } + end + + context 'when there are no representation orders' do + let(:defendant) { build(:defendant, representation_orders: []) } + + it { is_expected.to be_empty } + end + end +end diff --git a/spec/services/maat_service_spec.rb b/spec/services/maat_service_spec.rb new file mode 100644 index 0000000000..6b89974ffa --- /dev/null +++ b/spec/services/maat_service_spec.rb @@ -0,0 +1,61 @@ +RSpec.describe MaatService do + before do + allow(Settings).to receive_messages(maat_api_url: 'https://example.com', maat_api_oauth_url: 'https://example.com/oauth') + stub_request(:post, 'https://example.com/oauth') + .to_return(body: { access_token: 'test_token' }.to_json) + end + + describe '.call' do + subject { described_class.call(maat_reference:) } + + let(:maat_reference) { '9876543' } + let(:connection) { MaatService::Connection.instance } + + context 'with a valid MAAT reference' do + before do + stub_request(:get, "https://example.com/assessment/rep-orders/#{maat_reference}") + .to_return(body: { caseId: 'TEST12345678', crownRepOrderDate: '2024-03-28' }.to_json) + end + + it { is_expected.to eq({ case_number: 'TEST12345678', representation_order_date: '2024-03-28' }) } + end + + context 'with a valid MAAT reference with no date' do + before do + stub_request(:get, "https://example.com/assessment/rep-orders/#{maat_reference}") + .to_return(body: { caseId: 'TEST12345678' }.to_json) + end + + it { is_expected.to eq({ case_number: 'TEST12345678', representation_order_date: nil }) } + end + + context 'with an unknown MAAT reference' do + before do + stub_request(:get, "https://example.com/assessment/rep-orders/#{maat_reference}") + .to_return(status: 404, body: { message: "No Rep Order found for ID: #{maat_reference}" }.to_json) + end + + it { is_expected.to eq({ case_number: nil, representation_order_date: nil }) } + end + + context 'when unauthorized' do + before do + stub_request(:get, "https://example.com/assessment/rep-orders/#{maat_reference}") + .to_return(status: 401, body: { message: 'Unauthorized' }.to_json) + end + + it { is_expected.to eq({ case_number: nil, representation_order_date: nil }) } + end + + context 'when the OAuth settings are not correct' do + before do + stub_request(:post, 'https://example.com/oauth') + .to_return(status: 400, body: { error: 'invalid_client' }.to_json) + stub_request(:get, "https://example.com/assessment/rep-orders/#{maat_reference}") + .to_return(status: 401, body: { message: 'Unauthorized' }.to_json) + end + + it { is_expected.to eq({ case_number: nil, representation_order_date: nil }) } + end + end +end