Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into dependabot/bundler/ra…
Browse files Browse the repository at this point in the history
…ils-7.2.2

 Conflicts:
	Gemfile.lock
	app/models/request.rb
  • Loading branch information
awwaiid committed Dec 15, 2024
2 parents cf88808 + 36f4fe8 commit c30b4d4
Show file tree
Hide file tree
Showing 431 changed files with 6,074 additions and 4,572 deletions.
File renamed without changes.
1 change: 0 additions & 1 deletion .rubocop_todo.yml
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,6 @@ Layout/SpaceInsideHashLiteralBraces:
- 'app/models/product_drive_participant.rb'
- 'app/models/distribution.rb'
- 'app/models/donation.rb'
- 'app/models/inventory_item.rb'
- 'app/models/item.rb'
- 'app/models/item_category.rb'
- 'app/models/kit.rb'
Expand Down
46 changes: 41 additions & 5 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,20 +53,49 @@ Make sure to install **Ubuntu** as your Linux distribution. (This should be defa
<details>
<summary> Bank Users 🏦 </summary>

Pawnee Diaper Bank
A fully set up bank with items, storage locations, donations, distributions, requests, etc.
The bank has multiple partners associated with it.
```
Organization Admin
Email: [email protected]
Email: [email protected]
Password: password!
User
Email: [email protected]
Password: password!
```

Second City Essentials Bank
A fully set up bank with items, storage locations, donations, distributions, requests, etc.
The bank has four items unique to it (named Second City Item #).
```
Organization Admin
Email: [email protected]
Password: password!
User
Email: [email protected]
Password: password!
```

SF Diaper Bank
A bank which has just been accepted and so is not fully set up. It lacks many of the records the other banks have.
```
Organization Admin
Email: [email protected]
Password: password!
User
Email: [email protected]
Password: password!
```
</details>

<details>
<summary> Partner Users 👥 </summary>

Partners in Pawnee Diaper Bank partner groups
```
Verified Partner
Email: [email protected]
Expand All @@ -87,10 +116,17 @@ Make sure to install **Ubuntu** as your Linux distribution. (This should be defa
Waiting Approval Partner
Email: [email protected]
Password: password!
Another approved partner (with all groups):
Another verified partner (in second partner group):
Email: [email protected]
Pasword: password!
Password: password!
```

Partners in Second City Essentials Bank partner group
```
Verified partner
Email: [email protected]
Password: password!
```
</details>

Expand Down Expand Up @@ -221,7 +257,7 @@ Before submitting a pull request, run all tests and lints. Fix any broken tests
- Once your first PR has been merged, all commits pushed to an open PR will also run these workflows.
#### Local testing
- Run all lints with `bin/lint`.
- Run all lints with `bin/lint`. (You can lint a single file/folder with `bin/lint {path_to_folder_or_file}`.)
- Run all tests with `bundle exec rspec`
- You can run a single test with `bundle exec rspec {path_to_test_name}_spec.rb` or on a specific line by appending `:LineNumber`
- If you need to skip a failing test, place `pending("Reason you are skipping the test")` into the `it` block rather than skipping with `xit`. This will allow rspec to deliver the error message without causing the test suite to fail.
Expand Down
2 changes: 2 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ gem "jwt"
gem "newrelic_rpm"
# Used to manage periodic cron-like jobs
gem "clockwork"
# Speed up app boot time by caching expensive operations
gem 'bootsnap', require: false

##### DEPENDENCY PINS ######
# These are gems that aren't used directly, only as dependencies for other gems.
Expand Down
4 changes: 4 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ GEM
bindex (0.8.1)
binding_of_caller (1.0.1)
debug_inspector (>= 1.2.0)
bootsnap (1.18.4)
msgpack (~> 1.2)
bootstrap (5.2.3)
autoprefixer-rails (>= 9.1.0)
popper_js (>= 2.11.6, < 3)
Expand Down Expand Up @@ -381,6 +383,7 @@ GEM
monetize (~> 1.9)
money (~> 6.13)
railties (>= 3.0)
msgpack (1.7.5)
multi_xml (0.7.1)
bigdecimal (~> 3.1)
multipart-post (2.4.1)
Expand Down Expand Up @@ -716,6 +719,7 @@ DEPENDENCIES
azure-storage-blob
better_errors
binding_of_caller
bootsnap
bootstrap (~> 5.2)
brakeman
bugsnag
Expand Down
10 changes: 10 additions & 0 deletions app/assets/stylesheets/custom.scss
Original file line number Diff line number Diff line change
Expand Up @@ -98,3 +98,13 @@
margin-top: 40px;
}
}

.accordion-button.saving::after {
background-image: none;
content: "Saving...";
font-size: 0.875rem;
color: #005568;
transform: none;
width: 3rem;
cursor: not-allowed;
}
6 changes: 5 additions & 1 deletion app/controllers/admin/base_items_controller.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# [Super Admin] Manage the BaseItems -- this is the only place in the app where Base Items can be
# added / modified. Base Items are both the template and common thread for regular Items
#
# See #4656, BaseItems are pending significant changes/possible deletion
class Admin::BaseItemsController < AdminController
def edit
@base_item = BaseItem.find(params[:id])
Expand Down Expand Up @@ -40,7 +42,9 @@ def show

def destroy
@base_item = BaseItem.includes(:items).find(params[:id])
if @base_item.items.any? && @base_item.destroy
if @base_item.id == KitCreateService.find_or_create_kit_base_item!.id
redirect_to admin_base_items_path, alert: "You cannot delete the Kits base item. This is reserved for all Kits."
elsif @base_item.items.empty? && @base_item.destroy
redirect_to admin_base_items_path, notice: "Base Item deleted!"
else
redirect_to admin_base_items_path, alert: "Failed to delete Base Item. Are there still items attached?"
Expand Down
9 changes: 5 additions & 4 deletions app/controllers/admin/organizations_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,14 @@ def new

def create
@organization = Organization.new(organization_params)
@user = User.new(user_params)

if @organization.save
Organization.seed_items(@organization)
@user = UserInviteService.invite(name: user_params[:name],
email: user_params[:email],
roles: [Role::ORG_USER, Role::ORG_ADMIN],
resource: @organization)
UserInviteService.invite(name: user_params[:name],
email: user_params[:email],
roles: [Role::ORG_USER, Role::ORG_ADMIN],
resource: @organization)
SnapshotEvent.publish(@organization) # need one to start with
redirect_to admin_organizations_path, notice: "Organization added!"
else
Expand Down
27 changes: 3 additions & 24 deletions app/controllers/audits_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,7 @@ def index
end

def show
if Event.read_events?(@audit.organization)
@items = View::Inventory.items_for_location(@audit.storage_location)
else
@inventory_items = @audit.storage_location.inventory_items
end
@items = View::Inventory.items_for_location(@audit.storage_location, include_omitted: true)
end

def edit
Expand All @@ -28,24 +24,7 @@ def finalize
@audit.adjustment = Adjustment.new(organization_id: @audit.organization_id, storage_location_id: @audit.storage_location_id, user_id: current_user.id, comment: 'Created Automatically through the Auditing Process')
@audit.save

inventory_items = @audit.storage_location.inventory_items

inventory_items.each do |inventory_item|
line_item = @audit.line_items.find_by(item: inventory_item.item)

next if line_item.nil?

if line_item.quantity != inventory_item.quantity
@audit.adjustment.line_items.create(item_id: inventory_item.item.id, quantity: line_item.quantity - inventory_item.quantity)
end
end

increasing_adjustment, decreasing_adjustment = @audit.adjustment.split_difference
ActiveRecord::Base.transaction do
@audit.storage_location.increase_inventory(increasing_adjustment.line_item_values)
@audit.storage_location.decrease_inventory(decreasing_adjustment.line_item_values)
AuditEvent.publish(@audit)
end
AuditEvent.publish(@audit)
@audit.finalized!
redirect_to audit_path(@audit), notice: "Audit is Finalized."
rescue => e
Expand Down Expand Up @@ -114,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
94 changes: 40 additions & 54 deletions app/controllers/distributions_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,30 +43,33 @@ def index

@distributions = current_organization
.distributions
.includes(:partner, :storage_location, line_items: [:item])
.order('issued_at DESC')
.apply_filters(filter_params, helpers.selected_range)
.order(issued_at: :desc)
.includes(:partner, :storage_location)
.class_filter(scope_filters)
@paginated_distributions = @distributions.page(params[:page])
@items = current_organization.items.alphabetized
@item_categories = current_organization.item_categories
@storage_locations = current_organization.storage_locations.active_locations.alphabetized
@partners = @distributions.collect(&:partner).uniq.sort_by(&:name)
@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 = current_organization.partners.active.alphabetized.select(:id, :name)
@selected_item = filter_params[:by_item_id].presence
@total_value_all_distributions = total_value(@distributions)
@total_items_all_distributions = total_items(@distributions, @selected_item)
@total_value_paginated_distributions = total_value(@paginated_distributions)
@total_items_paginated_distributions = total_items(@paginated_distributions, @selected_item)
@distribution_totals = DistributionTotalsService.new(current_organization.distributions, scope_filters)
@total_value_all_distributions = @distribution_totals.total_value
@total_items_all_distributions = @distribution_totals.total_quantity
paginated_ids = @paginated_distributions.ids
@total_value_paginated_distributions = @distribution_totals.total_value(paginated_ids)
@total_items_paginated_distributions = @distribution_totals.total_quantity(paginated_ids)
@selected_item_category = filter_params[:by_item_category_id]
@selected_partner = filter_params[:by_partner]
@selected_status = filter_params[:by_state]
@selected_location = filter_params[:by_location]
# FIXME: one of these needs to be removed but it's unclear which at this point
@statuses = Distribution.states.transform_keys(&:humanize)
@distributions_with_inactive_items = @distributions.joins(:inactive_items).pluck(:id)

respond_to do |format|
format.html
format.csv do
send_data Exports::ExportDistributionsCSVService.new(distributions: @distributions, organization: current_organization, filters: filter_params).generate_csv, filename: "Distributions-#{Time.zone.today}.csv"
send_data Exports::ExportDistributionsCSVService.new(distributions: @distributions, organization: current_organization, filters: scope_filters).generate_csv, filename: "Distributions-#{Time.zone.today}.csv"
end
end
end
Expand Down Expand Up @@ -114,16 +117,12 @@ 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

if Event.read_events?(current_organization)
inventory = View::Inventory.new(@distribution.organization_id)
@storage_locations = current_organization.storage_locations.active_locations.alphabetized.select do |storage_loc|
inventory.quantity_for(storage_location: storage_loc.id).positive?
end
else
@storage_locations = current_organization.storage_locations.active_locations.has_inventory_items.alphabetized
inventory = View::Inventory.new(@distribution.organization_id)
@storage_locations = current_organization.storage_locations.active_locations.alphabetized.select do |storage_loc|
inventory.quantity_for(storage_location: storage_loc.id).positive?
end

flash_error = insufficient_error_message(result.error.message)
Expand All @@ -148,16 +147,12 @@ 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

if Event.read_events?(current_organization)
inventory = View::Inventory.new(current_organization.id)
@storage_locations = current_organization.storage_locations.active_locations.alphabetized.select do |storage_loc|
inventory.quantity_for(storage_location: storage_loc.id).positive?
end
else
@storage_locations = current_organization.storage_locations.active_locations.has_inventory_items.alphabetized
inventory = View::Inventory.new(current_organization.id)
@storage_locations = current_organization.storage_locations.active_locations.alphabetized.select do |storage_loc|
inventory.quantity_for(storage_location: storage_loc.id).positive?
end
end

Expand All @@ -178,18 +173,14 @@ 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)
.where("updated_at > ?", @distribution.created_at).any?
if Event.read_events?(current_organization)
inventory = View::Inventory.new(@distribution.organization_id)
@storage_locations = current_organization.storage_locations.active_locations.alphabetized.select do |storage_loc|
!inventory.quantity_for(storage_location: storage_loc.id).negative?
end
else
@storage_locations = current_organization.storage_locations.active_locations.has_inventory_items.alphabetized
inventory = View::Inventory.new(@distribution.organization_id)
@storage_locations = current_organization.storage_locations.active_locations.alphabetized.select do |storage_loc|
!inventory.quantity_for(storage_location: storage_loc.id).negative?
end
else
redirect_to distributions_path, error: 'To edit a distribution,
Expand All @@ -213,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 Expand Up @@ -297,16 +288,6 @@ def request_id
params.dig(:distribution, :request_attributes, :id)
end

def total_items(distributions, item)
query = LineItem.where(itemizable_type: "Distribution", itemizable_id: distributions.pluck(:id))
query = query.where(item_id: item.to_i) if item
query.sum('quantity')
end

def total_value(distributions)
distributions.sum(&:value_per_itemizable)
end

def daily_items(pick_ups)
item_groups = LineItem.where(itemizable_type: "Distribution", itemizable_id: pick_ups.pluck(:id)).group_by(&:item_id)
item_groups.map do |_id, items|
Expand All @@ -318,21 +299,26 @@ def daily_items(pick_ups)
end
end

def scope_filters
filter_params
.except(:date_range)
.merge(during: helpers.selected_range)
end

helper_method \
def filter_params
return {} unless params.key?(:filters)

params.require(:filters).permit(:by_item_id, :by_item_category_id, :by_partner, :by_state, :by_location)
params
.require(:filters)
.permit(:by_item_id, :by_item_category_id, :by_partner, :by_state, :by_location, :date_range)
end

def perform_inventory_check
inventory_check_result = InventoryCheckService.new(@distribution).call

if inventory_check_result.error.present?
flash[:error] = inventory_check_result.error
end
if inventory_check_result.alert.present?
flash[:alert] = inventory_check_result.alert
end
alerts = [inventory_check_result.minimum_alert, inventory_check_result.recommended_alert]
merged_alert = alerts.compact.join("\n")
flash[:alert] = merged_alert if merged_alert.present?
end
end
Loading

0 comments on commit c30b4d4

Please sign in to comment.