add receive screen, quantities for model, redistribution
This commit is contained in:
parent
ed9a6cca39
commit
bd1b932775
17 changed files with 365 additions and 49 deletions
|
|
@ -99,57 +99,63 @@ class GroupOrderArticle < ActiveRecord::Base
|
|||
# Returns a hash with three keys: :quantity / :tolerance / :total
|
||||
#
|
||||
# See description of the ordering algorithm in the general application documentation for details.
|
||||
def calculate_result
|
||||
@calculate_result ||= begin
|
||||
quantity = tolerance = total_quantity = 0
|
||||
def calculate_result(total = nil)
|
||||
# return memoized result unless a total is given
|
||||
return @calculate_result if total.nil? and not @calculate_result.nil?
|
||||
|
||||
# Get total
|
||||
if order_article.article.is_a?(StockArticle)
|
||||
total = order_article.article.quantity
|
||||
logger.debug "<#{order_article.article.name}> (stock) => #{total}"
|
||||
else
|
||||
total = order_article.units_to_order * order_article.price.unit_quantity
|
||||
logger.debug "<#{order_article.article.name}> units_to_order #{order_article.units_to_order} => #{total}"
|
||||
quantity = tolerance = total_quantity = 0
|
||||
|
||||
# Get total
|
||||
if not total.nil?
|
||||
logger.debug "<#{order_article.article.name}> => #{total} (given)"
|
||||
elsif order_article.article.is_a?(StockArticle)
|
||||
total = order_article.article.quantity
|
||||
logger.debug "<#{order_article.article.name}> (stock) => #{total}"
|
||||
else
|
||||
total = order_article.units_to_order * order_article.price.unit_quantity
|
||||
logger.debug "<#{order_article.article.name}> units_to_order #{order_article.units_to_order} => #{total}"
|
||||
end
|
||||
|
||||
if total > 0
|
||||
# In total there are enough units ordered. Now check the individual result for the ordergroup (group_order).
|
||||
#
|
||||
# Get all GroupOrderArticleQuantities for this OrderArticle...
|
||||
order_quantities = GroupOrderArticleQuantity.all(
|
||||
:conditions => ["group_order_article_id IN (?)", order_article.group_order_article_ids], :order => 'created_on')
|
||||
logger.debug "GroupOrderArticleQuantity records found: #{order_quantities.size}"
|
||||
|
||||
# Determine quantities to be ordered...
|
||||
order_quantities.each do |goaq|
|
||||
q = [goaq.quantity, total - total_quantity].min
|
||||
total_quantity += q
|
||||
if goaq.group_order_article_id == self.id
|
||||
logger.debug "increasing quantity by #{q}"
|
||||
quantity += q
|
||||
end
|
||||
break if total_quantity >= total
|
||||
end
|
||||
|
||||
if total > 0
|
||||
# In total there are enough units ordered. Now check the individual result for the ordergroup (group_order).
|
||||
#
|
||||
# Get all GroupOrderArticleQuantities for this OrderArticle...
|
||||
order_quantities = GroupOrderArticleQuantity.all(
|
||||
:conditions => ["group_order_article_id IN (?)", order_article.group_order_article_ids], :order => 'created_on')
|
||||
logger.debug "GroupOrderArticleQuantity records found: #{order_quantities.size}"
|
||||
|
||||
# Determine quantities to be ordered...
|
||||
# Determine tolerance to be ordered...
|
||||
if total_quantity < total
|
||||
logger.debug "determining additional items to be ordered from tolerance"
|
||||
order_quantities.each do |goaq|
|
||||
q = [goaq.quantity, total - total_quantity].min
|
||||
q = [goaq.tolerance, total - total_quantity].min
|
||||
total_quantity += q
|
||||
if goaq.group_order_article_id == self.id
|
||||
logger.debug "increasing quantity by #{q}"
|
||||
quantity += q
|
||||
logger.debug "increasing tolerance by #{q}"
|
||||
tolerance += q
|
||||
end
|
||||
break if total_quantity >= total
|
||||
end
|
||||
|
||||
# Determine tolerance to be ordered...
|
||||
if total_quantity < total
|
||||
logger.debug "determining additional items to be ordered from tolerance"
|
||||
order_quantities.each do |goaq|
|
||||
q = [goaq.tolerance, total - total_quantity].min
|
||||
total_quantity += q
|
||||
if goaq.group_order_article_id == self.id
|
||||
logger.debug "increasing tolerance by #{q}"
|
||||
tolerance += q
|
||||
end
|
||||
break if total_quantity >= total
|
||||
end
|
||||
end
|
||||
|
||||
logger.debug "determined quantity/tolerance/total: #{quantity} / #{tolerance} / #{quantity + tolerance}"
|
||||
end
|
||||
|
||||
{:quantity => quantity, :tolerance => tolerance, :total => quantity + tolerance}
|
||||
logger.debug "determined quantity/tolerance/total: #{quantity} / #{tolerance} / #{quantity + tolerance}"
|
||||
end
|
||||
|
||||
# memoize result unless a total is given
|
||||
r = {:quantity => quantity, :tolerance => tolerance, :total => quantity + tolerance}
|
||||
@calculate_result = r if total.nil?
|
||||
r
|
||||
end
|
||||
|
||||
# Returns order result,
|
||||
|
|
@ -160,8 +166,8 @@ class GroupOrderArticle < ActiveRecord::Base
|
|||
end
|
||||
|
||||
# This is used during order.finish!.
|
||||
def save_results!
|
||||
self.update_attribute(:result, calculate_result[:total])
|
||||
def save_results!(article_total = nil)
|
||||
self.update_attribute(:result, calculate_result(article_total)[:total])
|
||||
end
|
||||
|
||||
# Returns total price for this individual article
|
||||
|
|
|
|||
|
|
@ -166,6 +166,9 @@ class Order < ActiveRecord::Base
|
|||
goa.save_results!
|
||||
# Delete no longer required order-history (group_order_article_quantities) and
|
||||
# TODO: Do we need articles, which aren't ordered? (units_to_order == 0 ?)
|
||||
# A: Yes, we do - for redistributing articles when the number of articles
|
||||
# delivered changes, and for statistics on popular articles. Records
|
||||
# with both tolerance and quantity zero can be deleted.
|
||||
#goa.group_order_article_quantities.clear
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -12,8 +12,8 @@ class OrderArticle < ActiveRecord::Base
|
|||
validate :article_and_price_exist
|
||||
validates_uniqueness_of :article_id, scope: :order_id
|
||||
|
||||
scope :ordered, :conditions => "units_to_order > 0"
|
||||
scope :ordered_or_member, -> { includes(:group_order_articles).where("units_to_order > 0 OR group_order_articles.result > 0") }
|
||||
scope :ordered, -> { where("units_to_order > 0 OR units_billed > 0 OR units_received > 0") }
|
||||
scope :ordered_or_member, -> { includes(:group_order_articles).where("units_to_order > 0 OR units_billed > 0 OR units_received > 0 OR group_order_articles.result > 0") }
|
||||
|
||||
before_create :init_from_balancing
|
||||
after_destroy :update_ordergroup_prices
|
||||
|
|
@ -34,7 +34,14 @@ class OrderArticle < ActiveRecord::Base
|
|||
def price
|
||||
article_price || article
|
||||
end
|
||||
|
||||
|
||||
# latest information on available units
|
||||
def units
|
||||
return units_received unless units_received.nil?
|
||||
return units_billed unless units_billed.nil?
|
||||
units_to_order
|
||||
end
|
||||
|
||||
# Count quantities of belonging group_orders.
|
||||
# In balancing this can differ from ordered (by supplier) quantity for this article.
|
||||
def group_orders_sum
|
||||
|
|
@ -94,6 +101,18 @@ class OrderArticle < ActiveRecord::Base
|
|||
(units_to_order * price.unit_quantity) == group_orders_sum[:quantity] rescue false
|
||||
end
|
||||
|
||||
def redistribute(quantity)
|
||||
# recompute
|
||||
group_order_articles.each {|goa| goa.save_results! quantity }
|
||||
|
||||
# Update GroupOrder prices & Ordergroup stats
|
||||
# TODO only affected group_orders, and once after redistributing all articles
|
||||
order.group_orders.each(&:update_price!)
|
||||
order.ordergroups.each(&:update_stats!)
|
||||
|
||||
# TODO notifications
|
||||
end
|
||||
|
||||
# Updates order_article and belongings during balancing process
|
||||
def update_article_and_price!(order_article_attributes, article_attributes, price_attributes = nil)
|
||||
OrderArticle.transaction do
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue