Skip to content

Commit

Permalink
Everything needed to load all lists from the app store
Browse files Browse the repository at this point in the history
  • Loading branch information
patrick-laa committed Nov 6, 2024
1 parent 93fb689 commit cc49040
Show file tree
Hide file tree
Showing 12 changed files with 268 additions and 28 deletions.
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
15 changes: 15 additions & 0 deletions app/services/submissions/search_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
25 changes: 25 additions & 0 deletions db/migrate/20241105091753_add_assignment_fields_to_application.rb
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
25 changes: 8 additions & 17 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 @@ -166,19 +168,7 @@
FROM base;
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,21 +183,22 @@
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,
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
Expand Down
39 changes: 39 additions & 0 deletions db/views/searches_v06.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
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,
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
108 changes: 98 additions & 10 deletions spec/requests/submissions_search_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -280,18 +280,10 @@
create(:submission, :with_pa_version, laa_reference: "LAA-CCCCCC", state: "rejected")

# in_progress pseudo status_with_assignment (submitted with an assignment)
create(:submission, :with_pa_version, laa_reference: "LAA-DDDDDD", state: "submitted",
events: [build(:event, :new_version),
build(:event, :assignment),
build(:event, :unassignment),
build(:event, :assignment),
build(:event, :decision)])
create(:submission, :with_pa_version, laa_reference: "LAA-DDDDDD", state: "submitted", assigned_user_id: "123")

# not_assigned pseudo status_with_assignment (submitted without an assignment)
create(:submission, :with_pa_version, laa_reference: "LAA-EEEEEE", state: "submitted",
events: [build(:event, :new_version),
build(:event, :assignment),
build(:event, :unassignment)])
create(:submission, :with_pa_version, laa_reference: "LAA-EEEEEE", state: "submitted", assigned_user_id: nil)
end

it "brings back only those with a matching status_with_assignment" do
Expand All @@ -317,6 +309,15 @@
expect(response.parsed_body["data"].pluck("laa_reference")).to contain_exactly("LAA-CCCCCC")
end

it "can handle a status array" do
post search_endpoint, params: {
application_type: "crm4",
status_with_assignment: %w[part_grant rejected],
}

expect(response.parsed_body["data"].pluck("laa_reference")).to contain_exactly("LAA-BBBBBB", "LAA-CCCCCC")
end

it "brings back only those with a matching psuedo status_with_assignment" do
post search_endpoint, params: {
application_type: "crm4",
Expand Down Expand Up @@ -368,6 +369,93 @@
end
end

context "with current caseworker filter" do
before do
create(:submission,
:with_pa_version,
ufn: "111111/111",
assigned_user_id: "123-456",
unassigned_user_ids: [])

create(:submission,
:with_pa_version,
ufn: "222222/222",
assigned_user_id: "789-789",
unassigned_user_ids: [])

create(:submission,
:with_pa_version,
ufn: "333333/333",
assigned_user_id: nil,
unassigned_user_ids: %w[123-456])
end

it "brings back only those with a matching caseworker id" do
post search_endpoint, params: {
application_type: "crm4",
current_caseworker_id: "123-456",
}

expect(response.parsed_body["raw_data"].size).to eq 1
expect(response.parsed_body["raw_data"].pluck("application").pluck("ufn")).to eq(["111111/111"])
end
end

context "with account number filter" do
before do
create(:submission,
:with_pa_version,
ufn: "111111/111",
account_number: "ABC123")

create(:submission,
:with_pa_version,
ufn: "222222/222",
account_number: nil)

create(:submission,
:with_pa_version,
ufn: "333333/333",
account_number: "DEF456")
end

it "brings back only those with a matching account number id" do
post search_endpoint, params: {
application_type: "crm4",
account_number: "ABC123",
}

expect(response.parsed_body["raw_data"].size).to eq 1
expect(response.parsed_body["raw_data"].pluck("application").pluck("ufn")).to eq(["111111/111"])
end
end

context "with id_to_exclude filter" do
let(:excluded_id) { SecureRandom.uuid }

before do
create(:submission,
:with_pa_version,
id: excluded_id,
ufn: "111111/111")

create(:submission,
:with_pa_version,
id: SecureRandom.uuid,
ufn: "222222/222")
end

it "brings back only those that do not" do
post search_endpoint, params: {
application_type: "crm4",
id_to_exclude: excluded_id,
}

expect(response.parsed_body["raw_data"].size).to eq 1
expect(response.parsed_body["raw_data"].pluck("application").pluck("ufn")).to eq(["222222/222"])
end
end

context "with defendant name query for PA" do
before do
create(:submission, :with_pa_version,
Expand Down

0 comments on commit cc49040

Please sign in to comment.