diff --git a/app/controllers/donations_controller.rb b/app/controllers/donations_controller.rb index bc9e6c7e06..2d67085062 100644 --- a/app/controllers/donations_controller.rb +++ b/app/controllers/donations_controller.rb @@ -97,8 +97,9 @@ def show def update @donation = Donation.find(params[:id]) + previous_quantities = @donation.line_items_quantities if @donation.update_attributes(donation_params) - @donation.storage_location.adjust_from_past! @donation + @donation.storage_location.adjust_from_past!(@donation, previous_quantities) redirect_to donations_path else render 'edit' diff --git a/app/controllers/purchases_controller.rb b/app/controllers/purchases_controller.rb index 7f4b4cb69d..ec28a6dba6 100644 --- a/app/controllers/purchases_controller.rb +++ b/app/controllers/purchases_controller.rb @@ -3,7 +3,7 @@ class PurchasesController < ApplicationController skip_before_action :verify_authenticity_token, only: [:scale_intake, :scale] skip_before_action :authenticate_user!, only: [:scale_intake, :scale] skip_before_action :authorize_user, only: [:scale_intake, :scale] - + def index @purchases = current_organization.purchases .includes(:line_items, :storage_location) @@ -49,8 +49,9 @@ def show def update @purchase = current_organization.purchases.find(params[:id]) @purchase.changed? + previous_quantities = @purchase.line_items_quantities if @purchase.update_attributes(purchase_params) - @purchase.storage_location.adjust_from_past! @purchase + @purchase.storage_location.adjust_from_past!(@purchase, previous_quantities) redirect_to purchases_path else render 'edit' diff --git a/app/models/concerns/itemizable.rb b/app/models/concerns/itemizable.rb index d0343c3184..5c99a490b6 100644 --- a/app/models/concerns/itemizable.rb +++ b/app/models/concerns/itemizable.rb @@ -62,6 +62,13 @@ def total validates_associated :line_items end + def line_items_quantities + line_items.inject(Hash.new) do |hash, item| + hash[item.id] = item.quantity + hash + end + end + private def line_item_items_exist_in_inventory diff --git a/app/models/storage_location.rb b/app/models/storage_location.rb index 66e6eb7792..672ccbd5cb 100644 --- a/app/models/storage_location.rb +++ b/app/models/storage_location.rb @@ -101,24 +101,16 @@ def remove!(donation_or_purchase) log end - def adjust_from_past!(donation_or_purchase) - log = {} + def adjust_from_past!(donation_or_purchase, previous_quantities) donation_or_purchase.line_items.each do |line_item| - inventory_item = InventoryItem.find_or_create_by(storage_location_id: self.id, - item_id: line_item.item_id) - before_last_save = line_item.quantity.nil? ? 0 : line_item.quantity - updated_quantity = inventory_item.quantity.nil? ? 0 : inventory_item.quantity - delta = before_last_save - updated_quantity - inventory_item.quantity += delta rescue 0 - if inventory_item.quantity <= 0 - inventory_item.destroy - else - # Otherwise update it - inventory_item.save + inventory_item = InventoryItem.find_or_create_by(storage_location_id: self.id, item_id: line_item.item_id) + if previous_quantity = previous_quantities[line_item.id] + inventory_item.quantity += line_item.quantity + inventory_item.quantity -= previous_quantity + inventory_item.save! end - log[line_item.item_id] = "+#{line_item.quantity}" + inventory_item.destroy! if inventory_item.quantity == 0 end - log end def distribute!(distribution) diff --git a/spec/controllers/donations_controller_spec.rb b/spec/controllers/donations_controller_spec.rb index 03b5f336fa..7ca69279c2 100644 --- a/spec/controllers/donations_controller_spec.rb +++ b/spec/controllers/donations_controller_spec.rb @@ -52,6 +52,23 @@ put :update, params: default_params.merge(id: donation.id, donation: { source: "Donation Site" }) expect(response).to redirect_to(donations_path) end + + it "updates storage quantity correctly" do + donation = create(:donation, :with_items, item_quantity: 10) + line_item = donation.line_items.first + line_item_params = { + "0" => { + "_destroy" => "false", + item_id: line_item.item_id, + quantity: "15", + id: line_item.id + } + } + donation_params = { source: "Donation Site", line_items_attributes: line_item_params } + expect { + put :update, params: default_params.merge(id: donation.id, donation: donation_params) + }.to change { donation.storage_location.inventory_items.first.quantity }.by(5) + end end describe "GET #edit" do diff --git a/spec/controllers/purchases_controller_spec.rb b/spec/controllers/purchases_controller_spec.rb index 56699e5b08..4898ea3dd7 100644 --- a/spec/controllers/purchases_controller_spec.rb +++ b/spec/controllers/purchases_controller_spec.rb @@ -1,7 +1,7 @@ require 'rails_helper' RSpec.describe PurchasesController, type: :controller do - + let(:default_params) { { organization_id: @organization.to_param } } @@ -53,6 +53,23 @@ put :update, params: default_params.merge(id: purchase.id, purchase: { purchased_from: "Google" }) expect(response).to redirect_to(purchases_path) end + + it "updates storage quantity correctly" do + purchase = create(:purchase, :with_items, item_quantity: 10) + line_item = purchase.line_items.first + line_item_params = { + "0" => { + "_destroy" => "false", + item_id: line_item.item_id, + quantity: "5", + id: line_item.id + } + } + purchase_params = { source: "Purchase Site", line_items_attributes: line_item_params } + expect { + put :update, params: default_params.merge(id: purchase.id, purchase: purchase_params) + }.to change { purchase.storage_location.inventory_items.first.quantity }.by(-5) + end end describe "GET #edit" do diff --git a/spec/models/storage_location_spec.rb b/spec/models/storage_location_spec.rb index bd859f490c..42bb573764 100644 --- a/spec/models/storage_location_spec.rb +++ b/spec/models/storage_location_spec.rb @@ -127,28 +127,20 @@ end it "updates the quantity of items" do + previous_quantities = donation.line_items_quantities donation.line_items.first.update(quantity: 5) expect { - storage_location.adjust_from_past!(donation) + storage_location.adjust_from_past!(donation, previous_quantities) storage_location.reload }.to change{storage_location.size}.by(-5) end - - it "adds an inventory item if it doesn't already exist" do - donation.line_items << create(:line_item, quantity: 5) - expect { - storage_location.adjust_from_past!(donation) - storage_location.reload - }.to change{storage_location.size}.by(5) - .and change{InventoryItem.count}.by(1) - end - it "removes the inventory item from the DB if the item's removal results in a 0 count" do + previous_quantities = donation.line_items_quantities donation.line_items.first.update(quantity: 0) expect { - storage_location.adjust_from_past!(donation) + storage_location.adjust_from_past!(donation, previous_quantities) storage_location.reload }.to change{storage_location.inventory_items.size}.by(-1) .and change{InventoryItem.count}.by(-1) @@ -159,27 +151,13 @@ storage_location.intake!(purchase) storage_location.items.reload end - it "add additional line item" do - item = create(:item) - purchase.line_items.create(item_id: item.id, quantity: 6) - storage_location.adjust_from_past!(purchase) - storage_location.items.reload - end - it "adds an inventory item if it doesn't already exist" do - purchase.line_items << create(:line_item, quantity: 5) - - expect { - storage_location.adjust_from_past!(purchase) - storage_location.reload - }.to change{storage_location.size}.by(5) - .and change{InventoryItem.count}.by(1) - end it "removes the inventory item from the DB if the item's removal results in a 0 count" do + previous_quantities = purchase.line_items_quantities purchase.line_items.first.update(quantity: 0) expect { - storage_location.adjust_from_past!(purchase) + storage_location.adjust_from_past!(purchase, previous_quantities) storage_location.reload }.to change{storage_location.inventory_items.size}.by(-1) .and change{InventoryItem.count}.by(-1) diff --git a/spec/support/itemizable_shared_example.rb b/spec/support/itemizable_shared_example.rb index 9fcb0471ec..0f7c525500 100644 --- a/spec/support/itemizable_shared_example.rb +++ b/spec/support/itemizable_shared_example.rb @@ -115,5 +115,20 @@ }.to change{ subject.line_items.total }.by(10) end end + + describe "updated line item quantity" do + subject { create(model_f, organization: @organization) } + let(:storage_location) { subject.storage_location } + + it "updates storage location quantity by the correct amount" do + line_item = subject.line_items.create(item_id: item.id, quantity: 10) + inventory_item = create(:inventory_item, storage_location: storage_location, item_id: line_item.item_id) + previous_quantities = subject.line_items_quantities + line_item.update!(quantity: 5) + expect{ + storage_location.adjust_from_past!(subject, previous_quantities) + }.to change{ inventory_item.reload.quantity }.by(-5) + end + end end end