Skip to content

Commit

Permalink
3351 add family archive (#3623)
Browse files Browse the repository at this point in the history
* Added archive column to the Families column
* Updated the view, controller and test to use the new column
* Added auto archive of children on families archive

* Finished adding Scope and Default Filtering

* Added scope to Families with unit tests
* Added default filter to families controller
* Updated the CSV output on the families controller
* Added `Include Archived?` option on the families view
* Added request test to ensure default only returns the non-archived
* Added test for `Include Archived?` check on index

* Fixed some formatting with for respec

* 3351 add family archive Addressing feedback

* Extracted archiving the children of a family to a service object that
  is called in the family controller and took the funciton and callback
  off of the family model
* Updated and added unit test
* Updated the migration to remove backfill migration

* Addressed rubocop formatting issues

* Added ignore for update_all for rubocop since the Child class has no validations

* Quick Fix to update the rubocop issue with update_all

* Renamed the archive_family_children service object to update_family and
updated it to module level function. I also updated the migration table
to creat the column and set nill and default all on one line

* Missed a whitespace after the UpdateFamily service module

* Added archive column to the Families column
* Updated the view, controller and test to use the new column
* Added auto archive of children on families archive

* Finished adding Scope and Default Filtering

* Added scope to Families with unit tests
* Added default filter to families controller
* Updated the CSV output on the families controller
* Added `Include Archived?` option on the families view
* Added request test to ensure default only returns the non-archived
* Added test for `Include Archived?` check on index

* Fixed some formatting with for respec

* 3351 add family archive Addressing feedback

* Extracted archiving the children of a family to a service object that
  is called in the family controller and took the funciton and callback
  off of the family model
* Updated and added unit test
* Updated the migration to remove backfill migration

* Addressed rubocop formatting issues

* Added ignore for update_all for rubocop since the Child class has no validations

* Quick Fix to update the rubocop issue with update_all

* Renamed the archive_family_children service object to update_family and
updated it to module level function. I also updated the migration table
to creat the column and set nill and default all on one line

* Missed a whitespace after the UpdateFamily service module

* Updated the scope to follow the pattern recommended for checkboxes on filterrific

* Fixed some whitespace for rubocop

* Fixed a small typo on the migration
  • Loading branch information
grantmca authored Sep 14, 2023
1 parent edd09a9 commit 4ff7b49
Show file tree
Hide file tree
Showing 12 changed files with 134 additions and 13 deletions.
14 changes: 13 additions & 1 deletion app/controllers/partners/families_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ def index
@filterrific = initialize_filterrific(
current_partner.families
.order(sort_order),
params[:filterrific]
params[:filterrific],
default_filter_params: {"include_archived" => 0}
) || return

@families = @filterrific.find
Expand Down Expand Up @@ -39,6 +40,7 @@ def create
@family = current_partner.families.new(family_params)

if @family.save
archive_children if params[:partners_family][:archived] == '1'
redirect_to @family, notice: "Family was successfully created."
else
render :new
Expand All @@ -49,6 +51,7 @@ def update
@family = current_partner.families.find(params[:id])

if @family.update(family_params)
archive_children if params[:partners_family][:archived] == '1'
redirect_to partners_family_path(@family), notice: "Family was successfully updated."
else
render :edit
Expand All @@ -70,6 +73,7 @@ def family_params
params.require(:partners_family).permit(
:case_manager,
:comments,
:archived,
:guardian_county,
:guardian_employed,
:guardian_employment_type,
Expand Down Expand Up @@ -98,5 +102,13 @@ def sort_direction
def sort_column
Family.column_names.include?(params[:sort]) ? params[:sort] : "guardian_last_name"
end

def archive_children
if UpdateFamily.archive(@family)
flash.now[:notice] = 'Family and children archived successfully.'
else
flash.now[:alert] = service.errors.full_messages.join(', ')
end
end
end
end
13 changes: 10 additions & 3 deletions app/models/partners/family.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
# Table name: families
#
# id :bigint not null, primary key
# archived :boolean default(FALSE)
# case_manager :string
# comments :text
# guardian_county :string
Expand Down Expand Up @@ -39,12 +40,17 @@ class Family < Base
filterrific(
available_filters: [
:search_guardian_names,
:search_agency_guardians
:search_agency_guardians,
:include_archived
],
)

scope :search_guardian_names, ->(query) { where('guardian_first_name ilike ? OR guardian_last_name ilike ?', "%#{query}%", "%#{query}%") }
scope :search_agency_guardians, ->(query) { where('case_manager ilike ?', "%#{query}%") }
scope :include_archived, ->(archived) {
return where(archived: false) if archived == 0
all
}

INCOME_TYPES = ['SSI', 'SNAP/FOOD Stamps', 'TANF', 'WIC', 'Housing/subsidized', 'Housing/unsubsidized', 'N/A'].freeze
INSURANCE_TYPES = ['Private insurance', 'Medicaid', 'Uninsured'].freeze
Expand Down Expand Up @@ -72,7 +78,7 @@ def self.csv_export_headers
id guardian_first_name guardian_last_name guardian_zip_code guardian_county
guardian_phone case_manager home_adult_count home_child_count home_young_child_count
sources_of_income guardian_employed guardian_employment_type guardian_monthly_pay
guardian_health_insurance comments created_at updated_at partner_id military
guardian_health_insurance comments created_at updated_at partner_id military archived
].freeze
end

Expand All @@ -97,7 +103,8 @@ def csv_export_attributes
created_at,
updated_at,
partner_id,
military
military,
archived
]
end
end
Expand Down
21 changes: 21 additions & 0 deletions app/services/partners/update_family.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# This service object is meant to archive a family and all of
# its children
module Partners
module UpdateFamily
extend ServiceObjectErrorsMixin
# rubocop:disable Rails::SkipsModelValidations
def self.archive(family)
if family.children.exists?
ActiveRecord::Base.transaction do
family.update(archived: true, updated_at: Time.zone.now)
family.children.update_all(archived: true, updated_at: Time.zone.now)
rescue => e
errors.add(:base, e.message)
raise ActiveRecord::Rollback
end
end
self
end
# rubocop:enable Rails::SkipsModelValidations
end
end
2 changes: 1 addition & 1 deletion app/views/partners/children/index.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
class: 'filterrific-periodically-observed form-control'
) %>
</div>
<div class="col-3">
<div class="col-2" align="center">
<%= f.label :search_comments, "Show Active Only?" %>
<%= f.check_box(
:search_active,
Expand Down
2 changes: 2 additions & 0 deletions app/views/partners/families/_form.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@
<br>
<%= f.label :comments %>
<%= f.text_area :comments, class: "form-control" %>
<%= f.label :archived %>
<%= f.check_box :archived %>
</div>
<!-- /.card-body -->
<div class="card-footer">
Expand Down
7 changes: 7 additions & 0 deletions app/views/partners/families/index.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,13 @@
class: 'filterrific-periodically-observed form-control'
) %>
</div>
<div class="col-2" align="center">
<%= f.label :include_archived, "Include Archived?" %>
<%= f.check_box(
:include_archived,
class: 'filterrific-periodically-observed form-control',
) %>
</div>
<div class="col-3">
<%= render_filterrific_spinner %>
</div>
Expand Down
9 changes: 9 additions & 0 deletions db/migrate/20230430025441_add_archive_to_families.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
class AddArchiveToFamilies < ActiveRecord::Migration[7.0]
def up
add_column :families, :archived, :boolean, nil: false, default: false
end

def down
remove_column :families, :archived
end
end
4 changes: 3 additions & 1 deletion db/schema.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

# This file is auto-generated from the current state of the database. Instead
# of editing this file, please use the migrations feature of Active Record to
# incrementally modify your database, and then regenerate this schema definition.
Expand All @@ -10,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema[7.0].define(version: 2023_08_18_185722) do
ActiveRecord::Schema[7.0].define(version: 2023_04_30_025441) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"

Expand Down Expand Up @@ -295,6 +296,7 @@
t.bigint "partner_id"
t.boolean "military", default: false
t.bigint "old_partner_id"
t.boolean "archived", default: false
t.index ["partner_id"], name: "index_families_on_partner_id"
end

Expand Down
3 changes: 2 additions & 1 deletion spec/factories/partners/family.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

comments { Faker::Lorem.paragraph }
# Faker doesn't have county, community is same flavour, we don't use it, and it is not country.
guardian_county { Faker::Address.community }
guardian_county { Faker::Address.community }
guardian_employed { false }
guardian_employment_type { nil }
guardian_first_name { Faker::Name.first_name }
Expand All @@ -17,5 +17,6 @@
home_child_count { rand(0..5) }
home_young_child_count { rand(0..5) }
military { false }
archived { false }
end
end
16 changes: 16 additions & 0 deletions spec/models/partners/family_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
# Table name: families
#
# id :bigint not null, primary key
# archived :boolean default(FALSE)
# case_manager :string
# comments :text
# guardian_county :string
Expand Down Expand Up @@ -74,4 +75,19 @@
describe "versioning" do
it { is_expected.to be_versioned }
end

describe "#search_non_archived" do
let!(:partners_family_1) { FactoryBot.create(:partners_family) }
let!(:partners_family_2) { FactoryBot.create(:partners_family) }
let!(:partners_family_3) { FactoryBot.create(:partners_family, archived: true) }
let!(:partners_family_4) { FactoryBot.create(:partners_family, archived: true) }

it "should return all families if one is passed in" do
expect(Partners::Family.include_archived(1)).to contain_exactly(partners_family_1, partners_family_2, partners_family_3, partners_family_4)
end

it "should return non-archived families if zero is passed in" do
expect(Partners::Family.include_archived(0)).to contain_exactly(partners_family_1, partners_family_2)
end
end
end
22 changes: 16 additions & 6 deletions spec/requests/partners/family_requests_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,26 +42,36 @@
guardian_health_insurance: "Medicaid",
comments: "Some comment 2",
military: true,
partner: partner)
partner: partner,
archived: true)
end

describe "GET #index" do
before do
sign_in(partner_user)
end

it "should render without any issues" do
it "should render without any issues and display unarchived families by default" do
get partners_families_path
expect(response).to render_template(:index)
expect(assigns[:families].count).to eq(1)
expect(assigns[:families].pluck(:archived)).to all(be(false))
end

it "should render without any issues and present all families" do
get partners_families_path, params: {"filterrific" => {"include_archived" => "1"}}
expect(response).to render_template(:index)
expect(assigns[:families].count).to eq(2)
end

it "should export CSV" do
headers = {"Accept" => "text/csv", "Content-Type" => "text/csv"}
get partners_families_path, headers: headers
params = {"filterrific" => {"search_guardian_names" => "", "search_agency_guardians" => "", "include_archived" => "1"}}
get partners_families_path, headers: headers, params: params
csv = <<~CSV
id,guardian_first_name,guardian_last_name,guardian_zip_code,guardian_county,guardian_phone,case_manager,home_adult_count,home_child_count,home_young_child_count,sources_of_income,guardian_employed,guardian_employment_type,guardian_monthly_pay,guardian_health_insurance,comments,created_at,updated_at,partner_id,military
#{family1.id},John,Smith,90210,Franklin,416-555-2345,Jane Smith,2,3,1,"SSI,TANF",true,Part-time,4.0,Medicaid,Some comment,#{family1.created_at},#{family1.updated_at},#{partner.id},false
#{family2.id},Mark,Smith,90210,Jefferson,416-555-0987,Jane Smith,1,2,2,TANF,false,Part-time,4.0,Medicaid,Some comment 2,#{family2.created_at},#{family2.updated_at},#{partner.id},true
id,guardian_first_name,guardian_last_name,guardian_zip_code,guardian_county,guardian_phone,case_manager,home_adult_count,home_child_count,home_young_child_count,sources_of_income,guardian_employed,guardian_employment_type,guardian_monthly_pay,guardian_health_insurance,comments,created_at,updated_at,partner_id,military,archived
#{family1.id},John,Smith,90210,Franklin,416-555-2345,Jane Smith,2,3,1,"SSI,TANF",true,Part-time,4.0,Medicaid,Some comment,#{family1.created_at},#{family1.updated_at},#{partner.id},false,false
#{family2.id},Mark,Smith,90210,Jefferson,416-555-0987,Jane Smith,1,2,2,TANF,false,Part-time,4.0,Medicaid,Some comment 2,#{family2.created_at},#{family2.updated_at},#{partner.id},true,true
CSV
expect(response.body).to eq(csv)
end
Expand Down
34 changes: 34 additions & 0 deletions spec/services/partners/update_family_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
require "rails_helper"

RSpec.describe Partners::UpdateFamily do
describe "#call" do
subject { described_class.archive(family) }
let(:family) { FactoryBot.create(:partners_family) }
let!(:child1) { FactoryBot.create(:partners_child, family: family) }
let!(:child2) { FactoryBot.create(:partners_child, family: family) }

context "when family has children" do
it "archives the family and its children" do
expect {
subject
}.to change { family.reload.archived }.from(false).to(true)
.and change { child1.reload.archived }.from(false).to(true)
.and change { child2.reload.archived }.from(false).to(true)
end
end

context "when an error occurs during archiving" do
it "does not archive the family or its children and adds error to the service" do
allow(family.children).to receive(:update_all).and_raise(StandardError)

initial_family_archived = family.archived
initial_children_archived = family.children.pluck(:archived)
initial_errors = subject.errors.dup

expect(family.reload.archived).to eq(initial_family_archived)
expect(family.children.pluck(:archived)).to eq(initial_children_archived)
expect(subject.errors.full_messages).to eq(initial_errors.full_messages)
end
end
end
end

0 comments on commit 4ff7b49

Please sign in to comment.