Order-refactoring part II.

This commit is contained in:
Benjamin Meichsner 2009-02-03 21:14:48 +01:00
parent f7b9582261
commit 6fd5d825f9
27 changed files with 228 additions and 231 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -1,5 +1,5 @@
# == Schema Information
# Schema version: 20090119155930
# Schema version: 20090120184410
#
# Table name: group_order_articles
#
@ -9,13 +9,16 @@
# 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
has_many :group_order_article_quantities, :dependent => :destroy
@ -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

View File

@ -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,51 +133,26 @@ 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
notify_order_finished
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)

View File

@ -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

View File

@ -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

View File

@ -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;"}

View File

@ -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))

View File

@ -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)

View File

@ -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 -%>

View File

@ -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')}

View File

@ -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>

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
- 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
%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
- unless @order.open?
%p

View File

@ -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')

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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