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

feat: add timing metadata for case contacts #5919

Merged
merged 1 commit into from
Jul 17, 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
3 changes: 2 additions & 1 deletion app/controllers/case_contacts/form_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ def update
params[:case_contact][:status] = step.to_s if !@case_contact.active?
remove_unwanted_contact_types
remove_nil_draft_ids
if @case_contact.update(case_contact_params)

if CaseContactUpdateService.new(@case_contact).update_attrs(case_contact_params)
respond_to do |format|
format.html {
if step == steps.last
Expand Down
1 change: 1 addition & 0 deletions app/models/case_contact.rb
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,7 @@ def casa_org_any_expenses_enabled?
# draft_case_ids :integer default([]), is an Array
# duration_minutes :integer
# medium_type :string
# metadata :jsonb
# miles_driven :integer default(0), not null
# notes :string
# occurred_at :datetime
Expand Down
28 changes: 28 additions & 0 deletions app/services/case_contact_update_service.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
class CaseContactUpdateService
attr_reader :case_contact

def initialize(case_contact)
@case_contact = case_contact
end

def update_attrs(new_attrs)
old_attrs = case_contact.as_json

result = case_contact.update(new_attrs)
update_status_metadata(old_attrs, new_attrs) if result

result
end

private

def update_status_metadata(old_attrs, new_attrs)
return if old_attrs[:status] == new_attrs[:status]

metadata = case_contact.metadata
metadata["status"] ||= {}
metadata["status"][new_attrs[:status]] = Time.zone.now

case_contact.update(metadata: metadata)
end
end
5 changes: 5 additions & 0 deletions db/migrate/20240716194609_add_metadata_to_case_contacts.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class AddMetadataToCaseContacts < ActiveRecord::Migration[7.1]
def change
add_column :case_contacts, :metadata, :jsonb, default: {}
end
end
3 changes: 2 additions & 1 deletion db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema[7.1].define(version: 2024_06_22_020203) do
ActiveRecord::Schema[7.1].define(version: 2024_07_16_194609) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"

Expand Down Expand Up @@ -203,6 +203,7 @@
t.string "status", default: "started"
t.integer "draft_case_ids", default: [], array: true
t.string "volunteer_address"
t.jsonb "metadata", default: {}
t.index ["casa_case_id"], name: "index_case_contacts_on_casa_case_id"
t.index ["creator_id"], name: "index_case_contacts_on_creator_id"
t.index ["deleted_at"], name: "index_case_contacts_on_deleted_at"
Expand Down
203 changes: 203 additions & 0 deletions spec/services/case_contact_update_service_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
require "rails_helper"

RSpec.describe CaseContactUpdateService do
let(:updater) { described_class.new(case_contact) }
let(:case_contact) { create(:case_contact) }

let!(:now) { Time.zone.now }
let!(:one_day_ago) { 1.day.ago }
let!(:two_days_ago) { 2.days.ago }

before { travel_to one_day_ago }
after { travel_back }

describe "#update_attributes" do
context "case is in details status" do
let!(:case_contact) { create(:case_contact, status: "details", created_at: two_days_ago) }

context "status is not updated" do
before { updater.update_attrs({notes: "stuff"}) }

it { expect(case_contact.metadata).to eq({}) }
it { expect(updater.update_attrs({notes: "stuff"})).to be true }
end

it "does not update metadata if attrs are invalid" do
result = updater.update_attrs({occurred_at: 50.years.ago})
expect(case_contact.metadata).to eq({})
expect(result).to be false
end

context "gets updated to details" do
before { updater.update_attrs({status: "details"}) }

it "updates details metadata to current date" do
date = case_contact.metadata.dig("status", "details")
expect(DateTime.parse(date)).to eq(Time.zone.now)
end
it { expect(case_contact.status).to eq("details") }
end

context "gets updated to expenses" do
before { updater.update_attrs({status: "expenses"}) }

it "updates expenses metadata to current date" do
date = case_contact.metadata.dig("status", "expenses")
expect(DateTime.parse(date)).to eq(Time.zone.now)
end
it { expect(case_contact.status).to eq("expenses") }
end

context "gets updated to active" do
before { updater.update_attrs({status: "active"}) }

it "updates active metadata to current date" do
date = case_contact.metadata.dig("status", "active")
expect(DateTime.parse(date)).to eq(Time.zone.now)
end
it { expect(case_contact.status).to eq("active") }
end
end

context "case is in expenses status" do
let!(:case_contact) { create(:case_contact, status: "expenses", created_at: two_days_ago) }

context "status is not updated" do
before { updater.update_attrs({notes: "stuff"}) }

it { expect(case_contact.metadata).to eq({}) }
it { expect(updater.update_attrs({notes: "stuff"})).to be true }
end

it "does not update metadata if attrs are invalid" do
result = updater.update_attrs({occurred_at: 50.years.ago})
expect(case_contact.metadata).to eq({})
expect(result).to be false
end

context "gets updated to details" do
before { updater.update_attrs({status: "details"}) }

it "updates details metadata to current date" do
date = case_contact.metadata.dig("status", "details")
expect(DateTime.parse(date)).to eq(Time.zone.now)
end
it { expect(case_contact.status).to eq("details") }
end

context "gets updated to expenses" do
before { updater.update_attrs({status: "expenses"}) }

it "updates expenses metadata to current date" do
date = case_contact.metadata.dig("status", "expenses")
expect(DateTime.parse(date)).to eq(Time.zone.now)
end
it { expect(case_contact.status).to eq("expenses") }
end

context "gets updated to active" do
before { updater.update_attrs({status: "active"}) }

it "updates active metadata to current date" do
date = case_contact.metadata.dig("status", "active")
expect(DateTime.parse(date)).to eq(Time.zone.now)
end
it { expect(case_contact.status).to eq("active") }
end
end

context "case is in active status" do
let!(:case_contact) { create(:case_contact, status: "active", created_at: two_days_ago) }

context "status is not updated" do
before { updater.update_attrs({notes: "stuff"}) }

it { expect(case_contact.metadata).to eq({}) }
it { expect(updater.update_attrs({notes: "stuff"})).to be true }
end

it "does not update metadata if attrs are invalid" do
result = updater.update_attrs({occurred_at: 50.years.ago})
expect(case_contact.metadata).to eq({})
expect(result).to be false
end

context "gets updated to details" do
before { updater.update_attrs({status: "details"}) }

it "updates details metadata to current date" do
date = case_contact.metadata.dig("status", "details")
expect(DateTime.parse(date)).to eq(Time.zone.now)
end
it { expect(case_contact.status).to eq("details") }
end

context "gets updated to expenses" do
before { updater.update_attrs({status: "expenses"}) }

it "updates expenses metadata to current date" do
date = case_contact.metadata.dig("status", "expenses")
expect(DateTime.parse(date)).to eq(Time.zone.now)
end
it { expect(case_contact.status).to eq("expenses") }
end

context "gets updated to active" do
before { updater.update_attrs({status: "active"}) }

it "updates active metadata to current date" do
date = case_contact.metadata.dig("status", "active")
expect(DateTime.parse(date)).to eq(Time.zone.now)
end
it { expect(case_contact.status).to eq("active") }
end
end

context "case is in started status" do
let!(:case_contact) { create(:case_contact, status: "started", created_at: two_days_ago) }

context "status is not updated" do
before { updater.update_attrs({notes: "stuff"}) }

it { expect(case_contact.metadata).to eq({}) }
it { expect(updater.update_attrs({notes: "stuff"})).to be true }
end

it "does not update metadata if attrs are invalid" do
result = updater.update_attrs({occurred_at: 50.years.ago})
expect(case_contact.metadata).to eq({})
expect(result).to be false
end

context "gets updated to details" do
before { updater.update_attrs({status: "details"}) }

it "updates details metadata to current date" do
date = case_contact.metadata.dig("status", "details")
expect(DateTime.parse(date)).to eq(Time.zone.now)
end
it { expect(case_contact.status).to eq("details") }
end

context "gets updated to expenses" do
before { updater.update_attrs({status: "expenses"}) }

it "updates expenses metadata to current date" do
date = case_contact.metadata.dig("status", "expenses")
expect(DateTime.parse(date)).to eq(Time.zone.now)
end
it { expect(case_contact.status).to eq("expenses") }
end

context "gets updated to active" do
before { updater.update_attrs({status: "active"}) }

it "updates active metadata to current date" do
date = case_contact.metadata.dig("status", "active")
expect(DateTime.parse(date)).to eq(Time.zone.now)
end
it { expect(case_contact.status).to eq("active") }
end
end
end
end
Loading