foodsoft/app/models/group_order_article.rb

151 lines
6.8 KiB
Ruby
Raw Normal View History

# == Schema Information
# Schema version: 20090102171850
#
# Table name: group_order_articles
#
# id :integer(4) not null, primary key
# group_order_id :integer(4) default(0), not null
# order_article_id :integer(4) default(0), not null
# quantity :integer(4) default(0), not null
# tolerance :integer(4) default(0), not null
# updated_on :datetime not null
#
2009-01-06 11:49:19 +01:00
# A GroupOrderArticle stores the sum of how many items of an OrderArticle are ordered as part of a GroupOrder.
# The chronologically order of the OrderGroup - activity are stored in GroupOrderArticleQuantity
#
class GroupOrderArticle < ActiveRecord::Base
belongs_to :group_order
belongs_to :order_article
has_many :group_order_article_quantities, :dependent => :destroy
validates_presence_of :group_order_id
validates_presence_of :order_article_id
validates_inclusion_of :quantity, :in => 0..99
validates_inclusion_of :tolerance, :in => 0..99
validates_uniqueness_of :order_article_id, :scope => :group_order_id # just once an article per group order
# Updates the quantity/tolerance for this GroupOrderArticle by updating both GroupOrderArticle properties
# and the associated GroupOrderArticleQuantities chronologically.
#
# See description of the ordering algorithm in the general application documentation for details.
def updateQuantities(quantity, tolerance)
logger.debug("GroupOrderArticle[#{id}].updateQuantities(#{quantity}, #{tolerance})")
logger.debug("Current quantity = #{self.quantity}, tolerance = #{self.tolerance}")
# Get quantities ordered with the newest item first.
quantities = group_order_article_quantities.find(:all, :order => 'created_on desc')
logger.debug("GroupOrderArticleQuantity items found: #{quantities.size}")
if (quantities.size == 0)
# There is no GroupOrderArticleQuantity item yet, just insert with desired quantities...
logger.debug("No quantities entry at all, inserting a new one with the desired quantities")
quantities.push(GroupOrderArticleQuantity.new(:group_order_article => self, :quantity => quantity, :tolerance => tolerance))
self.quantity, self.tolerance = quantity, tolerance
else
# Decrease quantity/tolerance if necessary by going through the existing items and decreasing their values...
i = 0
while (i < quantities.size && (quantity < self.quantity || tolerance < self.tolerance))
logger.debug("Need to decrease quantities for GroupOrderArticleQuantity[#{quantities[i].id}]")
if (quantity < self.quantity && quantities[i].quantity > 0)
delta = self.quantity - quantity
delta = (delta > quantities[i].quantity ? quantities[i].quantity : delta)
logger.debug("Decreasing quantity by #{delta}")
quantities[i].quantity -= delta
self.quantity -= delta
end
if (tolerance < self.tolerance && quantities[i].tolerance > 0)
delta = self.tolerance - tolerance
delta = (delta > quantities[i].tolerance ? quantities[i].tolerance : delta)
logger.debug("Decreasing tolerance by #{delta}")
quantities[i].tolerance -= delta
self.tolerance -= delta
end
i += 1
end
# If there is at least one increased value: insert a new GroupOrderArticleQuantity object
if (quantity > self.quantity || tolerance > self.tolerance)
logger.debug("Inserting a new GroupOrderArticleQuantity")
quantities.insert(0, GroupOrderArticleQuantity.new(
:group_order_article => self,
:quantity => (quantity > self.quantity ? quantity - self.quantity : 0),
:tolerance => (tolerance > self.tolerance ? tolerance - self.tolerance : 0)
))
# Recalc totals:
self.quantity += quantities[0].quantity
self.tolerance += quantities[0].tolerance
end
end
# Check if something went terribly wrong and quantites have not been adjusted as desired.
if (self.quantity != quantity || self.tolerance != tolerance)
raise 'Invalid state: unable to update GroupOrderArticle/-Quantities to desired quantities!'
end
# Remove zero-only items.
quantities = quantities.reject { | q | q.quantity == 0 && q.tolerance == 0}
# Save
transaction do
quantities.each { | i | i.save! }
self.group_order_article_quantities = quantities
save!
end
end
# Determines how many items of this article the OrderGroup receives.
# Returns a hash with three keys: :quantity / :tolerance / :total
#
# See description of the ordering algorithm in the general application documentation for details.
def orderResult
quantity = tolerance = 0
# Get total
total = order_article.units_to_order * order_article.article.unit_quantity
logger.debug("unitsToOrder => items ordered: #{order_article.units_to_order} => #{total}")
if (total > 0)
# Get all GroupOrderArticleQuantities for this OrderArticle...
orderArticles = GroupOrderArticle.find(:all, :conditions => ['order_article_id = ? AND group_order_id IN (?)', order_article.id, group_order.order.group_orders.collect { | o | o.id }])
orderQuantities = GroupOrderArticleQuantity.find(:all, :conditions => ['group_order_article_id IN (?)', orderArticles.collect { | i | i.id }], :order => 'created_on')
logger.debug("GroupOrderArticleQuantity records found: #{orderQuantities.size}")
# Determine quantities to be ordered...
totalQuantity = i = 0
while (i < orderQuantities.size && totalQuantity < total)
q = (orderQuantities[i].quantity <= total - totalQuantity ? orderQuantities[i].quantity : total - totalQuantity)
totalQuantity += q
if (orderQuantities[i].group_order_article_id == self.id)
logger.debug("increasing quantity by #{q}")
quantity += q
end
i += 1
end
# Determine tolerance to be ordered...
if (totalQuantity < total)
logger.debug("determining additional items to be ordered from tolerance")
i = 0
while (i < orderQuantities.size && totalQuantity < total)
q = (orderQuantities[i].tolerance <= total - totalQuantity ? orderQuantities[i].tolerance : total - totalQuantity)
totalQuantity += q
if (orderQuantities[i].group_order_article_id == self.id)
logger.debug("increasing tolerance by #{q}")
tolerance += q
end
i += 1
end
end
# calculate the sum of quantity and tolerance:
sum = quantity + tolerance
logger.debug("determined quantity/tolerance/total: #{quantity} / #{tolerance} / #{sum}")
end
{:quantity => quantity, :tolerance => tolerance, :total => sum}
end
end