Second part of stock-integration.

Introduced StockArticle and a special page for ordering from stock. StockChanges will be created and the StockArticle.quantity
updated in 'order.close!'.
This commit is contained in:
Benjamin Meichsner 2009-02-06 16:26:35 +01:00
parent 1912a3fd80
commit c17b63b192
37 changed files with 616 additions and 340 deletions

View file

@ -22,6 +22,7 @@
# updated_at :datetime
# quantity :decimal(, ) default(0.0)
# deleted_at :datetime
# type :string(255)
#
class Article < ActiveRecord::Base
@ -32,9 +33,7 @@ class Article < ActiveRecord::Base
belongs_to :supplier
belongs_to :article_category
has_many :article_prices, :order => "created_at"
has_many :stock_changes
named_scope :in_stock, :conditions => "quantity > 0", :order => 'suppliers.name', :include => :supplier
named_scope :available, :conditions => {:availability => true}
# Validations
@ -173,11 +172,6 @@ class Article < ActiveRecord::Base
end
end
# Update the quantity of items in stock
def update_quantity!
update_attribute :quantity, stock_changes.collect(&:quantity).sum
end
protected
# Checks if the article is in use before it will deleted

View file

@ -13,7 +13,7 @@ class Delivery < ActiveRecord::Base
belongs_to :supplier
has_one :invoice
has_many :stock_changes
has_many :stock_changes, :dependent => :destroy
named_scope :recent, :order => 'created_at DESC', :limit => 10

View file

@ -9,8 +9,7 @@
# quantity :integer default(0), not null
# tolerance :integer default(0), not null
# updated_on :datetime not null
# quantity_result :integer
# tolerance_result :integer
# result :integer
#
# A GroupOrderArticle stores the sum of how many items of an OrderArticle are ordered as part of a GroupOrder.
@ -106,9 +105,10 @@ class GroupOrderArticle < ActiveRecord::Base
# See description of the ordering algorithm in the general application documentation for details.
def calculate_result
quantity = tolerance = 0
stockit = order_article.article.is_a?(StockArticle)
# Get total
total = order_article.units_to_order * order_article.price.unit_quantity
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)
@ -130,7 +130,7 @@ class GroupOrderArticle < ActiveRecord::Base
end
i += 1
end
# Determine tolerance to be ordered...
if (total_quantity < total)
logger.debug("determining additional items to be ordered from tolerance")
@ -143,7 +143,7 @@ class GroupOrderArticle < ActiveRecord::Base
tolerance += q
end
i += 1
end
end
end
logger.debug("determined quantity/tolerance/total: #{quantity} / #{tolerance} / #{quantity + tolerance}")

View file

@ -24,6 +24,7 @@ class Order < ActiveRecord::Base
has_many :ordergroups, :through => :group_orders
has_one :invoice
has_many :comments, :class_name => "OrderComment", :order => "created_at"
has_many :stock_changes
belongs_to :supplier
belongs_to :updated_by, :class_name => "User", :foreign_key => "updated_by_user_id"
@ -51,8 +52,10 @@ class Order < ActiveRecord::Base
def articles_for_ordering
if stockit?
Article.in_stock.all(:include => :article_category,
:order => 'article_categories.name, articles.name').group_by { |a| a.article_category.name }
StockArticle.available.all(:include => :article_category,
:order => 'article_categories.name, articles.name').reject{ |a|
a.quantity_available == 0
}.group_by { |a| a.article_category.name }
else
supplier.articles.available.all.group_by { |a| a.article_category.name }
end
@ -95,7 +98,7 @@ class Order < ActiveRecord::Base
def group_order(ordergroup)
group_orders.first :conditions => { :ordergroup_id => ordergroup.id }
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]]]
@ -196,6 +199,14 @@ class Order < ActiveRecord::Base
price = group_order.price * -1 # decrease! account balance
group_order.ordergroup.add_financial_transaction(price, transaction_note, user)
end
if stockit? # Decreases the quantity of stock_articles
for oa in order_articles.all(:include => :article)
oa.update_results! # Update units_to_order of order_article
stock_changes.create! :stock_article => oa.article, :quantity => oa.units_to_order*-1
end
end
self.update_attributes! :state => 'closed', :updated_by => user
end
end

View file

@ -48,12 +48,15 @@ class OrderArticle < ActiveRecord::Base
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
update_attributes(:quantity => quantity, :tolerance => tolerance,
:units_to_order => calculate_units_to_order(quantity, tolerance))
if order.open?
quantity = group_order_articles.collect(&:quantity).sum
tolerance = group_order_articles.collect(&:tolerance).sum
update_attributes(:quantity => quantity, :tolerance => tolerance,
:units_to_order => calculate_units_to_order(quantity, tolerance))
elsif order.finished?
update_attribute(:units_to_order, group_order_articles.collect(&:result).sum)
end
end
# Returns how many units of the belonging article need to be ordered given the specified order quantity and tolerance.

View file

@ -0,0 +1,49 @@
# == Schema Information
# Schema version: 20090120184410
#
# Table name: articles
#
# id :integer not null, primary key
# name :string(255) default(""), not null
# supplier_id :integer default(0), not null
# article_category_id :integer default(0), not null
# unit :string(255) default(""), not null
# note :string(255)
# availability :boolean default(TRUE), not null
# manufacturer :string(255)
# origin :string(255)
# shared_updated_on :datetime
# price :decimal(, )
# tax :float
# deposit :decimal(, ) default(0.0)
# unit_quantity :integer default(1), not null
# order_number :string(255)
# created_at :datetime
# updated_at :datetime
# quantity :decimal(, ) default(0.0)
# deleted_at :datetime
# type :string(255)
#
class StockArticle < Article
has_many :stock_changes
named_scope :available, :conditions => "quantity > 0"
# Update the quantity of items in stock
def update_quantity!
update_attribute :quantity, stock_changes.collect(&:quantity).sum
end
# Check for unclosed orders and substract its ordered quantity
def quantity_available(exclude_order = nil)
available = quantity
for order in Order.stockit.all(:conditions => "state = 'open' OR state = 'finished'")
unless order == exclude_order
order_article = order.order_articles.first(:conditions => {:article_id => id})
available -= order_article.units_to_order if order_article
end
end
available
end
end

View file

@ -1,22 +1,22 @@
# == Schema Information
# Schema version: 20090119155930
# Schema version: 20090120184410
#
# Table name: stock_changes
#
# id :integer not null, primary key
# delivery_id :integer
# order_id :integer
# article_id :integer
# quantity :decimal(6, 2) default(0.0)
# created_at :datetime
# id :integer not null, primary key
# delivery_id :integer
# order_id :integer
# stock_article_id :integer
# quantity :decimal(, ) default(0.0)
# created_at :datetime
#
class StockChange < ActiveRecord::Base
belongs_to :delivery
belongs_to :order
belongs_to :article
belongs_to :stock_article
validates_presence_of :article_id, :quantity
validates_presence_of :stock_article_id, :quantity
validates_numericality_of :quantity
after_save :update_article_quantity
@ -25,6 +25,6 @@ class StockChange < ActiveRecord::Base
protected
def update_article_quantity
article.update_quantity!
stock_article.update_quantity!
end
end

View file

@ -26,6 +26,7 @@ class Supplier < ActiveRecord::Base
has_many :articles, :dependent => :destroy,
:include => [:article_category], :order => 'article_categories.name, articles.name'
has_many :stock_articles
has_many :orders
has_many :deliveries
has_many :invoices