Introduced group_order_article.result to save the result for each group/article.
This commit is contained in:
parent
6fd5d825f9
commit
251ced4fa1
27 changed files with 106 additions and 137 deletions
|
|
@ -34,6 +34,7 @@ class Article < ActiveRecord::Base
|
|||
has_many :article_prices, :order => "created_at"
|
||||
|
||||
named_scope :in_stock, :conditions => "quantity > 0", :order => 'suppliers.name', :include => :supplier
|
||||
named_scope :available, :conditions => {:availability => true}
|
||||
|
||||
# Validations
|
||||
validates_presence_of :name, :unit, :price, :tax, :deposit, :unit_quantity, :supplier_id, :article_category_id
|
||||
|
|
@ -170,24 +171,6 @@ class Article < ActiveRecord::Base
|
|||
nil
|
||||
end
|
||||
end
|
||||
|
||||
# Returns Articles 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]]]
|
||||
# TODO: force article to belong to a category and remove this complicated implementation!
|
||||
def self.group_by_category(articles)
|
||||
articles_by_category = {}
|
||||
ArticleCategory.find(:all).each do |category|
|
||||
articles_by_category.merge!(category.name.to_s => articles.select {|article| article.article_category and article.article_category.id == category.id })
|
||||
end
|
||||
# add articles without a category
|
||||
articles_by_category.merge!( "--" => articles.select {|article| article.article_category == nil})
|
||||
# return "clean" hash, sorted by category.name
|
||||
return articles_by_category.reject {|category, array| array.empty?}.sort
|
||||
|
||||
# it could be so easy ... but that doesn't work for empty category-ids...
|
||||
# articles.group_by {|a| a.article_category}.sort {|a, b| a[0].name <=> b[0].name}
|
||||
end
|
||||
|
||||
def update_quantity(amount)
|
||||
update_attribute :quantity, quantity + amount
|
||||
|
|
@ -203,7 +186,7 @@ class Article < ActiveRecord::Base
|
|||
# Create an ArticlePrice, when the price-attr are changed.
|
||||
def update_price_history
|
||||
if price_changed?
|
||||
article_prices.create(
|
||||
article_prices.build(
|
||||
:price => price,
|
||||
:tax => tax,
|
||||
:deposit => deposit,
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ class GroupOrderArticle < ActiveRecord::Base
|
|||
|
||||
attr_accessor :ordergroup_id # To create an new GroupOrder if neccessary
|
||||
|
||||
named_scope :ordered, :conditions => 'quantity_result > 0 OR tolerance_result > 0'
|
||||
named_scope :ordered, :conditions => 'result > 0'
|
||||
|
||||
# Updates the quantity/tolerance for this GroupOrderArticle by updating both GroupOrderArticle properties
|
||||
# and the associated GroupOrderArticleQuantities chronologically.
|
||||
|
|
@ -155,18 +155,14 @@ class GroupOrderArticle < ActiveRecord::Base
|
|||
|
||||
# Returns order result,
|
||||
# either calcualted on the fly or fetched from quantity_/tolerance_result
|
||||
def result
|
||||
if quantity_result.nil?
|
||||
calculate_result
|
||||
else
|
||||
{:quantity => quantity_result, :tolerance => tolerance_result, :total => quantity_result + tolerance_result}
|
||||
end
|
||||
# After an order is finished, there is only the result
|
||||
def result(type = :total)
|
||||
self[:result] || calculate_result[type]
|
||||
end
|
||||
|
||||
# This is used when finishing the order.
|
||||
# This is used during order.finish!.
|
||||
def save_results!
|
||||
self.quantity_result = calculate_result[:quantity]
|
||||
self.tolerance_result = calculate_result[:tolerance]
|
||||
save!
|
||||
self.update_attribute(:result, calculate_result[:total])
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -76,12 +76,18 @@ class Order < ActiveRecord::Base
|
|||
# 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 get_articles
|
||||
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] }
|
||||
end
|
||||
memoize :get_articles
|
||||
memoize :articles_grouped_by_category
|
||||
|
||||
def articles_sort_by_category
|
||||
order_articles.all(:include => [:article], :order => 'articles.name').sort do |a,b|
|
||||
a.article.article_category.name <=> b.article.article_category.name
|
||||
end
|
||||
end
|
||||
|
||||
# Returns the defecit/benefit for the foodcoop
|
||||
# Requires a valid invoice, belonging to this order
|
||||
|
|
@ -117,9 +123,9 @@ class Order < ActiveRecord::Base
|
|||
for goa in go.group_order_articles
|
||||
case type
|
||||
when :groups
|
||||
total += goa.quantity * goa.order_article.price.fc_price
|
||||
total += goa.result * goa.order_article.price.fc_price
|
||||
when :groups_without_markup
|
||||
total += goa.quantity * goa.order_article.price.gross_price
|
||||
total += goa.result * goa.order_article.price.gross_price
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -165,7 +171,7 @@ class Order < ActiveRecord::Base
|
|||
transaction do # Start updating account balances
|
||||
for group_order in gos
|
||||
price = group_order.price * -1 # decrease! account balance
|
||||
group_order.ordergroup.addFinancialTransaction(price, transaction_note, user)
|
||||
group_order.ordergroup.add_financial_transaction(price, transaction_note, user)
|
||||
end
|
||||
self.update_attributes! :state => 'closed', :updated_by => user
|
||||
end
|
||||
|
|
|
|||
|
|
@ -43,11 +43,12 @@ class OrderArticle < ActiveRecord::Base
|
|||
# Count quantities of belonging group_orders.
|
||||
# In balancing this can differ from ordered (by supplier) quantity for this article.
|
||||
def group_orders_sum
|
||||
quantity = group_order_articles.collect(&:quantity).sum
|
||||
quantity = group_order_articles.collect(&:result).sum
|
||||
{:quantity => quantity, :price => quantity * price.fc_price}
|
||||
end
|
||||
|
||||
# Update quantity/tolerance/units_to_order from group_order_articles
|
||||
# This is only used in opened orders.
|
||||
def update_results!
|
||||
quantity = group_order_articles.collect(&:quantity).sum
|
||||
tolerance = group_order_articles.collect(&:tolerance).sum
|
||||
|
|
@ -80,6 +81,10 @@ class OrderArticle < ActiveRecord::Base
|
|||
units += ((remainder > 0) && (remainder + tolerance >= unit_size) ? 1 : 0)
|
||||
end
|
||||
|
||||
def ordered_quantities_equal_to_group_orders?
|
||||
(units_to_order * price.unit_quantity) == group_orders_sum[:quantity]
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def article_and_price_exist
|
||||
|
|
|
|||
|
|
@ -65,50 +65,22 @@ class Ordergroup < Group
|
|||
|
||||
# Creates a new FinancialTransaction for this Ordergroup and updates the account_balance accordingly.
|
||||
# Throws an exception if it fails.
|
||||
def addFinancialTransaction(amount, note, user)
|
||||
def add_financial_transaction(amount, note, user)
|
||||
transaction do
|
||||
trans = FinancialTransaction.new(:ordergroup => self, :amount => amount, :note => note, :user => user)
|
||||
trans.save!
|
||||
self.account_balance += trans.amount
|
||||
self.account_updated = trans.created_on
|
||||
save!
|
||||
notifyNegativeBalance(trans)
|
||||
notify_negative_balance(trans)
|
||||
end
|
||||
end
|
||||
|
||||
# Returns all GroupOrders by this group that are currently running.
|
||||
def findCurrent
|
||||
group_orders.find(:all, :conditions => ["orders.finished = ? AND orders.starts < ? AND (orders.ends IS NULL OR orders.ends > ?)", false, Time.now, Time.now], :include => :order)
|
||||
end
|
||||
|
||||
#find expired (lapsed) but not manually finished orders
|
||||
def findExpiredOrders
|
||||
group_orders.find(:all, :conditions => ["orders.ends < ?", Time.now], :include => :order, :order => 'orders.ends DESC')
|
||||
end
|
||||
|
||||
# Returns all GroupOrderResults by this group that are finished but not booked yet.
|
||||
def findFinishedNotBooked
|
||||
GroupOrderResult.find(:all,
|
||||
:conditions => ["group_order_results.group_name = ? AND group_order_results.order_id = orders.id AND orders.finished = ? AND orders.booked = ? ", self.name, true, false],
|
||||
:include => :order,
|
||||
:order => 'orders.ends DESC')
|
||||
end
|
||||
|
||||
# Returns all GroupOrderResults for booked orders
|
||||
def findBookedOrders(limit = false, offset = 0)
|
||||
GroupOrderResult.find(:all,
|
||||
:conditions => ["group_order_results.group_name = ? AND group_order_results.order_id = orders.id AND orders.finished = ? AND orders.booked = ? ", self.name, true, true],
|
||||
:include => :order,
|
||||
:order => "orders.ends DESC",
|
||||
:limit => limit,
|
||||
:offset => offset)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
private
|
||||
|
||||
# If this order group's account balance is made negative by the given/last transaction,
|
||||
# a message is sent to all users who have enabled notification.
|
||||
def notifyNegativeBalance(transaction)
|
||||
def notify_negative_balance(transaction)
|
||||
# Notify only when order group had a positive balance before the last transaction:
|
||||
if (transaction.amount < 0 && self.account_balance < 0 && self.account_balance - transaction.amount >= 0)
|
||||
users = self.users.reject { |u| u.settings["notify.negativeBalance"] != '1' }
|
||||
|
|
|
|||
|
|
@ -24,7 +24,8 @@
|
|||
class Supplier < ActiveRecord::Base
|
||||
acts_as_paranoid # Avoid deleting the supplier for consistency of order-results
|
||||
|
||||
has_many :articles, :dependent => :destroy
|
||||
has_many :articles, :dependent => :destroy,
|
||||
:include => [:article_category], :order => 'article_categories.name, articles.name'
|
||||
has_many :orders
|
||||
has_many :deliveries
|
||||
has_many :invoices
|
||||
|
|
@ -40,10 +41,9 @@ class Supplier < ActiveRecord::Base
|
|||
# for the sharedLists-App
|
||||
belongs_to :shared_supplier
|
||||
|
||||
# Returns all articles for this supplier that are available and have a valid price, grouped by article category and ordered by name.
|
||||
def getArticlesAvailableForOrdering
|
||||
articles = Article.find(:all, :conditions => ['supplier_id = ? AND availability = ?', self.id, true], :order => 'article_categories.name, articles.name', :include => :article_category)
|
||||
articles.select {|article| article.fc_price}
|
||||
# Returns all articles for this supplier that are available, grouped by article category and ordered by name.
|
||||
def get_articles_for_ordering
|
||||
articles.available.all.group_by { |a| a.article_category.name }
|
||||
end
|
||||
|
||||
# sync all articles with the external database
|
||||
|
|
@ -52,7 +52,7 @@ class Supplier < ActiveRecord::Base
|
|||
def sync_all
|
||||
updated_articles = Array.new
|
||||
outlisted_articles = Array.new
|
||||
for article in articles.find(:all, :order => "article_categories.name", :include => :article_category)
|
||||
for article in articles
|
||||
# try to find the associated shared_article
|
||||
shared_article = article.shared_article
|
||||
if shared_article
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue