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

CRM457-2216: Everything needed to load all lists from the app store #315

Merged
merged 1 commit into from
Nov 8, 2024
Merged
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
33 changes: 33 additions & 0 deletions app/controllers/V1/assignments_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
module V1
class AssignmentsController < ApplicationController
def create
current_submission.with_lock do
current_submission.assigned_user_id = params[:caseworker_id]
current_submission.save!
end
head :created
end

def destroy
current_submission.with_lock do
# `unassigned_user_ids allows us to log which caseworkers have ever been
# assigned to a claim, both for search filtering and to allow us to run
# automatic assignment logic
current_submission.unassigned_user_ids << current_submission.assigned_user_id
current_submission.assigned_user_id = nil
current_submission.save!
end
head :no_content
end

private

def current_submission
@current_submission ||= Submission.find(params[:submission_id])
end

def authorization_object
current_submission
end
end
end
4 changes: 4 additions & 0 deletions app/controllers/V1/submissions/searches_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,11 @@ def search_params
:updated_from,
:updated_to,
:caseworker_id,
:account_number,
:current_caseworker_id,
:status_with_assignment,
:id_to_exclude,
status_with_assignment: [],
)
end
end
Expand Down
2 changes: 1 addition & 1 deletion app/models/submission.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def latest_version
end

def as_json(*)
super(only: %i[application_risk application_type updated_at created_at last_updated_at]).merge(
super(only: %i[application_risk application_type updated_at created_at last_updated_at assigned_user_id]).merge(
application_state: state,
version: current_version,
json_schema_version: latest_version.json_schema_version,
Expand Down
4 changes: 4 additions & 0 deletions app/services/authorization/rules.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ module Rules
events: {
create: ->(object, _params) { object.state.in?(%w[submitted sent_back provider_updated]) },
},
assignments: {
create: true,
destroy: true,
},
searches: {
create: true,
},
Expand Down
17 changes: 16 additions & 1 deletion app/services/submissions/search_service.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module Submissions
class SearchService
SORTABLE_COLUMNS = %w[laa_reference firm_name client_name last_updated status_with_assignment].freeze
SORTABLE_COLUMNS = %w[laa_reference firm_name client_name last_updated status_with_assignment risk_level service_name].freeze

attr_reader :search_params

Expand All @@ -26,6 +26,9 @@ def search_query
relation = relation.where(application_type:) if application_type
relation = relation.where(status_with_assignment:) if status_with_assignment
relation = relation.where("has_been_assigned_to ? :caseworker_id", caseworker_id:) if caseworker_id
relation = relation.where(assigned_user_id:) if assigned_user_id
relation = relation.where(account_number:) if account_number
relation = relation.where.not(id: id_to_exclude) if id_to_exclude
relation = relation.order(sort_clause)

relation.where_terms(query)
Expand Down Expand Up @@ -83,6 +86,18 @@ def caseworker_id
search_params[:caseworker_id]
end

def assigned_user_id
search_params[:current_caseworker_id]
end

def account_number
search_params[:account_number]
end

def id_to_exclude
search_params[:id_to_exclude]
end

def query
search_params[:query]
end
Expand Down
1 change: 1 addition & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
namespace "v1" do
resources :submissions, only: %i[show create index update] do
resources :events, only: %i[create]
resource :assignment, only: %i[create destroy]
member { patch :metadata }
end
resources :subscribers, only: %i[create]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
class AddAssignmentFieldsToApplication < ActiveRecord::Migration[7.2]
def up
add_column :application, :assigned_user_id, :string
add_column :application, :unassigned_user_ids, :string, array: true, default: []

Submission.find_each do |submission|
ass_and_unass_events = submission.events.select { _1['event_type'].in?(%w[assignment unassignment send_back]) }
.sort_by { DateTime.parse(_1['created_at']) }
last_event = ass_and_unass_events.last

if last_event['event_type'] == 'assignment'
assigned_user_id = last_event['primary_user_id']
end

unassigned_user_ids = ass_and_unass_events.map { _1['primary_user_id'] }.compact.uniq - [assigned_user_id]

submission.update!(assigned_user_id:, unassigned_user_ids:)
end
end

def down
remove_column :application, :assigned_user_id, :string
remove_column :application, :unassigned_user_ids, :string, array: true, default: []
end
end
5 changes: 5 additions & 0 deletions db/migrate/20241105094407_update_searches_to_version_6.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class UpdateSearchesToVersion6 < ActiveRecord::Migration[7.2]
def change
update_view :searches, version: 6, revert_to_version: 5
end
end
61 changes: 29 additions & 32 deletions db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
t.virtual "has_been_assigned_to", type: :jsonb, as: "jsonb_path_query_array(events, '$[*]?(@.\"event_type\" == \"assignment\").\"primary_user_id\"'::jsonpath)", stored: true
t.datetime "last_updated_at", precision: nil
t.boolean "notify_subscriber_completed"
t.string "assigned_user_id"
t.string "unassigned_user_ids", default: [], array: true
t.check_constraint "created_at IS NOT NULL", name: "application_created_at_null"
t.check_constraint "updated_at IS NOT NULL", name: "application_updated_at_null"
end
Expand Down Expand Up @@ -165,20 +167,23 @@
GREATEST(EXTRACT(epoch FROM (base.to_time - base.from_time)), (0)::numeric) AS processing_seconds
FROM base;
SQL
create_view "submissions_by_date", sql_definition: <<-SQL
SELECT counted_values.event_on,
counted_values.application_type,
counted_values.submission,
counted_values.resubmission,
(counted_values.submission + counted_values.resubmission) AS total
FROM ( SELECT all_events.event_on,
all_events.application_type,
count(*) FILTER (WHERE ((all_events.event_type = 'new_version'::text) AND (all_events.submission_version = 1))) AS submission,
count(*) FILTER (WHERE (((all_events.event_type = 'new_version'::text) AND (all_events.submission_version > 1) AND (all_events.application_type = 'crm7'::text)) OR ((all_events.event_type = 'provider_updated'::text) AND (all_events.application_type = 'crm4'::text)))) AS resubmission
FROM all_events
WHERE (all_events.event_type = ANY (ARRAY['new_version'::text, 'provider_updated'::text]))
GROUP BY all_events.application_type, all_events.event_on
ORDER BY all_events.application_type, all_events.event_on) counted_values;
SQL
create_view "searches", sql_definition: <<-SQL
WITH event_types AS (
SELECT application.id,
jsonb_path_query_array(application.events, '$[*]?(@."event_type" == "assignment" || @."event_type" == "unassignment")."event_type"'::jsonpath) AS assigment_arr
FROM application
), assignments AS (
SELECT app_1.id,
CASE
WHEN ((et.assigment_arr ->> '-1'::integer) = 'assignment'::text) THEN true
ELSE false
END AS assigned
FROM (application app_1
JOIN event_types et ON ((et.id = app_1.id)))
), defendants AS (
WITH defendants AS (
SELECT app_1.id,
CASE
WHEN (app_1.application_type = 'crm4'::text) THEN ((((app_ver_1.application -> 'defendant'::text) ->> 'first_name'::text) || ' '::text) || ((app_ver_1.application -> 'defendant'::text) ->> 'last_name'::text))
Expand All @@ -193,38 +198,30 @@
app_ver.id AS application_version_id,
(app_ver.application ->> 'laa_reference'::text) AS laa_reference,
((app_ver.application -> 'firm_office'::text) ->> 'name'::text) AS firm_name,
((app_ver.application -> 'firm_office'::text) ->> 'account_number'::text) AS account_number,
(app_ver.application ->> 'service_name'::text) AS service_name,
CASE app.application_risk
WHEN 'high'::text THEN 3
WHEN 'medium'::text THEN 2
ELSE 1
END AS risk_level,
def.client_name,
app_ver.search_fields,
app.has_been_assigned_to,
app.assigned_user_id,
app.created_at AS date_submitted,
app.last_updated_at AS last_updated,
CASE
WHEN ((app.state = 'submitted'::text) AND ass.assigned) THEN 'in_progress'::text
WHEN ((app.state = 'submitted'::text) AND (NOT ass.assigned)) THEN 'not_assigned'::text
WHEN ((app.state = 'submitted'::text) AND (app.assigned_user_id IS NOT NULL)) THEN 'in_progress'::text
WHEN ((app.state = 'submitted'::text) AND (app.assigned_user_id IS NULL)) THEN 'not_assigned'::text
ELSE app.state
END AS status_with_assignment,
app.application_type,
app.application_risk AS risk
FROM (((application app
FROM ((application app
JOIN application_version app_ver ON (((app.id = app_ver.application_id) AND (app.current_version = app_ver.version))))
JOIN assignments ass ON ((ass.id = app.id)))
JOIN defendants def ON ((def.id = app.id)));
SQL
create_view "submissions_by_date", sql_definition: <<-SQL
SELECT counted_values.event_on,
counted_values.application_type,
counted_values.submission,
counted_values.resubmission,
(counted_values.submission + counted_values.resubmission) AS total
FROM ( SELECT all_events.event_on,
all_events.application_type,
count(*) FILTER (WHERE ((all_events.event_type = 'new_version'::text) AND (all_events.submission_version = 1))) AS submission,
count(*) FILTER (WHERE (((all_events.event_type = 'new_version'::text) AND (all_events.submission_version > 1) AND (all_events.application_type = 'crm7'::text)) OR ((all_events.event_type = 'provider_updated'::text) AND (all_events.application_type = 'crm4'::text)))) AS resubmission
FROM all_events
WHERE (all_events.event_type = ANY (ARRAY['new_version'::text, 'provider_updated'::text]))
GROUP BY all_events.application_type, all_events.event_on
ORDER BY all_events.application_type, all_events.event_on) counted_values;
SQL
create_view "submission_by_services", sql_definition: <<-SQL
SELECT COALESCE((app_ver.application ->> 'service_type'::text), 'not_found'::text) AS service_type,
date_trunc('DAY'::text, app.created_at) AS date_submitted,
Expand Down
44 changes: 44 additions & 0 deletions db/views/searches_v06.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
WITH defendants AS (
SELECT
app.id,
CASE WHEN app.application_type = 'crm4' THEN
(app_ver.application -> 'defendant' ->> 'first_name') || ' ' || (app_ver.application -> 'defendant' ->> 'last_name')
ELSE
(
SELECT (defendants.value->>'first_name') || ' ' || (defendants.value->>'last_name')
FROM jsonb_array_elements(app_ver.application->'defendants') AS defendants
WHERE defendants.value->>'main' = 'true'
)
END AS client_name
FROM application AS app
JOIN application_version AS app_ver
ON app.id = app_ver.application_id AND app.current_version = app_ver.version
)
SELECT
app.id,
app_ver.id as application_version_id,
app_ver.application ->> 'laa_reference' as laa_reference,
app_ver.application -> 'firm_office' ->> 'name' as firm_name,
app_ver.application -> 'firm_office' ->> 'account_number' as account_number,
app_ver.application ->> 'service_name' as service_name,
CASE app.application_risk
WHEN 'high' THEN 3
WHEN 'medium' THEN 2
ELSE 1 END as risk_level,
def.client_name,
app_ver.search_fields,
app.has_been_assigned_to,
app.assigned_user_id,
app.created_at as date_submitted,
app.last_updated_at as last_updated, -- latest event's created_at date in most instances
CASE WHEN app.state = 'submitted' AND app.assigned_user_id IS NOT NULL THEN 'in_progress'
WHEN app.state = 'submitted' AND app.assigned_user_id IS NULL THEN 'not_assigned'
ELSE app.state
END AS status_with_assignment,
app.application_type as application_type,
app.application_risk as risk
FROM application AS app
JOIN application_version AS app_ver
ON app.id = app_ver.application_id AND app.current_version = app_ver.version
JOIN defendants AS def
ON def.id = app.id
35 changes: 35 additions & 0 deletions spec/requests/assignments_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
require "rails_helper"

RSpec.describe "Assignments" do
let(:submission) { create(:submission) }
let(:caseworker_id) { SecureRandom.uuid }

before { allow(Tokens::VerificationService).to receive(:call).and_return(valid: true, role: :caseworker) }

describe "#create" do
it "records the assignment" do
post "/v1/submissions/#{submission.id}/assignment", params: { caseworker_id: }
expect(response).to have_http_status :created

expect(submission.reload.assigned_user_id).to eq caseworker_id
end
end

describe "#destroy" do
before { submission.update(assigned_user_id: caseworker_id, unassigned_user_ids: %w[foo]) }

it "removes the assignment" do
delete "/v1/submissions/#{submission.id}/assignment"
expect(response).to have_http_status :no_content

expect(submission.reload.assigned_user_id).to be_nil
end

it "adds to the previous assignee list" do
delete "/v1/submissions/#{submission.id}/assignment"
expect(response).to have_http_status :no_content

expect(submission.reload.unassigned_user_ids).to eq ["foo", caseworker_id]
end
end
end
Loading