Order-refactoring part II.
This commit is contained in:
parent
f7b9582261
commit
6fd5d825f9
27 changed files with 228 additions and 231 deletions
|
@ -53,7 +53,7 @@ class ApplicationController < ActionController::Base
|
|||
|
||||
def deny_access
|
||||
self.return_to = request.request_uri
|
||||
redirect_to :controller => 'login', :action => 'denied'
|
||||
redirect_to :controller => '/login', :action => 'denied'
|
||||
return false
|
||||
end
|
||||
|
||||
|
|
|
@ -4,9 +4,6 @@ class HomeController < ApplicationController
|
|||
def index
|
||||
@currentOrders = Order.open
|
||||
@ordergroup = @current_user.ordergroup
|
||||
if @ordergroup
|
||||
@financial_transactions = @ordergroup.financial_transactions.find(:all, :order => 'created_on desc', :limit => 3)
|
||||
end
|
||||
# unaccepted tasks
|
||||
@unaccepted_tasks = @current_user.unaccepted_tasks
|
||||
# task in next week
|
||||
|
|
|
@ -5,7 +5,7 @@ class OrderingController < ApplicationController
|
|||
before_filter :ensure_ordergroup_member
|
||||
before_filter :ensure_open_order, :only => [:order, :saveOrder]
|
||||
|
||||
verify :method => :post, :only => [:saveOrder], :redirect_to => { :action => :index }
|
||||
verify :method => :post, :only => [:saveOrder], :redirect_to => {:action => :index}
|
||||
|
||||
# Index page.
|
||||
def index
|
||||
|
@ -23,8 +23,8 @@ class OrderingController < ApplicationController
|
|||
if @group_order
|
||||
# Group has already ordered, so get the results...
|
||||
for article in @group_order.group_order_articles
|
||||
result = article.orderResult
|
||||
ordered_articles[article.order_article_id] = { 'quantity' => article.quantity,
|
||||
result = article.result
|
||||
ordered_articles[article.order_article_id] = {'quantity' => article.quantity,
|
||||
'tolerance' => article.tolerance,
|
||||
'quantity_result' => result[:quantity],
|
||||
'tolerance_result' => result[:tolerance]}
|
||||
|
@ -61,53 +61,53 @@ class OrderingController < ApplicationController
|
|||
|
||||
# Update changes to a current order.
|
||||
def saveOrder
|
||||
order = @order # Get the object through before_filter
|
||||
if (params[:total_balance].to_i < 0)
|
||||
if (params[:total_balance].to_i < 0) #TODO: Better use a real test on sufficiant funds
|
||||
flash[:error] = 'Der Bestellwert übersteigt das verfügbare Guthaben.'
|
||||
redirect_to :action => 'order'
|
||||
elsif (ordered = params[:ordered])
|
||||
begin
|
||||
Order.transaction do
|
||||
# Create group order if necessary...
|
||||
if (groupOrder = order.group_orders.find(:first, :conditions => "ordergroup_id = #{@ordergroup.id}", :include => [:group_order_articles]))
|
||||
if (params[:version].to_i != groupOrder.lock_version) # check for conflicts well ahead
|
||||
raise ActiveRecord::StaleObjectError
|
||||
end
|
||||
else
|
||||
groupOrder = GroupOrder.new(:ordergroup => @ordergroup, :order => order, :updated_by => @current_user, :price => 0)
|
||||
groupOrder.save!
|
||||
end
|
||||
# Create/update GroupOrderArticles...
|
||||
newGroupOrderArticles = Array.new
|
||||
for article in order.order_articles
|
||||
# Find the GroupOrderArticle, create a new one if necessary...
|
||||
groupOrderArticles = groupOrder.group_order_articles.select{ |v| v.order_article_id == article.id }
|
||||
unless (groupOrderArticle = groupOrderArticles[0])
|
||||
groupOrderArticle = GroupOrderArticle.create(:group_order => groupOrder, :order_article_id => article.id, :quantity => 0, :tolerance => 0)
|
||||
end
|
||||
# Get ordered quantities and update GroupOrderArticle/-Quantities...
|
||||
unless (quantities = ordered.delete(article.id.to_s)) && (quantity = quantities['quantity']) && (tolerance = quantities['tolerance'])
|
||||
quantity = tolerance = 0
|
||||
end
|
||||
groupOrderArticle.update_quantities(quantity.to_i, tolerance.to_i)
|
||||
# Add to new list of GroupOrderArticles:
|
||||
newGroupOrderArticles.push(groupOrderArticle)
|
||||
end
|
||||
groupOrder.group_order_articles = newGroupOrderArticles
|
||||
groupOrder.update_price!
|
||||
groupOrder.updated_by = @current_user
|
||||
groupOrder.save!
|
||||
order.update_quantities
|
||||
order.save!
|
||||
end
|
||||
flash[:notice] = 'Die Bestellung wurde gespeichert.'
|
||||
rescue ActiveRecord::StaleObjectError
|
||||
flash[:error] = 'In der Zwischenzeit hat jemand anderes auch bestellt, daher konnte die Bestellung nicht aktualisiert werden.'
|
||||
rescue => exception
|
||||
logger.error('Failed to update order: ' + exception.message)
|
||||
flash[:error] = 'Die Bestellung konnte nicht aktualisiert werden, da ein Fehler auftrat.'
|
||||
end
|
||||
redirect_to :action => 'my_order_result', :id => order
|
||||
begin
|
||||
Order.transaction do
|
||||
# Try to find group_order
|
||||
group_order = @order.group_orders.first :conditions => "ordergroup_id = #{@ordergroup.id}",
|
||||
:include => [:group_order_articles]
|
||||
# Create group order if necessary...
|
||||
unless group_order.nil?
|
||||
# check for conflicts well ahead
|
||||
if (params[:version].to_i != group_order.lock_version)
|
||||
raise ActiveRecord::StaleObjectError
|
||||
end
|
||||
else
|
||||
group_order = @ordergroup.group_orders.create!(:order => @order, :updated_by => @current_user, :price => 0)
|
||||
end
|
||||
|
||||
# Create/update 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.group_order_articles.detect { |v| v.order_article_id == order_article.id }
|
||||
if group_order_article.nil?
|
||||
group_order_article = group_order.group_order_articles.create(:order_article_id => order_article.id)
|
||||
end
|
||||
|
||||
# Get ordered quantities and update group_order_articles/_quantities...
|
||||
quantities = ordered.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
|
||||
order_article.update_results!
|
||||
end
|
||||
|
||||
group_order.update_price!
|
||||
group_order.update_attribute(:updated_by, @current_user)
|
||||
end
|
||||
flash[:notice] = 'Die Bestellung wurde gespeichert.'
|
||||
rescue ActiveRecord::StaleObjectError
|
||||
flash[:error] = 'In der Zwischenzeit hat jemand anderes auch bestellt, daher konnte die Bestellung nicht aktualisiert werden.'
|
||||
rescue => exception
|
||||
logger.error('Failed to update order: ' + exception.message)
|
||||
flash[:error] = 'Die Bestellung konnte nicht aktualisiert werden, da ein Fehler auftrat.'
|
||||
end
|
||||
redirect_to :action => 'my_order_result', :id => @order
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -138,7 +138,7 @@ class OrdersController < ApplicationController
|
|||
text += "****** " + "Artikel" + "\n\n"
|
||||
text += "Nummer" + " " + "Menge" + " " + "Name" + "\n"
|
||||
# now display all ordered articles
|
||||
order.order_articles.all(:include => [:article, :article_price]).each do |oa|
|
||||
order.order_articles.ordered.all(:include => [:article, :article_price]).each do |oa|
|
||||
number = oa.article.order_number
|
||||
(8 - number.size).times { number += " " }
|
||||
quantity = oa.units_to_order.to_i.to_s
|
||||
|
|
|
@ -76,34 +76,9 @@ class Article < ActiveRecord::Base
|
|||
updated_at > 2.days.ago
|
||||
end
|
||||
|
||||
# Returns how many units of this article need to be ordered given the specified order quantity and tolerance.
|
||||
# This is determined by calculating how many units can be ordered from the given order quantity, using
|
||||
# the tolerance to order an additional unit if the order quantity is not quiet sufficient.
|
||||
# There must always be at least one item in a unit that is an ordered quantity (no units are ever entirely
|
||||
# filled by tolerance items only).
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# unit_quantity | quantity | tolerance | calculate_order_quantity
|
||||
# --------------+----------+-----------+-----------------------
|
||||
# 4 | 0 | 2 | 0
|
||||
# 4 | 0 | 5 | 0
|
||||
# 4 | 2 | 2 | 1
|
||||
# 4 | 4 | 2 | 1
|
||||
# 4 | 4 | 4 | 1
|
||||
# 4 | 5 | 3 | 2
|
||||
# 4 | 5 | 4 | 2
|
||||
#
|
||||
def calculate_order_quantity(quantity, tolerance = 0)
|
||||
unit_size = unit_quantity
|
||||
units = quantity / unit_size
|
||||
remainder = quantity % unit_size
|
||||
units += ((remainder > 0) && (remainder + tolerance >= unit_size) ? 1 : 0)
|
||||
end
|
||||
|
||||
# If the article is used in an open Order, the Order will be returned.
|
||||
def in_open_order
|
||||
order_articles = OrderArticle.all(:conditions => ['order_id IN (?)', Order.open.collect {|o| o.id }])
|
||||
order_articles = OrderArticle.all(:conditions => ['order_id IN (?)', Order.open.collect(&:id)])
|
||||
order_article = order_articles.detect {|oa| oa.article_id == id }
|
||||
order_article ? order_article.order : nil
|
||||
end
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# == Schema Information
|
||||
# Schema version: 20090119155930
|
||||
# Schema version: 20090120184410
|
||||
#
|
||||
# Table name: group_order_articles
|
||||
#
|
||||
|
@ -9,12 +9,15 @@
|
|||
# quantity :integer default(0), not null
|
||||
# tolerance :integer default(0), not null
|
||||
# updated_on :datetime not null
|
||||
# quantity_result :integer
|
||||
# tolerance_result :integer
|
||||
#
|
||||
|
||||
# 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
|
||||
extend ActiveSupport::Memoizable # Ability to cache method results. Use memoize :expensive_method
|
||||
|
||||
belongs_to :group_order
|
||||
belongs_to :order_article
|
||||
|
@ -27,6 +30,8 @@ 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'
|
||||
|
||||
# Updates the quantity/tolerance for this GroupOrderArticle by updating both GroupOrderArticle properties
|
||||
# and the associated GroupOrderArticleQuantities chronologically.
|
||||
#
|
||||
|
@ -99,25 +104,27 @@ 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 orderResult
|
||||
def calculate_result
|
||||
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}")
|
||||
total = 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...
|
||||
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}")
|
||||
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...
|
||||
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)
|
||||
total_quantity = i = 0
|
||||
while (i < order_quantities.size && total_quantity < total)
|
||||
q = (order_quantities[i].quantity <= total - total_quantity ? order_quantities[i].quantity : total - total_quantity)
|
||||
total_quantity += q
|
||||
if (order_quantities[i].group_order_article_id == self.id)
|
||||
logger.debug("increasing quantity by #{q}")
|
||||
quantity += q
|
||||
end
|
||||
|
@ -125,13 +132,13 @@ class GroupOrderArticle < ActiveRecord::Base
|
|||
end
|
||||
|
||||
# Determine tolerance to be ordered...
|
||||
if (totalQuantity < total)
|
||||
if (total_quantity < 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)
|
||||
while (i < order_quantities.size && total_quantity < total)
|
||||
q = (order_quantities[i].tolerance <= total - total_quantity ? order_quantities[i].tolerance : total - total_quantity)
|
||||
total_quantity += q
|
||||
if (order_quantities[i].group_order_article_id == self.id)
|
||||
logger.debug("increasing tolerance by #{q}")
|
||||
tolerance += q
|
||||
end
|
||||
|
@ -139,13 +146,27 @@ class GroupOrderArticle < ActiveRecord::Base
|
|||
end
|
||||
end
|
||||
|
||||
# calculate the sum of quantity and tolerance:
|
||||
sum = quantity + tolerance
|
||||
|
||||
logger.debug("determined quantity/tolerance/total: #{quantity} / #{tolerance} / #{sum}")
|
||||
logger.debug("determined quantity/tolerance/total: #{quantity} / #{tolerance} / #{quantity + tolerance}")
|
||||
end
|
||||
|
||||
{:quantity => quantity, :tolerance => tolerance, :total => sum}
|
||||
{:quantity => quantity, :tolerance => tolerance, :total => quantity + tolerance}
|
||||
end
|
||||
memoize :calculate_result
|
||||
|
||||
# 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
|
||||
end
|
||||
|
||||
# This is used when finishing the order.
|
||||
def save_results!
|
||||
self.quantity_result = calculate_result[:quantity]
|
||||
self.tolerance_result = calculate_result[:tolerance]
|
||||
save!
|
||||
end
|
||||
end
|
||||
|
|
|
@ -100,11 +100,11 @@ class Order < ActiveRecord::Base
|
|||
# :fc, guess what...
|
||||
def sum(type = :gross)
|
||||
total = 0
|
||||
if type == :clear || type == :gross || type == :fc
|
||||
if type == :net || type == :gross || type == :fc
|
||||
for oa in order_articles.ordered.all(:include => [:article,:article_price])
|
||||
quantity = oa.units_to_order * oa.price.unit_quantity
|
||||
case type
|
||||
when :clear
|
||||
when :net
|
||||
total += quantity * oa.price.price
|
||||
when :gross
|
||||
total += quantity * oa.price.gross_price
|
||||
|
@ -133,14 +133,20 @@ class Order < ActiveRecord::Base
|
|||
unless finished?
|
||||
Order.transaction do
|
||||
# Update order_articles. Save the current article_price to keep price consistency
|
||||
# Also save results for each group_order_result
|
||||
order_articles.all(:include => :article).each do |oa|
|
||||
oa.update_attribute(:article_price, oa.article.article_prices.first)
|
||||
oa.group_order_articles.each { |goa| goa.save_results! }
|
||||
end
|
||||
# set new order state (needed by notify_order_finished)
|
||||
update_attributes(:state => 'finished', :ends => Time.now, :updated_by => user)
|
||||
|
||||
# TODO: delete data, which is no longer required ...
|
||||
# group_order_article_quantities... order_articles with units_to_order == 0 ? ...
|
||||
# Clean up
|
||||
# Delete no longer required order-history (group_order_article_quantities) and
|
||||
# TODO: Do we need articles, which aren't ordered? (units_to_order == 0 ?)
|
||||
order_articles.each do |oa|
|
||||
oa.group_order_articles.each { |goa| goa.group_order_article_quantities.clear }
|
||||
end
|
||||
end
|
||||
|
||||
# notify order groups
|
||||
|
@ -148,37 +154,6 @@ class Order < ActiveRecord::Base
|
|||
end
|
||||
end
|
||||
|
||||
# TODO: I can't understand, why its going out from the group_order_articles perspective.
|
||||
# Why we can't just iterate through the order_articles?
|
||||
#
|
||||
# Updates the ordered quantites of all OrderArticles from the GroupOrderArticles.
|
||||
# This method is fired after an ordergroup has saved/updated his order.
|
||||
def update_quantities
|
||||
indexed_order_articles = {} # holds the list of updated OrderArticles indexed by their id
|
||||
# Get all GroupOrderArticles for this order and update OrderArticle.quantity/.tolerance/.units_to_order from them...
|
||||
group_order_articles = GroupOrderArticle.all(:conditions => ['group_order_id IN (?)', group_order_ids],
|
||||
:include => [:order_article])
|
||||
for goa in group_order_articles
|
||||
if (order_article = indexed_order_articles[goa.order_article.id.to_s])
|
||||
# order_article has already been fetched, just update...
|
||||
order_article.quantity = order_article.quantity + goa.quantity
|
||||
order_article.tolerance = order_article.tolerance + goa.tolerance
|
||||
order_article.units_to_order = order_article.article.calculate_order_quantity(order_article.quantity, order_article.tolerance)
|
||||
else
|
||||
# First update to OrderArticle, need to store in orderArticle hash...
|
||||
order_article = goa.order_article
|
||||
order_article.quantity = goa.quantity
|
||||
order_article.tolerance = goa.tolerance
|
||||
order_article.units_to_order = order_article.article.calculate_order_quantity(order_article.quantity, order_article.tolerance)
|
||||
indexed_order_articles[order_article.id.to_s] = order_article
|
||||
end
|
||||
end
|
||||
# Commit changes to database...
|
||||
OrderArticle.transaction do
|
||||
indexed_order_articles.each_value { | value | value.save! }
|
||||
end
|
||||
end
|
||||
|
||||
# Sets order.status to 'close' and updates all Ordergroup.account_balances
|
||||
def close!(user)
|
||||
raise "Bestellung wurde schon abgerechnet" if closed?
|
||||
|
|
|
@ -34,8 +34,8 @@ class OrderArticle < ActiveRecord::Base
|
|||
#
|
||||
# before_validation_on_create :create_new_article
|
||||
|
||||
# This method returns either the Article or the ArticlePrice
|
||||
# The latter will be set, when the the order is finished
|
||||
# This method returns either the ArticlePrice or the Article
|
||||
# The first will be set, when the the order is finished
|
||||
def price
|
||||
article_price || article
|
||||
end
|
||||
|
@ -47,6 +47,39 @@ class OrderArticle < ActiveRecord::Base
|
|||
{:quantity => quantity, :price => quantity * price.fc_price}
|
||||
end
|
||||
|
||||
# Update quantity/tolerance/units_to_order from group_order_articles
|
||||
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))
|
||||
end
|
||||
|
||||
# Returns how many units of the belonging article need to be ordered given the specified order quantity and tolerance.
|
||||
# This is determined by calculating how many units can be ordered from the given order quantity, using
|
||||
# the tolerance to order an additional unit if the order quantity is not quiet sufficient.
|
||||
# There must always be at least one item in a unit that is an ordered quantity (no units are ever entirely
|
||||
# filled by tolerance items only).
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# unit_quantity | quantity | tolerance | calculate_units_to_order
|
||||
# --------------+----------+-----------+-----------------------
|
||||
# 4 | 0 | 2 | 0
|
||||
# 4 | 0 | 5 | 0
|
||||
# 4 | 2 | 2 | 1
|
||||
# 4 | 4 | 2 | 1
|
||||
# 4 | 4 | 4 | 1
|
||||
# 4 | 5 | 3 | 2
|
||||
# 4 | 5 | 4 | 2
|
||||
#
|
||||
def calculate_units_to_order(quantity, tolerance = 0)
|
||||
unit_size = price.unit_quantity
|
||||
units = quantity / unit_size
|
||||
remainder = quantity % unit_size
|
||||
units += ((remainder > 0) && (remainder + tolerance >= unit_size) ? 1 : 0)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def article_and_price_exist
|
||||
|
|
|
@ -35,7 +35,7 @@ class Ordergroup < Group
|
|||
acts_as_paranoid # Avoid deleting the ordergroup for consistency of order-results
|
||||
extend ActiveSupport::Memoizable # Ability to cache method results. Use memoize :expensive_method
|
||||
|
||||
has_many :financial_transactions
|
||||
has_many :financial_transactions, :order => "created_on DESC"
|
||||
has_many :group_orders
|
||||
has_many :orders, :through => :group_orders
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@
|
|||
|
|
||||
= link_to _('Upload articles'), upload_supplier_articles_path(@supplier)
|
||||
|
|
||||
= link_to_if @current_user.role_orders?, _('Create order'), {:controller => 'orders', :action => 'new', :id => @supplier }
|
||||
= link_to_if @current_user.role_orders?, _('Create order'), {:controller => 'orders', :action => 'new', :supplier_id => @supplier }
|
||||
|
||||
#article_filter
|
||||
#article_search_form{:style=>"display:inline;"}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
%table
|
||||
%tr
|
||||
%td Nettobetrag:
|
||||
%td= number_to_currency(order.sum(:clear))
|
||||
%td= number_to_currency(order.sum(:net))
|
||||
%tr
|
||||
%td Bruttobetrag:
|
||||
%td= number_to_currency(order.sum(:gross))
|
||||
|
|
|
@ -57,7 +57,7 @@
|
|||
%th=_ "Who"
|
||||
%th=_ "Note"
|
||||
%th=_ "Amount"
|
||||
- for ft in @financial_transactions
|
||||
- for ft in @ordergroup.financial_transactions.all(:limit => 5)
|
||||
%tr{:class => cycle('even','odd')}
|
||||
%td= format_time(ft.created_on)
|
||||
%td= h(ft.user.nil? ? '?' : ft.user.nick)
|
||||
|
|
|
@ -20,22 +20,22 @@
|
|||
:subnav => [
|
||||
{ :name => "Order", :url => "/ordering" },
|
||||
{ :name => "My orders", :url => "/ordering/myOrders" },
|
||||
{ :name => "Manage orders", :url => "/orders", :access? => (u.role_orders?) }
|
||||
{ :name => "Manage orders", :url => "/orders", :access_denied? => (!u.role_orders?) }
|
||||
]
|
||||
},
|
||||
{ :name => "Articles", :url => "/suppliers",
|
||||
:active => ["articles", "suppliers", "deliveries", "article_categories", "stockit"],
|
||||
:access? => (u.role_article_meta? || u.role_suppliers?),
|
||||
:access_denied? => (!u.role_article_meta? && !u.role_suppliers?),
|
||||
:subnav => [
|
||||
{ :name => "Artikel", :url => supplier_articles_path(Supplier.first) },
|
||||
{ :name => "Lager", :url => "/stockit" },
|
||||
{ :name => "Lieferantinnen", :url => suppliers_path, :access? => (u.role_suppliers?) },
|
||||
{ :name => "Lieferantinnen", :url => suppliers_path, :access_denied? => (!u.role_suppliers?) },
|
||||
{ :name => "Kategorien", :url => "/article_categories"}
|
||||
]
|
||||
},
|
||||
{ :name => "Finance", :url => "/finance",
|
||||
:active => ["finance/invoices", "finance/transactions", "finance/balancing"],
|
||||
:access? => (u.role_finance?),
|
||||
:access_denied? => (!u.role_finance?),
|
||||
:subnav => [
|
||||
{ :name => "Manage accounts", :url => "/finance/transactions" },
|
||||
{ :name => "Balance orders", :url => "/finance/balancing/list" },
|
||||
|
@ -44,7 +44,7 @@
|
|||
},
|
||||
{ :name => "Administration", :url => "/admin",
|
||||
:active => ["admin", "admin/users", "admin/ordergroups", "admin/workgroups"],
|
||||
:access? => (u.role_admin?),
|
||||
:access_denied? => (!u.role_admin?),
|
||||
:subnav => [
|
||||
{ :name => "Users", :url => admin_users_path },
|
||||
{ :name => "Ordergroups", :url => admin_ordergroups_path },
|
||||
|
@ -55,12 +55,12 @@
|
|||
-%>
|
||||
<ul>
|
||||
<% for tab in tabs -%>
|
||||
<% unless tab[:access?] and tab[:access?] == false -%>
|
||||
<% unless tab[:access_denied?] -%>
|
||||
<li class="<%= 'current' if tab_is_active?(tab) %>">
|
||||
<%= link_to tab[:name], tab[:url] %>
|
||||
<ul>
|
||||
<% for subtab in tab[:subnav] -%>
|
||||
<% unless subtab[:access?] and subtab[:access?] == false -%>
|
||||
<% unless subtab[:access_denied?] -%>
|
||||
<li><%= link_to subtab[:name], subtab[:url] %></li>
|
||||
<% end -%>
|
||||
<% end -%>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
%p
|
||||
Lieferant:
|
||||
%b=h @order.supplier.name
|
||||
- unless @order.note.empty?
|
||||
- unless @order.note.blank?
|
||||
%p
|
||||
Notiz:
|
||||
=h @order.note
|
||||
|
@ -76,7 +76,7 @@
|
|||
- if goa
|
||||
- quantity = goa.quantity
|
||||
- tolerance = goa.tolerance
|
||||
- result = goa.orderResult[:quantity] + goa.orderResult[:tolerance]
|
||||
- result = goa.result[:total]
|
||||
- sub_total = oa.price.fc_price * (quantity + tolerance)
|
||||
- else
|
||||
- quantity, tolerance, result, sub_total = 0, 0, 0, 0
|
||||
|
@ -88,7 +88,7 @@
|
|||
%tr{:class => cycle('even', 'odd', :name => 'articles'), :style => "color:#{style}"}
|
||||
%td{:style => "width:40%"}
|
||||
=h oa.article.name
|
||||
- unless oa.article.note.empty?
|
||||
- unless oa.article.note.blank?
|
||||
= image_tag("lamp_grey.png", {:alt => "Notiz anzeigen", :size => "15x16", :border => "0", :onmouseover => "$('note_#{oa.id}').show();", :onmouseout => "$('note_#{oa.id}').hide();"})
|
||||
%td= "#{oa.price.unit_quantity} x #{oa.article.unit}"
|
||||
%td= number_to_currency(oa.price.fc_price)
|
||||
|
@ -97,7 +97,7 @@
|
|||
= "+ #{tolerance}" if oa.price.unit_quantity > 1
|
||||
%td= result > 0 ? result : "0"
|
||||
%td= number_to_currency(sub_total)
|
||||
- unless oa.article.note.empty?
|
||||
- unless oa.article.note.blank?
|
||||
%tr{:id => "note_#{oa.id}", :class => "note even", :style => "display:none"}
|
||||
%td{:colspan => "6"}=h oa.article.note
|
||||
%tr{:class => cycle('even', 'odd', :name => 'articles')}
|
||||
|
|
|
@ -96,14 +96,14 @@
|
|||
-%>
|
||||
<tr class="<%= cycle('even', 'odd', :name => 'articles') %>" valign="top">
|
||||
<td class="name">
|
||||
<% unless order_article.article.note.empty? %>
|
||||
<% unless order_article.article.note.blank? %>
|
||||
<%= order_article.article.name %> <%= image_tag "lamp_grey.png", {:alt => _("Show note"), :size => "15x16", :border => "0", :onmouseover => "$('note_#{i}').show();", :onmouseout => "$('note_#{i}').hide();" }%>
|
||||
<% else %>
|
||||
<%= order_article.article.name %>
|
||||
<% end %>
|
||||
</td>
|
||||
<td><%=h order_article.article.origin %></td>
|
||||
<td><%=h truncate order_article.article.manufacturer, 11 %></td>
|
||||
<td><%=h truncate order_article.article.manufacturer, :length => 11 %></td>
|
||||
<td><%= @unit[i] %> * <%=h order_article.article.unit %></td>
|
||||
<td><%= number_to_currency(@price[i]) %></td>
|
||||
<td id="units_<%= i %>"><%= order_article.units_to_order %></td>
|
||||
|
@ -127,7 +127,7 @@
|
|||
</td>
|
||||
<td id="td_price_<%= i %>" style="text-align:right; padding-right:10px; width:4em"><span id="price_<%= i %>_display"><%= number_to_currency(article_total, :unit => "") %></span> €</td>
|
||||
</tr>
|
||||
<% unless order_article.article.note.empty? -%>
|
||||
<% unless order_article.article.note.blank? -%>
|
||||
<tr id="note_<%= i %>" class="note" style="display:none">
|
||||
<td colspan="10"><%=h order_article.article.note %> | <%=h order_article.article.manufacturer %></td>
|
||||
</tr>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
%tr
|
||||
%th Name
|
||||
%th Gebinde
|
||||
%th Netto/FC-Preis
|
||||
%th Netto-/Bruttopreis
|
||||
%th Bestellte Einheiten
|
||||
%th Volle Gebinde
|
||||
- total_net, total_gross, counter = 0, 0, 0
|
||||
|
@ -12,19 +12,19 @@
|
|||
%td{:colspan => "9"}
|
||||
- order_articles.each do |order_article|
|
||||
- net_price = order_article.price.price
|
||||
- fc_price = order_article.price.fc_price
|
||||
- gross_price = order_article.price.gross_price
|
||||
- units = order_article.units_to_order
|
||||
- unit_quantity = order_article.price.unit_quantity
|
||||
- total_net += units * unit_quantity * net_price
|
||||
- total_gross += units * unit_quantity * fc_price
|
||||
- total_gross += units * unit_quantity * gross_price
|
||||
%tr{:class => cycle('even', 'odd', :name => 'articles'), :style => "color: #{units > 0 ? 'green' : 'red'}"}
|
||||
%td=h order_article.article.name
|
||||
%td= "#{unit_quantity} x #{order_article.article.unit}"
|
||||
%td= "#{number_to_currency(net_price)} / #{number_to_currency(fc_price)}"
|
||||
%td= "#{number_to_currency(net_price)} / #{number_to_currency(gross_price)}"
|
||||
%td= "#{order_article.quantity} + #{order_article.tolerance}" if unit_quantity > 1
|
||||
%td= units
|
||||
%p
|
||||
Summe (Netto/FC-Preise):
|
||||
Summe (Netto/Brutto-Preise):
|
||||
= "#{number_to_currency(total_net)} / #{number_to_currency(total_gross)}"
|
||||
%p
|
||||
Bestellte Artikel.
|
||||
|
|
|
@ -41,7 +41,7 @@ pdf.text "Ansprechpartner: " + @order.supplier.contact_person
|
|||
pdf.move_down 10
|
||||
|
||||
# Articles
|
||||
data = @order.order_articles.all(:include => :article).collect do |a|
|
||||
data = @order.order_articles.ordered.all(:include => :article).collect do |a|
|
||||
[a.article.order_number, a.units_to_order, a.article.name,
|
||||
a.price.unit_quantity, a.article.unit, a.price.price]
|
||||
end
|
||||
|
|
|
@ -22,7 +22,7 @@ for group_order in @order.group_orders
|
|||
|
||||
total = 0
|
||||
data = []
|
||||
group_order.group_order_articles.each do |goa|
|
||||
group_order.group_order_articles.ordered.each do |goa|
|
||||
price = goa.order_article.price.fc_price
|
||||
quantity = goa.quantity
|
||||
sub_total = price * quantity
|
||||
|
|
|
@ -10,7 +10,7 @@ pdf.footer [pdf.margin_box.left, pdf.margin_box.bottom-5] do
|
|||
end
|
||||
|
||||
max_order_articles_per_page = 17 # How many order_articles shoud written on a page
|
||||
order_articles = @order.order_articles
|
||||
order_articles = @order.order_articles.ordered
|
||||
|
||||
pdf.text "Artikelübersicht", :style => :bold
|
||||
pdf.move_down 5
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
- title _("Show order")
|
||||
#element_navigation
|
||||
= link_to_unless @order.previous == @order, _("Previous order"), @order.previous
|
||||
= link_to_unless @order.previous == @order, "<< #{@order.previous.supplier.name}", @order.previous
|
||||
|
|
||||
= link_to _("Overview"), orders_path
|
||||
|
|
||||
= link_to_unless @order.next == @order, _("Next order"), @order.next
|
||||
= link_to_unless @order.next == @order, "#{@order.next.supplier.name} >>", @order.next
|
||||
|
||||
// Order summary
|
||||
.left_column{:style => "width:65em"}
|
||||
|
@ -33,18 +33,21 @@
|
|||
= "[#{@order.group_orders.find(:all, :include => :ordergroup).collect{|g| g.ordergroup.name}.join(', ')}]"
|
||||
|
||||
%p
|
||||
Bruttosummer aller Artikel
|
||||
%b= number_to_currency(@order.sum(:gross))
|
||||
- if @order.finished?
|
||||
|
|
||||
Bestellte Artikel:
|
||||
%b= @order.order_articles.ordered.count
|
||||
Netto/Bruttosumme aller Artikel
|
||||
%b= "#{number_to_currency(@order.sum(:net))} / #{number_to_currency(@order.sum(:gross))}"
|
||||
%p
|
||||
Bestellte Artikel:
|
||||
%b= @order.order_articles.ordered.count
|
||||
|
||||
|
||||
%p
|
||||
Aktionen:
|
||||
- if @order.open?
|
||||
= link_to "Bearbeiten", edit_order_path(@order)
|
||||
= link_to 'Beenden!', finish_order_path(@order), :method => :post, :confirm => "Willst Du wirklich die Bestellung beenden?\nEs gibt kein zurück.."
|
||||
- unless @order.closed?
|
||||
= link_to "Löschen", @order, :confirm => "Willst du wirklich die Bestellung löschen?", :method => :delete
|
||||
|
||||
- if @order.open?
|
||||
%p
|
||||
= link_to icon(:edit), edit_order_path(@order)
|
||||
= link_to icon(:delete), @order, :confirm => "Willst du wirklich die Bestellung löschen?", :method => :delete
|
||||
= link_to '[beenden]', finish_order_path(@order), :method => :post
|
||||
|
||||
- unless @order.open?
|
||||
%p
|
||||
|
|
|
@ -4,20 +4,23 @@
|
|||
%th{:colspan => '3'} Legende
|
||||
%tr
|
||||
%th{:style => 'width:70%'} Bestellgruppe
|
||||
%th Menge
|
||||
%th Bestellt
|
||||
%th Bekommen
|
||||
%th Gesamtpreis
|
||||
|
||||
- for order_article in order.order_articles.all(:include => [:article, :article_price])
|
||||
- for order_article in order.order_articles.ordered.all(:include => [:article, :article_price])
|
||||
%table{:style => "margin-bottom:1em"}
|
||||
%thead
|
||||
%tr
|
||||
%th{:colspan => "3"}
|
||||
%th{:colspan => "4"}
|
||||
= order_article.article.name
|
||||
= "(#{order_article.article.unit} | #{order_article.price.unit_quantity} | #{number_to_currency(order_article.price.fc_price)})"
|
||||
= "(#{order_article.article.unit} | #{order_article.price.unit_quantity} | #{number_to_currency(order_article.price.gross_price)})"
|
||||
%tbody
|
||||
- for goa in order_article.group_order_articles
|
||||
%tr{:class => cycle('even', 'odd', :name => 'groups')}
|
||||
%td{:style => "width:70%"}=h goa.group_order.ordergroup.name
|
||||
%td= "#{goa.quantity} (#{goa.tolerance})"
|
||||
%td
|
||||
%b= "#{goa.quantity_result} + #{goa.tolerance_result}"
|
||||
%td= number_to_currency(order_article.price.fc_price * goa.quantity)
|
||||
- reset_cycle('groups')
|
|
@ -18,13 +18,13 @@
|
|||
%th{:colspan => "6"}=h group_order.ordergroup.name
|
||||
%tbody
|
||||
- total = 0
|
||||
- for goa in group_order.group_order_articles.all(:include => :order_article)
|
||||
- for goa in group_order.group_order_articles.ordered.all(:include => :order_article)
|
||||
- fc_price = goa.order_article.price.fc_price
|
||||
- subTotal = fc_price * goa.quantity
|
||||
- total += subTotal
|
||||
%tr{:class => cycle('even', 'odd', :name => 'articles')}
|
||||
%td{:style => "width:40%"}=h goa.order_article.article.name
|
||||
%td= "#{goa.quantity} (#{goa.tolerance})"
|
||||
%td= "#{goa.result[:quantity]} (#{goa.result[:tolerance]})"
|
||||
%td= number_to_currency(fc_price)
|
||||
%td= goa.order_article.price.unit_quantity
|
||||
%td= goa.order_article.article.unit
|
||||
|
|
|
@ -3,21 +3,21 @@ class RefactorOrderLogic < ActiveRecord::Migration
|
|||
# TODO: Combine migrations since foodsoft3-development into one file
|
||||
# and try to build a migration path from old data.
|
||||
|
||||
# == Ordergroups
|
||||
add_column :groups, :deleted_at, :datetime # acts_as_paranoid
|
||||
remove_column :groups, :actual_size # Useless, desposits are better stored within a transaction.note
|
||||
# move contact-infos from users to ordergroups
|
||||
add_column :groups, :contact_person, :string
|
||||
add_column :groups, :contact_phone, :string
|
||||
add_column :groups, :contact_address, :string
|
||||
Ordergroup.all.each do |ordergroup|
|
||||
contact = ordergroup.users.first
|
||||
if contact
|
||||
ordergroup.update_attributes :contact_person => contact.name,
|
||||
:contact_phone => contact.phone, :contact_address => contact.address
|
||||
end
|
||||
end
|
||||
remove_column :users, :address
|
||||
# # == Ordergroups
|
||||
# add_column :groups, :deleted_at, :datetime # acts_as_paranoid
|
||||
# remove_column :groups, :actual_size # Useless, desposits are better stored within a transaction.note
|
||||
# # move contact-infos from users to ordergroups
|
||||
# add_column :groups, :contact_person, :string
|
||||
# add_column :groups, :contact_phone, :string
|
||||
# add_column :groups, :contact_address, :string
|
||||
# Ordergroup.all.each do |ordergroup|
|
||||
# contact = ordergroup.users.first
|
||||
# if contact
|
||||
# ordergroup.update_attributes :contact_person => contact.name,
|
||||
# :contact_phone => contact.phone, :contact_address => contact.address
|
||||
# end
|
||||
# end
|
||||
# remove_column :users, :address
|
||||
#
|
||||
# # == Article
|
||||
# rename_column :articles, :net_price, :price
|
||||
|
@ -77,6 +77,11 @@ class RefactorOrderLogic < ActiveRecord::Migration
|
|||
#
|
||||
# # == GroupOrder
|
||||
# change_column :group_orders, :updated_by_user_id, :integer, :default => nil, :null => true
|
||||
|
||||
# == GroupOrderArticle
|
||||
# The order result in ordergroup is now saved!
|
||||
add_column :group_order_articles, :quantity_result, :integer, :default => nil
|
||||
add_column :group_order_articles, :tolerance_result, :integer, :default => nil
|
||||
end
|
||||
|
||||
def self.down
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#
|
||||
# It's strongly recommended to check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(:version => 20090120184410) do
|
||||
ActiveRecord::Schema.define(:version => 20090119155930) do
|
||||
|
||||
create_table "article_categories", :force => true do |t|
|
||||
t.string "name", :default => "", :null => false
|
||||
|
|
|
@ -41,7 +41,7 @@ und OrderArticle miteinander verbunden.
|
|||
Bei jeder Bestellung wird außerdem die Summe der Menge, Toleranz in GroupOrderArticle
|
||||
abgelegt. Allerdings muss jede Aenderung dieser Mengen mit protokolliert werden.
|
||||
Dies ist wichtig, weil spaeter die Zuteilung der Einheiten pro bestellten Artikel
|
||||
nach der chronoligischen Reihenfolge erfolgt. (s.u.)
|
||||
nach der chronologischen Reihenfolge erfolgt. (s.u.)
|
||||
Das passiert dann in der Tabelle group_order_article_quantities.
|
||||
(GroupOrderArticleQuantity)
|
||||
|
||||
|
|
29
test/fixtures/suppliers.yml
vendored
29
test/fixtures/suppliers.yml
vendored
|
@ -3,19 +3,22 @@
|
|||
#
|
||||
# Table name: suppliers
|
||||
#
|
||||
# id :integer(4) not null, primary key
|
||||
# name :string(255) not null
|
||||
# address :string(255) not null
|
||||
# phone :string(255) not null
|
||||
# phone2 :string(255)
|
||||
# fax :string(255)
|
||||
# email :string(255)
|
||||
# url :string(255)
|
||||
# delivery_days :string(255)
|
||||
# note :string(255)
|
||||
# created_on :datetime
|
||||
# updated_on :datetime
|
||||
# lists :string(255)
|
||||
# id :integer not null, primary key
|
||||
# name :string(255) default(""), not null
|
||||
# address :string(255) default(""), not null
|
||||
# phone :string(255) default(""), not null
|
||||
# phone2 :string(255)
|
||||
# fax :string(255)
|
||||
# email :string(255)
|
||||
# url :string(255)
|
||||
# contact_person :string(255)
|
||||
# customer_number :string(255)
|
||||
# delivery_days :string(255)
|
||||
# order_howto :string(255)
|
||||
# note :string(255)
|
||||
# shared_supplier_id :integer
|
||||
# min_order_quantity :string(255)
|
||||
# deleted_at :datetime
|
||||
#
|
||||
|
||||
# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
require File.dirname(__FILE__) + '/../test_helper'
|
||||
require 'finance_controller'
|
||||
|
||||
# Re-raise errors caught by the controller.
|
||||
class FinanceController; def rescue_action(e) raise e end; end
|
||||
|
||||
class FinanceControllerTest < Test::Unit::TestCase
|
||||
def setup
|
||||
@controller = FinanceController.new
|
||||
@request = ActionController::TestRequest.new
|
||||
@response = ActionController::TestResponse.new
|
||||
end
|
||||
|
||||
# Replace this with your real tests.
|
||||
def test_truth
|
||||
assert true
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue