<commit_before># == Schema Information
#
# Table name: storage_locations
#
#  id              :integer          not null, primary key
#  name            :string
#  address         :string
#  created_at      :datetime
#  updated_at      :datetime
#  organization_id :integer
#

class StorageLocation < ApplicationRecord
  belongs_to :organization
  has_many :inventory_items, -> { includes(:item).order("items.name") }
  has_many :donations
  has_many :distributions
  has_many :items, through: :inventory_items

  validates :name, :address, :organization, presence: true

  include Filterable
  scope :containing, ->(item_id) { joins(:inventory_items).where('inventory_items.item_id = ?', item_id) }
  scope :alphabetized, -> { order(:name) }

  def self.item_total(item_id)
    StorageLocation.select('quantity').joins(:inventory_items).where('inventory_items.item_id = ?', item_id).collect { |h| h.quantity }.reduce(:+)
  end

  def self.items_inventoried
    Item.joins(:storage_locations).select(:id, :name).group(:id, :name).order(name: :asc)
  end

  def item_total(item_id)
    inventory_items.select(:quantity).find_by_item_id(item_id).try(:quantity)
  end

  def size
    inventory_items.sum(:quantity)
  end

  def intake!(donation)
    log = {}
    donation.line_items.each do |line_item|
      inventory_item = InventoryItem.find_or_create_by(storage_location_id: self.id, item_id: line_item.item_id) do |inventory_item|
        inventory_item.quantity = 0
      end
      inventory_item.quantity += line_item.quantity rescue 0
      inventory_item.save
      log[line_item.item_id] = "+#{line_item.quantity}"
    end
    log
  end

  def distribute!(distribution)
    updated_quantities = {}
    insufficient_items = []
    distribution.line_items.each do |line_item|
      inventory_item = self.inventory_items.find_by(item: line_item.item)
      next if inventory_item.nil? || inventory_item.quantity == 0
      if inventory_item.quantity >= line_item.quantity
        updated_quantities[inventory_item.id] = (updated_quantities[inventory_item.id] || inventory_item.quantity) - line_item.quantity
      else
        insufficient_items << {
          item_id: line_item.item.id,
          item_name: line_item.item.name,
          quantity_on_hand: inventory_item.quantity,
          quantity_requested: line_item.quantity
        }
      end
    end

    unless insufficient_items.empty?
      raise Errors::InsufficientAllotment.new(
        "Distribution line_items exceed the available inventory",
        insufficient_items)
    end

    update_inventory_inventory_items(updated_quantities)
  end

  # TODO - this action is happening in the Transfer model/controller - does this method belong here?
  def move_inventory!(transfer)
    updated_quantities = {}
    insufficient_items = []
    transfer.line_items.each do |line_item|<commit_msg>No more negative diapers in distributions when subtracting from quantity 0 When creating a distribution after exhausting a supply of an item to 0, previous behavior would allow for the creation of a distribution for any amount, even though there woud bo 0 of that item in stock. With the removal of the next if item quantity 0, the check is now properly applied, and distributions will not be created for items with a 0 stock at a location.<commit_after># == Schema Information
#
# Table name: storage_locations
#
#  id              :integer          not null, primary key
#  name            :string
#  address         :string
#  created_at      :datetime
#  updated_at      :datetime
#  organization_id :integer
#

class StorageLocation < ApplicationRecord
  belongs_to :organization
  has_many :inventory_items, -> { includes(:item).order("items.name") }
  has_many :donations
  has_many :distributions
  has_many :items, through: :inventory_items

  validates :name, :address, :organization, presence: true

  include Filterable
  scope :containing, ->(item_id) { joins(:inventory_items).where('inventory_items.item_id = ?', item_id) }
  scope :alphabetized, -> { order(:name) }

  def self.item_total(item_id)
    StorageLocation.select('quantity').joins(:inventory_items).where('inventory_items.item_id = ?', item_id).collect { |h| h.quantity }.reduce(:+)
  end

  def self.items_inventoried
    Item.joins(:storage_locations).select(:id, :name).group(:id, :name).order(name: :asc)
  end

  def item_total(item_id)
    inventory_items.select(:quantity).find_by_item_id(item_id).try(:quantity)
  end

  def size
    inventory_items.sum(:quantity)
  end

  def intake!(donation)
    log = {}
    donation.line_items.each do |line_item|
      inventory_item = InventoryItem.find_or_create_by(storage_location_id: self.id, item_id: line_item.item_id) do |inventory_item|
        inventory_item.quantity = 0
      end
      inventory_item.quantity += line_item.quantity rescue 0
      inventory_item.save
      log[line_item.item_id] = "+#{line_item.quantity}"
    end
    log
  end

  def distribute!(distribution)
    updated_quantities = {}
    insufficient_items = []
    distribution.line_items.each do |line_item|
      inventory_item = self.inventory_items.find_by(item: line_item.item)
      next if inventory_item.nil?
      if inventory_item.quantity >= line_item.quantity
        updated_quantities[inventory_item.id] = (updated_quantities[inventory_item.id] || inventory_item.quantity) - line_item.quantity
      else
        insufficient_items << {
          item_id: line_item.item.id,
          item_name: line_item.item.name,
          quantity_on_hand: inventory_item.quantity,
          quantity_requested: line_item.quantity
        }
      end
    end

    unless insufficient_items.empty?
      raise Errors::InsufficientAllotment.new(
        "Distribution line_items exceed the available inventory",
        insufficient_items)
    end

    update_inventory_inventory_items(updated_quantities)
  end

  # TODO - this action is happening in the Transfer model/controller - does this method belong here?
  def move_inventory!(transfer)
    updated_quantities = {}
    insufficient_items = []
    transfer.line_items.each do |line_item|
{'fraction_non_alphanumeric': 0.09334641163969266, 'fraction_numerical': 0.0016347882949158084, 'mean_word_length': 3.6069277108433737, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1856594', 'n_tokens_mistral': 1900, 'n_tokens_neox': 1835, 'n_words': 419}