Ordering refactored: Made everything RESTful.
This commit is contained in:
parent
45e0048490
commit
eb4705857b
19 changed files with 340 additions and 222 deletions
|
|
@ -1,6 +1,8 @@
|
|||
# A GroupOrder represents an Order placed by an Ordergroup.
|
||||
class GroupOrder < ActiveRecord::Base
|
||||
|
||||
|
||||
attr_accessor :group_order_articles_attributes
|
||||
|
||||
belongs_to :order
|
||||
belongs_to :ordergroup
|
||||
has_many :group_order_articles, :dependent => :destroy
|
||||
|
|
@ -14,27 +16,74 @@ class GroupOrder < ActiveRecord::Base
|
|||
|
||||
scope :open, lambda { {:conditions => ["order_id IN (?)", Order.open.collect(&:id)]} }
|
||||
scope :finished, lambda { {:conditions => ["order_id IN (?)", Order.finished_not_closed.collect(&:id)]} }
|
||||
|
||||
# Updates the "price" attribute.
|
||||
# Until the order is finished this will be the maximum price or
|
||||
# the minimum price depending on configuration. When the order is finished it
|
||||
# will be the value depending of the article results.
|
||||
def update_price!
|
||||
total = 0
|
||||
for article in group_order_articles.find(:all, :include => :order_article)
|
||||
unless order.finished?
|
||||
if Foodsoft.config[:tolerance_is_costly]
|
||||
total += article.order_article.article.fc_price * (article.quantity + article.tolerance)
|
||||
else
|
||||
total += article.order_article.article.fc_price * article.quantity
|
||||
end
|
||||
else
|
||||
total += article.order_article.price.fc_price * article.result
|
||||
|
||||
# Generate some data for the javascript methods in ordering view
|
||||
def load_data
|
||||
data = {}
|
||||
data[:available_funds] = ordergroup.get_available_funds(self)
|
||||
|
||||
unless new_record?
|
||||
# Group has already ordered, so get the results...
|
||||
goas = {}
|
||||
group_order_articles.all.each do |goa|
|
||||
goas[goa.order_article_id] = {:quantity => goa.quantity,
|
||||
:tolerance => goa.tolerance,
|
||||
:quantity_result => goa.result(:quantity),
|
||||
:tolerance_result => goa.result(:tolerance)}
|
||||
end
|
||||
end
|
||||
|
||||
# load prices ....
|
||||
data[:order_articles] = {}
|
||||
order.order_articles.each do |order_article|
|
||||
data[:order_articles][order_article.id] = {
|
||||
:price => order_article.article.fc_price,
|
||||
:unit => order_article.article.unit_quantity,
|
||||
:quantity => (new_record? ? 0 : goas[order_article.id][:quantity]),
|
||||
:others_quantity => order_article.quantity - (new_record? ? 0 : goas[order_article.id][:quantity]),
|
||||
:used_quantity => (new_record? ? 0 : goas[order_article.id][:quantity_result]),
|
||||
:tolerance => (new_record? ? 0 : goas[order_article.id][:tolerance]),
|
||||
:others_tolerance => order_article.tolerance - (new_record? ? 0 : goas[order_article.id][:tolerance]),
|
||||
:used_tolerance => (new_record? ? 0 : goas[order_article.id][:tolerance_result])
|
||||
}
|
||||
end
|
||||
|
||||
data
|
||||
end
|
||||
|
||||
def save_group_order_articles
|
||||
for order_article in order.order_articles
|
||||
# Find the group_order_article, create a new one if necessary...
|
||||
group_order_article = group_order_articles.find_or_create_by_order_article_id(order_article.id)
|
||||
|
||||
# Get ordered quantities and update group_order_articles/_quantities...
|
||||
quantities = group_order_articles_attributes.fetch(order_article.id.to_s, {:quantity => 0, :tolerance => 0})
|
||||
group_order_article.update_quantities(quantities[:quantity].to_i, quantities[:tolerance].to_i)
|
||||
|
||||
# Also update results for the order_article
|
||||
logger.debug "[save_group_order_articles] update order_article.results!"
|
||||
order_article.update_results!
|
||||
end
|
||||
|
||||
# set attributes to nil to avoid and infinite loop of
|
||||
end
|
||||
|
||||
# Updates the "price" attribute.
|
||||
def update_price!
|
||||
total = group_order_articles.includes(:order_article => :article).all.map(&:total_price).sum
|
||||
update_attribute(:price, total)
|
||||
end
|
||||
|
||||
|
||||
# Save GroupOrder and updates group_order_articles/quantities accordingly
|
||||
def save_ordering!
|
||||
transaction do
|
||||
save!
|
||||
save_group_order_articles
|
||||
update_price!
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# == Schema Information
|
||||
|
|
|
|||
|
|
@ -14,15 +14,10 @@ class GroupOrderArticle < ActiveRecord::Base
|
|||
validates_inclusion_of :tolerance, :in => 0..99
|
||||
validates_uniqueness_of :order_article_id, :scope => :group_order_id # just once an article per group order
|
||||
|
||||
attr_accessor :ordergroup_id # To create an new GroupOrder if neccessary
|
||||
|
||||
scope :ordered, :conditions => 'result > 0'
|
||||
|
||||
# Custom attribute setter that accepts decimal numbers using localized decimal separator.
|
||||
def result=(result)
|
||||
self[:result] = String.delocalized_decimal(result)
|
||||
end
|
||||
|
||||
localize_input_of :result
|
||||
|
||||
# Updates the quantity/tolerance for this GroupOrderArticle by updating both GroupOrderArticle properties
|
||||
# and the associated GroupOrderArticleQuantities chronologically.
|
||||
#
|
||||
|
|
@ -30,17 +25,17 @@ class GroupOrderArticle < ActiveRecord::Base
|
|||
def update_quantities(quantity, tolerance)
|
||||
logger.debug("GroupOrderArticle[#{id}].update_quantities(#{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)
|
||||
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
|
||||
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))
|
||||
|
|
@ -50,31 +45,31 @@ class GroupOrderArticle < ActiveRecord::Base
|
|||
delta = (delta > quantities[i].quantity ? quantities[i].quantity : delta)
|
||||
logger.debug("Decreasing quantity by #{delta}")
|
||||
quantities[i].quantity -= delta
|
||||
self.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
|
||||
self.tolerance -= delta
|
||||
end
|
||||
i += 1
|
||||
end
|
||||
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)
|
||||
: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
|
||||
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!'
|
||||
|
|
@ -82,7 +77,7 @@ class GroupOrderArticle < ActiveRecord::Base
|
|||
|
||||
# Remove zero-only items.
|
||||
quantities = quantities.reject { | q | q.quantity == 0 && q.tolerance == 0}
|
||||
|
||||
|
||||
# Save
|
||||
transaction do
|
||||
quantities.each { | i | i.save! }
|
||||
|
|
@ -90,7 +85,7 @@ class GroupOrderArticle < ActiveRecord::Base
|
|||
save!
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# Determines how many items of this article the Ordergroup receives.
|
||||
# Returns a hash with three keys: :quantity / :tolerance / :total
|
||||
#
|
||||
|
|
@ -102,15 +97,15 @@ class GroupOrderArticle < ActiveRecord::Base
|
|||
# Get total
|
||||
total = stockit ? order_article.article.quantity : order_article.units_to_order * order_article.price.unit_quantity
|
||||
logger.debug("<#{order_article.article.name}>.unitsToOrder => items ordered: #{order_article.units_to_order} => #{total}")
|
||||
|
||||
|
||||
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')
|
||||
: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...
|
||||
total_quantity = i = 0
|
||||
while (i < order_quantities.size && total_quantity < total)
|
||||
|
|
@ -137,10 +132,10 @@ class GroupOrderArticle < ActiveRecord::Base
|
|||
i += 1
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
logger.debug("determined quantity/tolerance/total: #{quantity} / #{tolerance} / #{quantity + tolerance}")
|
||||
end
|
||||
|
||||
|
||||
{:quantity => quantity, :tolerance => tolerance, :total => quantity + tolerance}
|
||||
end
|
||||
memoize :calculate_result
|
||||
|
|
@ -156,7 +151,23 @@ class GroupOrderArticle < ActiveRecord::Base
|
|||
def save_results!
|
||||
self.update_attribute(:result, calculate_result[:total])
|
||||
end
|
||||
|
||||
|
||||
# Returns total price for this individual article
|
||||
# Until the order is finished this will be the maximum price or
|
||||
# the minimum price depending on configuration. When the order is finished it
|
||||
# will be the value depending of the article results.
|
||||
def total_price
|
||||
unless order_article.order.finished?
|
||||
if Foodsoft.config[:tolerance_is_costly]
|
||||
order_article.article.fc_price * (quantity + tolerance)
|
||||
else
|
||||
order_article.article.fc_price * quantity
|
||||
end
|
||||
else
|
||||
order_article.price.fc_price * result
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -85,16 +85,16 @@ class Order < ActiveRecord::Base
|
|||
|
||||
# search GroupOrder of given Ordergroup
|
||||
def group_order(ordergroup)
|
||||
group_orders.first :conditions => { :ordergroup_id => ordergroup.id }
|
||||
group_orders.where(:ordergroup_id => ordergroup.id).first
|
||||
end
|
||||
|
||||
# Returns OrderArticles in a nested Array, grouped by category and ordered by article name.
|
||||
# The array has the following form:
|
||||
# e.g: [["drugs",[teethpaste, toiletpaper]], ["fruits" => [apple, banana, lemon]]]
|
||||
def articles_grouped_by_category
|
||||
order_articles.all(:include => [:article, :article_price], :order => 'articles.name').group_by { |a|
|
||||
a.article.article_category.name
|
||||
}.sort { |a, b| a[0] <=> b[0] }
|
||||
order_articles.includes(:article, :article_price).order('articles.name').
|
||||
group_by { |a| a.article.article_category.name }.
|
||||
sort { |a, b| a[0] <=> b[0] }
|
||||
end
|
||||
memoize :articles_grouped_by_category
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue