Skip to content

Commit

Permalink
Merge branch 'main' into improve-distributions-by-country-report-perf…
Browse files Browse the repository at this point in the history
…ormance
  • Loading branch information
coalest authored Dec 13, 2024
2 parents 257cf8f + 5538cc5 commit 2c1124d
Show file tree
Hide file tree
Showing 17 changed files with 350 additions and 15 deletions.
2 changes: 1 addition & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,7 @@ GEM
timeout
net-smtp (0.5.0)
net-protocol
newrelic_rpm (9.13.0)
newrelic_rpm (9.16.0)
nio4r (2.7.3)
nokogiri (1.16.7-arm64-darwin)
racc (~> 1.4)
Expand Down
4 changes: 2 additions & 2 deletions app/controllers/audits_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ def index
end

def show
@items = View::Inventory.items_for_location(@audit.storage_location)
@items = View::Inventory.items_for_location(@audit.storage_location, include_omitted: true)
end

def edit
Expand Down Expand Up @@ -93,7 +93,7 @@ def set_storage_locations
end

def set_items
@items = current_organization.items.alphabetized
@items = current_organization.items.where(active: true).alphabetized
end

def save_audit_status_and_redirect(params)
Expand Down
10 changes: 5 additions & 5 deletions app/controllers/distributions_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def index
@items = current_organization.items.alphabetized.select(:id, :name)
@item_categories = current_organization.item_categories.select(:id, :name)
@storage_locations = current_organization.storage_locations.active_locations.alphabetized.select(:id, :name)
@partners = Partner.joins(:distributions).where(distributions: @distributions).distinct.order(:name).select(:id, :name)
@partners = current_organization.partners.active.alphabetized.select(:id, :name)
@selected_item = filter_params[:by_item_id].presence
@distribution_totals = DistributionTotalsService.new(current_organization.distributions, scope_filters)
@total_value_all_distributions = @distribution_totals.total_value
Expand Down Expand Up @@ -117,7 +117,7 @@ def create
elsif request_id
@distribution.initialize_request_items
end
@items = current_organization.items.alphabetized
@items = current_organization.items.active.alphabetized
@partner_list = current_organization.partners.where.not(status: 'deactivated').alphabetized

inventory = View::Inventory.new(@distribution.organization_id)
Expand Down Expand Up @@ -147,7 +147,7 @@ def new
@distribution.line_items.build
@distribution.copy_from_donation(params[:donation_id], params[:storage_location_id])
end
@items = current_organization.items.alphabetized
@items = current_organization.items.active.alphabetized
@partner_list = current_organization.partners.where.not(status: 'deactivated').alphabetized

inventory = View::Inventory.new(current_organization.id)
Expand All @@ -173,7 +173,7 @@ def edit
if (!@distribution.complete? && @distribution.future?) ||
current_user.has_role?(Role::ORG_ADMIN, current_organization)
@distribution.line_items.build if @distribution.line_items.size.zero?
@items = current_organization.items.alphabetized
@items = current_organization.items.active.alphabetized
@partner_list = current_organization.partners.alphabetized
@audit_warning = current_organization.audits
.where(storage_location_id: @distribution.storage_location_id)
Expand Down Expand Up @@ -204,7 +204,7 @@ def update
flash[:error] = insufficient_error_message(result.error.message)
@distribution.line_items.build if @distribution.line_items.size.zero?
@distribution.initialize_request_items
@items = current_organization.items.alphabetized
@items = current_organization.items.active.alphabetized
@storage_locations = current_organization.storage_locations.active_locations.alphabetized
render :edit
end
Expand Down
6 changes: 6 additions & 0 deletions app/models/distribution.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ class Distribution < ApplicationRecord
enum state: { scheduled: 5, complete: 10 }
enum delivery_method: { pick_up: 0, delivery: 1, shipped: 2 }
scope :active, -> { joins(:line_items).joins(:items).where(items: { active: true }) }
scope :with_diapers, -> { joins(line_items: :item).merge(Item.disposable.or(Item.cloth_diapers)) }
scope :with_period_supplies, -> { joins(line_items: :item).merge(Item.period_supplies) }
# add item_id scope to allow filtering distributions by item
scope :by_item_id, ->(item_id) { includes(:items).where(items: { id: item_id }) }
# partner scope to allow filtering by partner
Expand All @@ -71,6 +73,10 @@ class Distribution < ApplicationRecord
where("issued_at > :start_date AND issued_at <= :end_date",
start_date: Time.zone.today.beginning_of_week.beginning_of_day, end_date: Time.zone.today.end_of_week.end_of_day)
end
scope :in_last_12_months, -> do
where("issued_at > :start_date AND issued_at <= :end_date",
start_date: 12.months.ago.beginning_of_day, end_date: Time.zone.today.end_of_day)
end

delegate :name, to: :partner, prefix: true

Expand Down
2 changes: 1 addition & 1 deletion app/models/item.rb
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ def is_in_kit?(kits = nil)
end

def can_delete?(inventory = nil, kits = nil)
can_deactivate_or_delete?(inventory, kits) && line_items.none? && !barcode_count&.positive? && !in_request?
can_deactivate_or_delete?(inventory, kits) && line_items.none? && !barcode_count&.positive? && !in_request? && kit.blank?
end

# @return [Boolean]
Expand Down
18 changes: 16 additions & 2 deletions app/models/partner.rb
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,10 @@ def self.csv_export_headers
"Contact Name",
"Contact Phone",
"Contact Email",
"Notes"
"Notes",
"Counties Served",
"Providing Diapers",
"Providing Period Supplies"
]
end

Expand All @@ -202,10 +205,21 @@ def csv_export_attributes
contact_person[:name],
contact_person[:phone],
contact_person[:email],
notes
notes,
profile.county_list_by_region,
providing_diapers,
providing_period_supplies
]
end

def providing_diapers
distributions.in_last_12_months.with_diapers.any? ? "Y" : "N"
end

def providing_period_supplies
distributions.in_last_12_months.with_period_supplies.any? ? "Y" : "N"
end

def contact_person
return @contact_person if @contact_person

Expand Down
6 changes: 6 additions & 0 deletions app/models/partners/profile.rb
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ class Profile < Base

has_many :served_areas, foreign_key: "partner_profile_id", class_name: "Partners::ServedArea", dependent: :destroy, inverse_of: :partner_profile

has_many :counties, through: :served_areas
accepts_nested_attributes_for :served_areas, allow_destroy: true

has_many_attached :documents
Expand Down Expand Up @@ -125,6 +126,11 @@ def split_pick_up_emails
pick_up_email.split(/,|\s+/).compact_blank
end

def county_list_by_region
# provides a county list in case insensitive alpha order, by region, then county name
counties.order(%w(lower(region) lower(name))).pluck(:name).join("; ")
end

private

def check_social_media
Expand Down
2 changes: 1 addition & 1 deletion app/views/audits/_form.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
</div>
<div class="box-body">
<%= simple_form_for @audit, data: { controller: "form-input" }, html: {class: "storage-location-required"} do |f| %>
<%= render partial: "storage_locations/source", object: f, locals: { label: "Storage location", error: "What storage location are you auditing?" } %>
<%= render partial: "storage_locations/source", object: f, locals: { label: "Storage location", error: "What storage location are you auditing?", include_omitted_items: true } %>
<fieldset style="margin-bottom: 2rem;">
<legend>Items in this audit</legend>
<div id="audit_line_items" class="line-item-fields" data-capture-barcode="true">
Expand Down
3 changes: 2 additions & 1 deletion db/seeds.rb
Original file line number Diff line number Diff line change
Expand Up @@ -739,7 +739,8 @@ def seed_quantity(item_name, organization, storage_location, quantity)
Flipper::Adapters::ActiveRecord::Feature.find_or_create_by(key: "new_logo")
Flipper::Adapters::ActiveRecord::Feature.find_or_create_by(key: "read_events")
Flipper.enable(:read_events)

Flipper::Adapters::ActiveRecord::Feature.find_or_create_by(key: "partner_step_form")
Flipper.enable(:partner_step_form)
# ----------------------------------------------------------------------------
# Account Requests
# ----------------------------------------------------------------------------
Expand Down
4 changes: 4 additions & 0 deletions spec/factories/partners.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@
status { :awaiting_review }
end

trait :deactivated do
status { :deactivated }
end

after(:create) do |partner, evaluator|
next if evaluator.try(:without_profile)

Expand Down
61 changes: 61 additions & 0 deletions spec/models/distribution_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,34 @@
end
end

describe "in_last_12_months >" do
context "when the current date is December 31, 2023" do
before do
travel_to Time.zone.local(2023, 12, 31)
end

after do
travel_back
end

it "includes distributions issued within the last 12 months" do
included_distribution = create(:distribution, organization: organization, issued_at: Time.zone.local(2023, 1, 1))
excluded_distribution = create(:distribution, organization: organization, issued_at: Time.zone.local(2022, 12, 30))
distributions = Distribution.in_last_12_months
expect(distributions).to include(included_distribution)
expect(distributions).not_to include(excluded_distribution)
end

it "includes distributions up to the current date and excludes future ones" do
current_distribution = create(:distribution, organization: organization, issued_at: Time.zone.local(2023, 12, 31))
future_distribution = create(:distribution, organization: organization, issued_at: Time.zone.local(2024, 1, 1))
distributions = Distribution.in_last_12_months
expect(distributions).to include(current_distribution)
expect(distributions).not_to include(future_distribution)
end
end
end

describe "by_item_id >" do
it "only returns distributions with given item id" do
# create 2 items with unique ids
Expand Down Expand Up @@ -176,6 +204,39 @@
expect(Distribution.by_location(location_1.id)).not_to include(dist2)
end
end

describe "with_diapers >" do
let(:disposable_item) { create(:item, base_item: create(:base_item, category: "Diapers - Childrens")) }
let(:cloth_diaper_item) { create(:item, base_item: create(:base_item, category: "Diapers - Cloth (Kids)")) }
let(:non_diaper_item) { create(:item, base_item: create(:base_item, category: "Menstrual Supplies/Items")) }

it "only includes distributions with disposable or cloth_diaper items" do
dist1 = create(:distribution, :with_items, item: disposable_item)
dist2 = create(:distribution, :with_items, item: cloth_diaper_item)
dist3 = create(:distribution, :with_items, item: non_diaper_item)

distributions = Distribution.with_diapers
expect(distributions.count).to eq(2)
expect(distributions).to include(dist1)
expect(distributions).to include(dist2)
expect(distributions).not_to include(dist3)
end
end

describe "with_period_supplies >" do
let(:period_supplies_item) { create(:item, base_item: create(:base_item, category: "Menstrual Supplies/Items")) }
let(:non_period_supplies_item) { create(:item, base_item: create(:base_item, category: "Diapers - Childrens")) }

it "only includes distributions with period supplies items" do
dist1 = create(:distribution, :with_items, item: period_supplies_item)
dist2 = create(:distribution, :with_items, item: non_period_supplies_item)

distributions = Distribution.with_period_supplies
expect(distributions.count).to eq(1)
expect(distributions).to include(dist1)
expect(distributions).not_to include(dist2)
end
end
end

context "Callbacks >" do
Expand Down
43 changes: 43 additions & 0 deletions spec/models/item_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -481,4 +481,47 @@
describe "versioning" do
it { is_expected.to be_versioned }
end

describe "kit items" do
context "with kit and regular items" do
let(:organization) { create(:organization) }
let(:kit) { create(:kit, organization: organization) }
let(:kit_item) { create(:item, kit: kit, organization: organization) }
let(:regular_item) { create(:item, organization: organization) }

describe "#can_delete?" do
it "returns false for kit items" do
expect(kit_item.can_delete?).to be false
end

it "returns true for regular items" do
expect(regular_item.can_delete?).to be true
end
end

describe "#deactivate!" do
it "deactivates both the kit item and its associated kit" do
kit_item.deactivate!
expect(kit_item.reload.active).to be false
expect(kit.reload.active).to be false
end

it "only deactivates regular items" do
regular_item.deactivate!
expect(regular_item.reload.active).to be false
end
end

describe "#validate_destroy" do
it "prevents deletion of kit items" do
expect { kit_item.destroy! }.to raise_error(ActiveRecord::RecordNotDestroyed)
expect(kit_item.errors[:base]).to include("Cannot delete item - it has already been used!")
end

it "allows deletion of regular items" do
expect { regular_item.destroy! }.not_to raise_error
end
end
end
end
end
Loading

0 comments on commit 2c1124d

Please sign in to comment.