Complete refactoring of orders-workflow.

OrderResult tables are removed. Data consistency is now possible through new article.price-history (ArticlePrice).
Balancing-workflow needs to be updated.
This commit is contained in:
Benjamin Meichsner 2009-01-29 01:57:51 +01:00
parent 80287aeea4
commit 9eb2125f15
98 changed files with 1121 additions and 1717 deletions

View file

@ -121,7 +121,7 @@ class ArticlesController < ApplicationController
def destroy
@article = Article.find(params[:id])
@order = @article.inUse # If article is in an active Order, the Order will be returned
@order = @article.in_open_order # If article is in an active Order, the Order will be returned
if @order
render :update do |page|
page.insert_html :after, @article.id.to_s, :partial => 'destroyActiveArticle'
@ -226,7 +226,7 @@ class ArticlesController < ApplicationController
:origin => row[:origin],
:unit => row[:unit],
:article_category => ArticleCategory.find_by_name(row[:category]),
:net_price => row[:price],
:price => row[:price],
:unit_quantity => row[:unit_quantity],
:order_number => row[:number],
:deposit => row[:deposit],
@ -290,7 +290,7 @@ class ArticlesController < ApplicationController
:note => shared_article.note,
:manufacturer => shared_article.manufacturer,
:origin => shared_article.origin,
:net_price => shared_article.price,
:price => shared_article.price,
:tax => shared_article.tax,
:deposit => shared_article.deposit,
:unit_quantity => shared_article.unit_quantity,

View file

@ -39,7 +39,7 @@ class Finance::BalancingController < ApplicationController
render :update do |page|
@article = OrderArticleResult.new(params[:order_article_result])
@article.fc_markup = APP_CONFIG[:price_markup]
@article.make_gross if @article.tax && @article.deposit && @article.net_price
@article.make_gross if @article.tax && @article.deposit && @article.price
if @article.valid?
@article.save
@order = @article.order
@ -121,9 +121,9 @@ class Finance::BalancingController < ApplicationController
page["edit_box"].hide
page.insert_html :after, "groups_results_#{article.id}", :partial => "groupResults"
page["group_order_article_result_#{@result.id}"].visual_effect :highlight, :duration => 2
page["groups_amount"].replace_html number_to_currency(article.order.sumPrice('groups'))
page["fcProfit"].replace_html number_to_currency(article.order.fcProfit)
page["fcProfit"].visual_effect :highlight, :duration => 2
page["groups_amount"].replace_html number_to_currency(article.order.sum('groups'))
page["profit"].replace_html number_to_currency(article.order.profit)
page["profit"].visual_effect :highlight, :duration => 2
# get the new sums for quantity and price and replace it
total = article.total
@ -141,15 +141,15 @@ class Finance::BalancingController < ApplicationController
if params[:group_order_article_result]
if @result.update_attribute(:quantity, params[:group_order_article_result][:quantity])
order = @result.group_order_result.order
groups_amount = order.sumPrice("groups")
groups_amount = order.sum(:groups)
article = @result.order_article_result
total = article.total
page["edit_box"].hide
page["groups_amount"].replace_html number_to_currency(groups_amount)
page["fcProfit"].replace_html number_to_currency(order.fcProfit)
page["profit"].replace_html number_to_currency(order.profit)
page["groups_amount"].visual_effect :highlight, :duration => 2
page["fcProfit"].visual_effect :highlight, :duration => 2
page["profit"].visual_effect :highlight, :duration => 2
page["group_order_article_result_#{@result.id}"].replace_html :partial => "groupResult"
page["group_order_article_result_#{@result.id}"].visual_effect :highlight, :duration => 2
page["totalArticleQuantity_#{article.id}"].replace_html total[:quantity]
@ -169,9 +169,9 @@ class Finance::BalancingController < ApplicationController
render :update do |page|
article = @result.order_article_result
page["group_order_article_result_#{@result.id}"].remove
page["groups_amount"].replace_html number_to_currency(article.order.sumPrice('groups'))
page["fcProfit"].replace_html number_to_currency(article.order.fcProfit)
page["fcProfit"].visual_effect :highlight, :duration => 2
page["groups_amount"].replace_html number_to_currency(article.order.sum('groups'))
page["profit"].replace_html number_to_currency(article.order.profit)
page["profit"].visual_effect :highlight, :duration => 2
total = article.total # get total quantity and price for the ArticleResult
page["totalArticleQuantity_#{article.id}"].replace_html total[:quantity]
page["totalArticleQuantity_#{article.id}"].visual_effect :highlight, :duration => 2

View file

@ -27,7 +27,7 @@ class FoodcoopController < ApplicationController
conditions = "first_name LIKE '%#{params[:query]}%' OR last_name LIKE '%#{params[:query]}%'" unless params[:query].blank?
@total = User.count(:conditions => conditions)
@users = User.paginate(:page => params[:page], :per_page => @per_page, :conditions => conditions, :order => "nick", :include => "groups")
@users = User.paginate(:page => params[:page], :per_page => @per_page, :conditions => conditions, :order => "nick", :include => :groups)
respond_to do |format|
format.html # index.html.erb

View file

@ -2,10 +2,10 @@ class HomeController < ApplicationController
helper :messages
def index
@currentOrders = Order.find_current
@orderGroup = @current_user.find_ordergroup
if @orderGroup
@financial_transactions = @orderGroup.financial_transactions.find(:all, :order => 'created_on desc', :limit => 3)
@currentOrders = Order.open
@ordergroup = @current_user.find_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

View file

@ -9,21 +9,12 @@ class OrderingController < ApplicationController
# Index page.
def index
@orderGroup = @current_user.find_ordergroup
@currentOrders = Order.find_current
@finishedOrders = @orderGroup.findExpiredOrders + @orderGroup.findFinishedNotBooked
@bookedOrders = @orderGroup.findBookedOrders(5)
# Calculate how much the order group has spent on open or nonbooked orders:
@currentOrdersValue, @nonbookedOrdersValue = 0, 0
@orderGroup.findCurrent.each { |groupOrder| @currentOrdersValue += groupOrder.price}
@finishedOrders.each { |groupOrder| @nonbookedOrdersValue += groupOrder.price}
end
# Edit a current order.
def order
@current_orders = Order.find_current
@other_orders = @current_orders.reject{|order| order == @order}
@open_orders = Order.open
@other_orders = @open_orders.reject{|order| order == @order}
# Load order article data...
@articles_by_category = @order.get_articles
# save results of earlier orders in array
@ -39,10 +30,10 @@ class OrderingController < ApplicationController
'tolerance_result' => result[:tolerance]}
end
@version = @group_order.lock_version
@availableFunds = @ordergroup.getAvailableFunds(@group_order)
@availableFunds = @ordergroup.get_available_funds(@group_order)
else
@version = 0
@availableFunds = @ordergroup.getAvailableFunds
@availableFunds = @ordergroup.get_available_funds
end
# load prices ....
@ -50,10 +41,10 @@ class OrderingController < ApplicationController
@others_quantity = Array.new; @quantity = Array.new; @quantity_result = Array.new; @used_quantity = Array.new; @unused_quantity = Array.new
@others_tolerance = Array.new; @tolerance = Array.new; @tolerance_result = Array.new; @used_tolerance = Array.new; @unused_tolerance = Array.new
i = 0;
@articles_by_category.each do |category, order_articles|
@articles_by_category.each do |category_name, order_articles|
for order_article in order_articles
# price/unit size
@price[i] = order_article.article.gross_price
@price[i] = order_article.article.fc_price
@unit[i] = order_article.article.unit_quantity
# quantity
@quantity[i] = (ordered_articles[order_article.id] ? ordered_articles[order_article.id]['quantity'] : 0)
@ -78,12 +69,12 @@ class OrderingController < ApplicationController
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 (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 = GroupOrder.new(:ordergroup => @ordergroup, :order => order, :updated_by => @current_user, :price => 0)
groupOrder.save!
end
# Create/update GroupOrderArticles...
@ -98,15 +89,15 @@ class OrderingController < ApplicationController
unless (quantities = ordered.delete(article.id.to_s)) && (quantity = quantities['quantity']) && (tolerance = quantities['tolerance'])
quantity = tolerance = 0
end
groupOrderArticle.updateQuantities(quantity.to_i, tolerance.to_i)
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.updatePrice
groupOrder.update_price!
groupOrder.updated_by = @current_user
groupOrder.save!
order.updateQuantities
order.update_quantities
order.save!
end
flash[:notice] = 'Die Bestellung wurde gespeichert.'
@ -124,67 +115,33 @@ class OrderingController < ApplicationController
# this method decides between finished and unfinished orders
def my_order_result
@order= Order.find(params[:id])
@current_orders = Order.find_current #.reject{|order| order == @order}
if @order.finished?
@finished= true
@groupOrderResult= @order.group_order_results.find_by_group_name(@current_user.find_ordergroup.name)
@order_value= @groupOrderResult.price if @groupOrderResult
@comments= @order.comments
else
@group_order = @order.group_orders.find_by_ordergroup_id(@current_user.find_ordergroup.id)
@order_value= @group_order.price if @group_order
end
@group_order = @order.group_order(@ordergroup)
end
# Shows all Orders of the Ordergroup
# if selected, it shows all orders of the foodcoop
def myOrders
@orderGroup = @current_user.find_ordergroup
unless params[:show_all] == "1"
# get only orders belonging to the ordergroup
@finishedOrders = @orderGroup.findExpiredOrders + @orderGroup.findFinishedNotBooked
@bookedOrders = GroupOrderResult.paginate :page => params[:page], :per_page => 10,
:include => :order,
:conditions => ["group_order_results.group_name = ? AND group_order_results.order_id = orders.id AND orders.finished = ? AND orders.booked = ? ", @orderGroup.name, true, true],
:order => "orders.ends DESC"
else
# get all orders, take care of different models in @finishedOrders
@show_all = true
@finishedOrders = Order.find_finished
@bookedOrders = Order.paginate_all_by_booked true, :page => params[:page], :per_page => 10, :order => 'ends desc'
end
@closed_orders = Order.paginate :page => params[:page], :per_page => 10,
:conditions => { :state => 'closed' }, :order => "orders.ends DESC"
respond_to do |format|
format.html # myOrders.haml
format.js do
render :update do |page|
page.replace_html 'bookedOrders', :partial => "bookedOrders"
end
end
end
end
# sends a form for adding a new comment
def newComment
@order = Order.find(params[:id])
render :update do |page|
page.replace_html 'newComment', :partial => 'shared/newComment', :object => @order
page["newComment"].show
format.js { render :partial => "orders" }
end
end
# adds a Comment to the Order
def addComment
@order = Order.find(params[:id])
@comment = Comment.new(params[:comment])
@comment.user = @current_user
if @comment.title.length > 3 && @order.comments << @comment
flash[:notice] = _("Comment has been created.")
redirect_to :action => 'my_order_result', :id => @order
def add_comment
order = Order.find(params[:id])
comment = order.comments.build(params[:comment])
comment.user = @current_user
if !comment.text.empty? and comment.save
flash[:notice] = "Kommentar wurde erstellt."
else
flash[:error] = _("The comment has not been saved. Check the title and try again.")
redirect_to :action => 'my_order_result', :id => @order
flash[:error] = "Kommentar konnte nicht erstellt werden. Leerer Kommentar?"
end
redirect_to :action => 'my_order_result', :id => order
end
private
@ -192,7 +149,8 @@ class OrderingController < ApplicationController
# Returns true if @current_user is member of an Ordergroup.
# Used as a :before_filter by OrderingController.
def ensure_ordergroup_member
unless @current_user.find_ordergroup
@ordergroup = @current_user.find_ordergroup
if @ordergroup.nil?
flash[:notice] = 'Sie gehören keiner Bestellgruppe an.'
redirect_to :controller => root_path
end
@ -200,7 +158,7 @@ class OrderingController < ApplicationController
def ensure_open_order
@order = Order.find(params[:id], :include => [:supplier, :order_articles])
unless @order.current?
unless @order.open?
flash[:notice] = 'Diese Bestellung ist bereits abgeschlossen.'
redirect_to :action => 'index'
end

View file

@ -1,9 +1,8 @@
# Controller for managing orders, i.e. all actions that require the "orders" role.
# Normal ordering actions of members of order groups is handled by the OrderingController.
class OrdersController < ApplicationController
# Security
before_filter :authenticate_orders
verify :method => :post, :only => [:finish, :create, :update, :destroy, :setAllBooked], :redirect_to => { :action => :index }
# Define layout exceptions for PDF actions:
layout "application", :except => [:faxPdf, :matrixPdf, :articlesPdf, :groupsPdf]
@ -11,20 +10,20 @@ class OrdersController < ApplicationController
# List orders
def index
@current_orders = Order.find_current
@open_orders = Order.open
@per_page = 15
if params['sort']
sort = case params['sort']
when "supplier" then "suppliers.name, ends DESC"
when "ends" then "ends DESC"
when "supplier_reverse" then "suppliers.name DESC, ends DESC"
when "supplier_reverse" then "suppliers.name DESC"
when "ends_reverse" then "ends"
end
else
sort = "ends DESC"
end
@orders = Order.paginate :page => params[:page], :per_page => @per_page,
:order => sort, :conditions => ['ends < ? OR starts > ? OR finished = ?', Time.now, Time.now, true],
:order => sort, :conditions => "state != 'open'",
:include => :supplier
respond_to do |format|
@ -38,30 +37,25 @@ class OrdersController < ApplicationController
end
# Gives a view for the results to a specific order
# Renders also the pdf
def show
@order= Order.find(params[:id])
unless @order.finished?
@order_articles= @order.get_articles
@group_orders= @order.group_orders
else
@finished= true
@order_articles= @order.order_article_results
@group_orders= @order.group_order_results
@comments= @order.comments
if params[:view] # Articles-list will be replaced
partial = case params[:view]
when 'normal' then "showResult"
when 'groups'then 'showResult_groups'
when 'articles'then 'showResult_articles'
when 'normal' then "articles"
when 'groups'then 'articles_by_groups'
when 'articles'then 'articles_by_articles'
end
render :partial => partial if partial
render :partial => partial, :locals => {:order => @order} if partial
end
end
# Page to create a new order.
def new
@supplier = Supplier.find(params[:id])
@supplier = Supplier.find(params[:supplier_id])
@order = @supplier.orders.build :ends => 4.days.from_now
@template_orders = Order.find_all_by_supplier_id_and_finished(@supplier.id, true, :limit => 3, :order => 'starts DESC', :include => "order_article_results")
@template_orders = @supplier.orders.finished :order => 'starts DESC', :include => "order_article_results"
end
# Save a new order.
@ -69,8 +63,8 @@ class OrdersController < ApplicationController
def create
@order = Order.new(params[:order])
if @order.save
flash[:notice] = _("The order has been created successfully.")
redirect_to :action => 'show', :id => @order
flash[:notice] = "Die Bestellung wurde erstellt."
redirect_to @order
else
render :action => 'new'
end
@ -86,12 +80,11 @@ class OrdersController < ApplicationController
def update
@order = Order.find params[:id]
if @order.update_attributes params[:order]
flash[:notice] = _("The order has been updated.")
flash[:notice] = "Die Bestellung wurde aktualisiert."
redirect_to :action => 'show', :id => @order
else
render :action => 'edit'
end
@order.updateAllGroupOrders #important if ordered articles has been removed
end
# Delete an order.
@ -103,21 +96,21 @@ class OrdersController < ApplicationController
# Finish a current order.
def finish
order = Order.find(params[:id])
order.finish(@current_user)
flash[:notice] = _("The order has been finished successfully.")
redirect_to :action => 'show', :id => order
order.finish!(@current_user)
flash[:notice] = "Die Bestellung wurde beendet."
redirect_to order
end
# Renders the groups-orderd PDF.
def groupsPdf
@order = Order.find(params[:id])
prawnto :filename => "#{Date.today}_#{@order.name}_GruppenSortierung.pdf"
prawnto :filename => "#{Date.today}_#{@order.supplier.name}_GruppenSortierung.pdf"
end
# Renders the articles-orderd PDF.
def articlesPdf
@order = Order.find(params[:id])
prawnto :filename => "#{Date.today}_#{@order.name}_ArtikelSortierung.pdf",
prawnto :filename => "#{Date.today}_#{@order.supplier.name}_ArtikelSortierung.pdf",
:prawn => { :left_margin => 48,
:right_margin => 48,
:top_margin => 48,
@ -127,7 +120,7 @@ class OrdersController < ApplicationController
# Renders the fax PDF.
def faxPdf
@order = Order.find(params[:id])
prawnto :filename => "#{Date.today}_#{@order.name}_FAX.pdf"
prawnto :filename => "#{Date.today}_#{@order.supplier.name}_FAX.pdf"
end
# Renders the fax-text-file
@ -136,51 +129,43 @@ class OrdersController < ApplicationController
order = Order.find(params[:id])
supplier = order.supplier
contact = APP_CONFIG[:contact].symbolize_keys
text = _("Order for") + " #{APP_CONFIG[:name]}"
text += "\n" + _("Customer number") + ": #{supplier.customer_number}" unless supplier.customer_number.blank?
text += "\n" + _("Delivery date") + ": "
text = "Bestellung für" + " #{APP_CONFIG[:name]}"
text += "\n" + "Kundennummer" + ": #{supplier.customer_number}" unless supplier.customer_number.blank?
text += "\n" + "Liefertag" + ": "
text += "\n\n#{supplier.name}\n#{supplier.address}\nFAX: #{supplier.fax}\n\n"
text += "****** " + _("Shipping address") + "\n\n"
text += "****** " + "Versandadresse" + "\n\n"
text += "#{APP_CONFIG[:name]}\n#{contact[:street]}\n#{contact[:zip_code]} #{contact[:city]}\n\n"
text += "****** " + _("Articles") + "\n\n"
text += _("Number") + " " + _("Quantity") + " " + _("Name") + "\n"
text += "****** " + "Artikel" + "\n\n"
text += "Nummer" + " " + "Menge" + " " + "Name" + "\n"
# now display all ordered articles
order.order_article_results.each do |article|
text += article.order_number.blank? ? " " : "#{article.order_number} "
quantity = article.units_to_order.to_i.to_s
order.order_articles.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
quantity = " " + quantity if quantity.size < 2
text += "#{quantity} #{article.name}\n"
text += "#{number} #{quantity} #{oa.article.name}\n"
end
send_data text,
:type => 'text/plain; charset=utf-8; header=present',
:disposition => "attachment; filename=#{order.name}"
:disposition => "attachment; filename=#{order.supplier.name}"
end
# Renders the matrix PDF.
def matrixPdf
@order = Order.find(params[:id])
prawnto :filename => "#{Date.today}_#{@order.name}_Matrix.pdf"
end
# sends a form for adding a new comment
def newComment
@order = Order.find(params[:id])
render :update do |page|
page.replace_html 'newComment', :partial => 'shared/newComment', :object => @order
end
prawnto :filename => "#{Date.today}_#{@order.supplier.name}_Matrix.pdf"
end
# adds a Comment to the Order
def addComment
@order = Order.find(params[:id])
@comment = Comment.new(params[:comment])
@comment.user = @current_user
if @comment.title.length > 3 && @order.comments << @comment
flash[:notice] = _("Comment has been created.")
redirect_to :action => 'show', :id => @order
def add_comment
order = Order.find(params[:id])
comment = order.comments.build(params[:comment])
comment.user = @current_user
if !comment.text.empty? and comment.save
flash[:notice] = "Kommentar wurde erstellt."
else
flash[:error] = _("The comment has not been saved. Check the title and try again.")
redirect_to :action => 'show', :id => @order
end
flash[:error] = "Kommentar konnte nicht erstellt werden. Leerer Kommentar?"
end
redirect_to order
end
end

View file

@ -1,11 +1,13 @@
module OrdersHelper
require 'iconv'
# This method is needed to convert special characters into UTF-8 for rendering PDF files correctly.
def replace_UTF8(field)
ic_ignore = Iconv.new('ISO-8859-15//IGNORE//TRANSLIT', 'UTF-8')
field = ic_ignore.iconv(field)
ic_ignore.close
field
def update_articles_link(order, text, view)
link_to_remote text, :url => order_path(order, :view => view),
:update => 'articles', :before => "Element.show('loader')", :success => "Element.hide('loader')",
:method => :get
end
def link_to_pdf(order, action)
link_to image_tag("save_pdf.png", :size => "16x16", :border => "0", :alt => "PDF erstellen"),
{ :action => action, :id => order, :format => :pdf }, { :title => "PDF erstellen" }
end
end

View file

@ -1,5 +1,5 @@
# == Schema Information
# Schema version: 20090119155930
# Schema version: 20090120184410
#
# Table name: articles
#
@ -13,8 +13,7 @@
# manufacturer :string(255)
# origin :string(255)
# shared_updated_on :datetime
# net_price :decimal(8, 2)
# gross_price :decimal(8, 2) default(0.0), not null
# price :decimal(8, 2)
# tax :float
# deposit :decimal(8, 2) default(0.0)
# unit_quantity :integer(4) default(1), not null
@ -27,24 +26,29 @@
class Article < ActiveRecord::Base
acts_as_paranoid # Avoid deleting the article for consistency of order-results
extend ActiveSupport::Memoizable # Ability to cache method results. Use memoize :expensive_method
# Associations
belongs_to :supplier
belongs_to :article_category
has_many :article_prices, :order => "created_at"
named_scope :in_stock, :conditions => "quantity > 0", :order => 'suppliers.name', :include => :supplier
validates_presence_of :name, :unit, :net_price, :tax, :deposit, :unit_quantity, :supplier_id
# Validations
validates_presence_of :name, :unit, :price, :tax, :deposit, :unit_quantity, :supplier_id, :article_category_id
validates_length_of :name, :in => 4..60
validates_length_of :unit, :in => 2..15
validates_numericality_of :net_price, :greater_than => 0
validates_numericality_of :price, :greater_than => 0
validates_numericality_of :deposit, :tax
# calculate the gross_price
before_save :calc_gross_price
# Callbacks
before_save :update_price_history
before_destroy :check_article_in_use
# Custom attribute setter that accepts decimal numbers using localized decimal separator.
def net_price=(net_price)
self[:net_price] = String.delocalized_decimal(net_price)
def price=(price)
self[:price] = String.delocalized_decimal(price)
end
# Custom attribute setter that accepts decimal numbers using localized decimal separator.
@ -57,9 +61,14 @@ class Article < ActiveRecord::Base
self[:deposit] = String.delocalized_decimal(deposit)
end
# calculate the fc price and sets the attribute
def calc_gross_price
self.gross_price = ((net_price + deposit) * (tax / 100 + 1)) * (APP_CONFIG[:price_markup] / 100 + 1)
# The financial gross, net plus tax and deposti
def gross_price
((price + deposit) * (tax / 100 + 1)).round(2)
end
# The price for the foodcoop-member.
def fc_price
(gross_price * (APP_CONFIG[:price_markup] / 100 + 1)).round(2)
end
# Returns true if article has been updated at least 2 days ago
@ -75,7 +84,7 @@ class Article < ActiveRecord::Base
#
# Example:
#
# unit_quantity | quantity | tolerance | calculateOrderQuantity
# unit_quantity | quantity | tolerance | calculate_order_quantity
# --------------+----------+-----------+-----------------------
# 4 | 0 | 2 | 0
# 4 | 0 | 5 | 0
@ -85,28 +94,20 @@ class Article < ActiveRecord::Base
# 4 | 5 | 3 | 2
# 4 | 5 | 4 | 2
#
def calculateOrderQuantity(quantity, tolerance = 0)
unitSize = unit_quantity
units = quantity / unitSize
remainder = quantity % unitSize
units += ((remainder > 0) && (remainder + tolerance >= unitSize) ? 1 : 0)
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 active Order, the Order will returned.
def inUse
Order.find(:all, :conditions => 'finished = 0').each do |order|
if order.articles.find_by_id(self)
@order = order
break
end
end
return @order if @order
end
# Checks if the article is in use before it will deleted
def before_destroy
raise self.name.to_s + _(" cannot be deleted. The article is used in a current order!") if self.inUse
# 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_article = order_articles.detect {|oa| oa.article_id == id }
order_article ? order_article.order : nil
end
memoize :in_open_order
# this method checks, if the shared_article has been changed
# unequal attributes will returned in array
@ -132,7 +133,7 @@ class Article < ActiveRecord::Base
:manufacturer => [self.manufacturer, self.shared_article.manufacturer.to_s],
:origin => [self.origin, self.shared_article.origin],
:unit => [self.unit, new_unit],
:net_price => [self.net_price, new_price],
:price => [self.price, new_price],
:tax => [self.tax, self.shared_article.tax],
:deposit => [self.deposit, self.shared_article.deposit],
# take care of different num-objects.
@ -217,4 +218,26 @@ class Article < ActiveRecord::Base
update_attribute :quantity, quantity + amount
end
protected
# Checks if the article is in use before it will deleted
def check_article_in_use
raise self.name.to_s + _(" cannot be deleted. The article is used in a current order!") if self.in_open_order
end
# Create an ArticlePrice, when the price-attr are changed.
def update_price_history
if price_changed?
article_prices.create(
:price => price,
:tax => tax,
:deposit => deposit,
:unit_quantity => unit_quantity
)
end
end
def price_changed?
changed.detect { |attr| attr == 'price' || 'tax' || 'deposit' || 'unit_quantity' } ? true : false
end
end

View file

@ -0,0 +1,29 @@
# == Schema Information
# Schema version: 20090120184410
#
# Table name: article_prices
#
# id :integer(4) not null, primary key
# article_id :integer(4)
# price :decimal(8, 2) default(0.0), not null
# tax :decimal(8, 2) default(0.0), not null
# deposit :decimal(8, 2) default(0.0), not null
# unit_quantity :integer(4)
# created_at :datetime
#
class ArticlePrice < ActiveRecord::Base
belongs_to :article
has_many :order_articles
# The financial gross, net plus tax and deposit.
def gross_price
((price + deposit) * (tax / 100 + 1))
end
# The price for the foodcoop-member.
def fc_price
(gross_price * (APP_CONFIG[:price_markup] / 100 + 1))
end
end

View file

@ -19,7 +19,6 @@ class GroupOrder < ActiveRecord::Base
belongs_to :ordergroup
has_many :group_order_articles, :dependent => :destroy
has_many :order_articles, :through => :group_order_articles
has_many :group_order_article_results
belongs_to :updated_by, :class_name => "User", :foreign_key => "updated_by_user_id"
validates_presence_of :order_id
@ -28,14 +27,17 @@ class GroupOrder < ActiveRecord::Base
validates_numericality_of :price
validates_uniqueness_of :ordergroup_id, :scope => :order_id # order groups can only order once per order
named_scope :open, lambda { {:conditions => ["order_id IN (?)", Order.open.collect{|o| o.id}]} }
named_scope :finished, lambda { {:conditions => ["order_id IN (?)", Order.finished.collect{|o| o.id}]} }
# Updates the "price" attribute.
# This will be the maximum value of a current order
def updatePrice
def update_price!
total = 0
for article in group_order_articles.find(:all, :include => :order_article)
total += article.order_article.article.gross_price * (article.quantity + article.tolerance)
total += article.order_article.article.fc_price * (article.quantity + article.tolerance)
end
self.price = total
update_attribute(:price, total)
end
end

View file

@ -30,8 +30,8 @@ class GroupOrderArticle < ActiveRecord::Base
# and the associated GroupOrderArticleQuantities chronologically.
#
# See description of the ordering algorithm in the general application documentation for details.
def updateQuantities(quantity, tolerance)
logger.debug("GroupOrderArticle[#{id}].updateQuantities(#{quantity}, #{tolerance})")
def update_quantities(quantity, tolerance)
logger.debug("GroupOrderArticle[#{id}].update_quantities(#{quantity}, #{tolerance})")
logger.debug("Current quantity = #{self.quantity}, tolerance = #{self.tolerance}")
# Get quantities ordered with the newest item first.

View file

@ -1,34 +0,0 @@
# == Schema Information
# Schema version: 20090102171850
#
# Table name: group_order_article_results
#
# id :integer(4) not null, primary key
# order_article_result_id :integer(4) default(0), not null
# group_order_result_id :integer(4) default(0), not null
# quantity :decimal(6, 3) default(0.0)
# tolerance :integer(4)
#
# An GroupOrderArticleResult represents a group-order for a single Article and its quantities,
# according to the order quantity/tolerance.
# The GroupOrderArticleResult is part of a finished Order, see OrderArticleResult.
#
class GroupOrderArticleResult < ActiveRecord::Base
belongs_to :order_article_result
belongs_to :group_order_result
validates_presence_of :order_article_result, :group_order_result, :quantity
validates_numericality_of :quantity, :minimum => 0
# updates the price attribute for the appropriate GroupOrderResult
after_update {|result| result.group_order_result.updatePrice }
after_destroy {|result| result.group_order_result.updatePrice }
# Custom attribute setter that accepts decimal numbers using localized decimal separator.
def quantity=(quantity)
self[:quantity] = String.delocalized_decimal(quantity)
end
end

View file

@ -1,26 +0,0 @@
# == Schema Information
# Schema version: 20090102171850
#
# Table name: group_order_results
#
# id :integer(4) not null, primary key
# order_id :integer(4) default(0), not null
# group_name :string(255) default(""), not null
# price :decimal(8, 2) default(0.0), not null
#
# Ordergroups, which participate on a specific order will have a line
class GroupOrderResult < ActiveRecord::Base
belongs_to :order
has_many :group_order_article_results, :dependent => :destroy
# Calculates the Order-Price for the Ordergroup and updates the price-attribute
def updatePrice
total = 0
group_order_article_results.each do |result|
total += result.order_article_result.gross_price * result.quantity
end
update_attribute(:price, total)
end
end

View file

@ -1,5 +1,5 @@
# == Schema Information
# Schema version: 20090113111624
# Schema version: 20090120184410
#
# Table name: invoices
#
@ -13,12 +13,16 @@
# amount :decimal(8, 2) default(0.0), not null
# created_at :datetime
# updated_at :datetime
# order_id :integer(4)
# deposit :decimal(8, 2) default(0.0), not null
# deposit_credit :decimal(8, 2) default(0.0), not null
#
class Invoice < ActiveRecord::Base
belongs_to :supplier
belongs_to :delivery
belongs_to :order
validates_presence_of :supplier_id
validates_uniqueness_of :date, :scope => [:supplier_id]
@ -29,4 +33,14 @@ class Invoice < ActiveRecord::Base
def amount=(amount)
self[:amount] = String.delocalized_decimal(amount)
end
# Custom attribute setter that accepts decimal numbers using localized decimal separator.
def deposit=(deposit)
self[:deposit] = String.delocalized_decimal(deposit)
end
# Custom attribute setter that accepts decimal numbers using localized decimal separator.
def deposit_credit=(deposit)
self[:deposit_credit] = String.delocalized_decimal(deposit)
end
end

View file

@ -1,68 +1,46 @@
# == Schema Information
# Schema version: 20090102171850
# Schema version: 20090120184410
#
# Table name: orders
#
# id :integer(4) not null, primary key
# name :string(255) default(""), not null
# supplier_id :integer(4) default(0), not null
# starts :datetime not null
# supplier_id :integer(4)
# note :text
# starts :datetime
# ends :datetime
# note :string(255)
# finished :boolean(1) not null
# booked :boolean(1) not null
# state :string(255) default("open")
# lock_version :integer(4) default(0), not null
# updated_by_user_id :integer(4)
# invoice_amount :decimal(8, 2) default(0.0), not null
# deposit :decimal(8, 2) default(0.0)
# deposit_credit :decimal(8, 2) default(0.0)
# invoice_number :string(255)
# invoice_date :string(255)
#
class Order < ActiveRecord::Base
extend ActiveSupport::Memoizable # Ability to cache method results. Use memoize :expensive_method
acts_as_ordered :order => "ends" # easyier find of next or previous model
# Associations
has_many :order_articles, :dependent => :destroy
has_many :articles, :through => :order_articles
has_many :group_orders, :dependent => :destroy
has_many :ordergroups, :through => :group_orders
has_many :order_article_results, :dependent => :destroy
has_many :group_order_results, :dependent => :destroy
has_one :invoice
has_many :comments, :class_name => "OrderComment", :order => "created_at"
belongs_to :supplier
belongs_to :updated_by, :class_name => "User", :foreign_key => "updated_by_user_id"
validates_length_of :name, :in => 2..50
validates_presence_of :starts
validates_presence_of :supplier_id
validates_inclusion_of :finished, :in => [true, false]
validates_numericality_of :invoice_amount, :deposit, :deposit_credit
# Validations
validates_presence_of :supplier_id, :starts
validate_on_create :starts_before_ends, :include_articles
validate_on_create :include_articles
# Callbacks
after_update :update_price_of_group_orders
# attr_accessible :name, :supplier, :starts, :ends, :note, :invoice_amount, :deposit, :deposit_credit, :invoice_number, :invoice_date
#use plugin to make Order commentable
acts_as_commentable
# easyier find of next or previous model
acts_as_ordered :order => "ends"
named_scope :finished, :conditions => { :finished => true },
:order => 'ends DESC', :include => :supplier
# Custom attribute setter that accepts decimal numbers using localized decimal separator.
def invoice_amount=(amount)
self[:invoice_amount] = String.delocalized_decimal(amount)
end
# Custom attribute setter that accepts decimal numbers using localized decimal separator.
def deposit=(deposit)
self[:deposit] = String.delocalized_decimal(deposit)
end
# Custom attribute setter that accepts decimal numbers using localized decimal separator.
def deposit_credit=(deposit)
self[:deposit_credit] = String.delocalized_decimal(deposit)
end
# Finders
named_scope :finished, :conditions => { :state => 'finished' },
:order => 'ends DESC'
named_scope :open, :conditions => { :state => 'open' },
:order => 'ends DESC'
named_scope :closed, :conditions => { :state => 'closed' },
:order => 'ends DESC'
# Create or destroy OrderArticle associations on create/update
def article_ids=(ids)
@ -76,201 +54,122 @@ class Order < ActiveRecord::Base
end
end
# Returns all current orders, i.e. orders that are not finished and the current time is between the order's start and end time.
def self.find_current
find(:all, :conditions => ['finished = ? AND starts < ? AND (ends IS NULL OR ends > ?)', false, Time.now, Time.now], :order => 'ends desc', :include => :supplier)
def open?
state == "open"
end
# Returns true if this is a current order (not finished and current time matches starts/ends).
def current?
!finished? && starts < Time.now && (!ends || ends > Time.now)
def finished?
state == "finished"
end
# Returns all finished or expired orders, exclude booked orders
def self.find_finished
find(:all, :conditions => ['(finished = ? OR ends < ?) AND booked = ?', true, Time.now, false], :order => 'ends desc', :include => :supplier)
end
# Return all booked Orders
def self.find_booked
find :all, :conditions => ['booked = ?', true], :order => 'ends desc', :include => :supplier
def closed?
state == "closed"
end
# search GroupOrder of given Ordergroup
def group_order(ordergroup)
unless finished
return group_orders.detect {|o| o.ordergroup_id == ordergroup.id}
else
return group_order_results.detect {|o| o.group_name == ordergroup.name}
end
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]]]
def get_articles
articles= order_articles.find :all, :include => :article, :order => "articles.name"
articles_by_category= Hash.new
ArticleCategory.find(:all).each do |category|
articles_by_category.merge!(category.name.to_s => articles.select {|order_article| order_article.article.article_category == category})
end
# add articles without a category
articles_by_category.merge!( "--" => articles.select {|order_article| order_article.article.article_category == nil})
# return "clean" hash, sorted by category.name
return articles_by_category.reject {|category, order_articles| order_articles.empty?}.sort
# it could be so easy ... but that doesn't work for empty category-ids...
# order_articles.group_by {|a| a.article.article_category}.sort {|a, b| a[0].name <=> b[0].name}
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
# Returns the defecit/benefit for the foodcoop
def fcProfit(with_markup = true)
groups_sum = with_markup ? sumPrice("groups") : sumPrice("groups_without_markup")
def profit(with_markup = true)
groups_sum = with_markup ? sum(:groups) : sum(:groups_without_markup)
groups_sum - invoice_amount + deposit - deposit_credit
end
# Returns the all round price of a finished order
# "groups" returns the sum of all GroupOrderResults
# "clear" returns the price without tax, deposit and markup
# "gross" includes tax and deposit. this amount should be equal to suppliers bill
# "fc", guess what...
# for unfinished orders it returns the gross price
def sumPrice(type = "gross")
sum = 0
if finished?
if type == "groups"
for groupResult in group_order_results
for result in groupResult.group_order_article_results
sum += result.order_article_result.gross_price * result.quantity
end
end
elsif type == "groups_without_markup"
for groupResult in group_order_results
for result in groupResult.group_order_article_results
oar = result.order_article_result
sum += (oar.net_price + oar.deposit) * (1 + oar.tax/100) * result.quantity
end
end
else
for article in order_article_results
# :groups returns the sum of all GroupOrders
# :clear returns the price without tax, deposit and markup
# :gross includes tax and deposit. this amount should be equal to suppliers bill
# :fc, guess what...
def sum(type = :gross)
total = 0
if type == :clear || 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'
sum += article.units_to_order * article.unit_quantity * article.net_price
when 'gross'
sum += article.units_to_order * article.unit_quantity * (article.net_price + article.deposit) * (article.tax / 100 + 1)
when "fc"
sum += article.units_to_order * article.unit_quantity * article.gross_price
when :clear
total += quantity * oa.price.price
when :gross
total += quantity * oa.price.gross_price
when :fc
total += quantity * oa.price.fc_price
end
end
elsif type == :groups || type == :groups_without_markup
for go in group_orders
for goa in go.group_order_articles
case type
when :groups
total += goa.quantity * goa.order_article.price.fc_price
when :groups_without_markup
total += goa.quantity * goa.order_article.price.gross_price
end
end
end
else
for article in order_articles
sum += article.units_to_order * article.article.gross_price * article.article.unit_quantity
end
end
sum
total
end
# Finishes this order. This will set the finish property to "true" and the end property to the current time.
# Finishes this order. This will set the order state to "finish" and the end property to the current time.
# Ignored if the order is already finished.
# this will also copied the results into OrderArticleResult, GroupOrderArticleResult and GroupOrderResult
def finish(user)
def finish!(user)
unless finished?
transaction do
#saves ordergroups, which take part in this order
self.group_orders.each do |go|
group_order_result = GroupOrderResult.create!(:order => self,
:group_name => go.ordergroup.name,
:price => go.price)
Order.transaction do
# Update order_articles. Save the current article_price to keep price consistency
order_articles.all(:include => :article).each do |oa|
oa.update_attribute(:article_price, oa.article.article_prices.first)
end
# saves every article of the order
self.get_articles.each do |category, articles|
articles.each do |oa|
if oa.units_to_order >= 1 # save only successful ordered articles!
article_result = OrderArticleResult.new(:order => self,
:name => oa.article.name,
:unit => oa.article.unit,
:net_price => oa.article.net_price,
:gross_price => oa.article.gross_price,
:tax => oa.article.tax,
:deposit => oa.article.deposit,
:fc_markup => APP_CONFIG[:price_markup],
:order_number => oa.article.order_number,
:unit_quantity => oa.article.unit_quantity,
:units_to_order => oa.units_to_order)
article_result.save
# saves the ordergroup results, belonging to the saved orderd article
oa.group_order_articles.each do |goa|
result = goa.orderResult
# find appropriate GroupOrderResult
group_order_result = GroupOrderResult.find(:first, :conditions => ['order_id = ? AND group_name = ?', self.id, goa.group_order.ordergroup.name])
group_order_article_result = GroupOrderArticleResult.new(:order_article_result => article_result,
:group_order_result => group_order_result,
:quantity => result[:total],
:tolerance => result[:tolerance])
group_order_article_result.save! if (group_order_article_result.quantity > 0)
# 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 ? ...
end
end
end
end
# set new order state (needed by notifyOrderFinished)
self.finished = true
self.ends = Time.now
self.updated_by = user
# delete data, which is no longer required, because everything is now in the result-tables
self.group_orders.each do |go|
go.destroy
end
self.order_articles.each do |oa|
oa.destroy
end
self.save!
# Update all GroupOrder.price
self.updateAllGroupOrders
# notify order groups
notifyOrderFinished
end
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.
def updateQuantities
orderArticles = Hash.new # holds the list of updated OrderArticles indexed by their id
# 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...
articles = GroupOrderArticle.find(:all, :conditions => ['group_order_id IN (?)', group_orders.collect { | o | o.id }], :include => [:order_article])
for article in articles
if (orderArticle = orderArticles[article.order_article.id.to_s])
# OrderArticle has already been fetched, just update...
orderArticle.quantity = orderArticle.quantity + article.quantity
orderArticle.tolerance = orderArticle.tolerance + article.tolerance
orderArticle.units_to_order = orderArticle.article.calculateOrderQuantity(orderArticle.quantity, orderArticle.tolerance)
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...
orderArticle = article.order_article
orderArticle.quantity = article.quantity
orderArticle.tolerance = article.tolerance
orderArticle.units_to_order = orderArticle.article.calculateOrderQuantity(orderArticle.quantity, orderArticle.tolerance)
orderArticles[orderArticle.id.to_s] = orderArticle
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
orderArticles.each_value { | value | value.save! }
end
end
# Updates the "price" attribute of GroupOrders or GroupOrderResults
# This will be either the maximum value of a current order or the actual order value of a finished order.
def updateAllGroupOrders
unless finished?
group_orders.each do |groupOrder|
groupOrder.updatePrice
groupOrder.save
end
else #for finished orders
group_order_results.each do |groupOrderResult|
groupOrderResult.updatePrice
end
indexed_order_articles.each_value { | value | value.save! }
end
end
@ -290,46 +189,37 @@ class Order < ActiveRecord::Base
end
end
# returns the corresponding message for the status
def status
if !self.finished? && self.ends > Time.now
_("running")
elsif !self.finished? && self.ends < Time.now
_("expired")
elsif self.finished? && !self.booked?
_("finished")
else
_("balanced")
end
end
protected
def validate
def starts_before_ends
errors.add(:ends, "muss nach dem Bestellstart liegen (oder leer bleiben)") if (ends && starts && ends <= starts)
end
def include_articles
errors.add(:order_articles, _("There must be at least one article selected")) if order_articles.empty?
errors.add(:order_articles, "Es muss mindestens ein Artikel ausgewählt sein") if order_articles.empty?
end
private
# Updates the "price" attribute of GroupOrders or GroupOrderResults
# This will be either the maximum value of a current order or the actual order value of a finished order.
def update_price_of_group_orders
group_orders.each { |group_order| group_order.update_price! }
end
# Sends "order finished" messages to users who have participated in this order.
def notifyOrderFinished
# Loop through GroupOrderResults for this order:
for group_order in self.group_order_results
ordergroup = Ordergroup.find_by_name(group_order.group_name)
# Determine group users that want a notification message:
def notify_order_finished
for group_order in self.group_orders
ordergroup = group_order.ordergroup
logger.debug("Send 'order finished' message to #{ordergroup.name}")
# Determine users that want a notification message:
users = ordergroup.users.reject{|u| u.settings["notify.orderFinished"] != '1'}
unless users.empty?
# Assemble the order message text:
results = group_order.group_order_article_results.find(:all, :include => [:order_article_result])
# Create user notification messages:
Message.from_template(
'order_finished',
{:group => ordergroup, :order => self, :results => results, :total => group_order.price},
{:recipients_ids => users.collect(&:id), :subject => "Bestellung beendet: #{self.name}"}
{:group => ordergroup, :order => self, :group_order => group_order},
{:recipients_ids => users.collect(&:id), :subject => "Bestellung beendet: #{supplier.name}"}
).save!
end
end

View file

@ -1,5 +1,5 @@
# == Schema Information
# Schema version: 20090102171850
# Schema version: 20090120184410
#
# Table name: order_articles
#
@ -10,6 +10,7 @@
# tolerance :integer(4) default(0), not null
# units_to_order :integer(4) default(0), not null
# lock_version :integer(4) default(0), not null
# article_price_id :integer(4)
#
# An OrderArticle represents a single Article that is part of an Order.
@ -17,16 +18,25 @@ class OrderArticle < ActiveRecord::Base
belongs_to :order
belongs_to :article
belongs_to :article_price
has_many :group_order_articles, :dependent => :destroy
validates_presence_of :order_id
validates_presence_of :article_id
validates_uniqueness_of :article_id, :scope => :order_id # an article can only have one record per order
named_scope :ordered, :conditions => "units_to_order >= 1"
# This method returns either the Article or the ArticlePrice
# The latter will be set, when the the order is finished
def price
article_price || article
end
private
def validate
errors.add(:article, "muss angegeben sein und einen aktuellen Preis haben") if !(article = Article.find(article_id)) || article.gross_price.nil?
errors.add(:article, "muss angegeben sein und einen aktuellen Preis haben") if !(article = Article.find(article_id)) || article.fc_price.nil?
end
end

View file

@ -1,78 +0,0 @@
# == Schema Information
# Schema version: 20090102171850
#
# Table name: order_article_results
#
# id :integer(4) not null, primary key
# order_id :integer(4) default(0), not null
# name :string(255) default(""), not null
# unit :string(255) default(""), not null
# note :string(255)
# net_price :decimal(8, 2) default(0.0)
# gross_price :decimal(8, 2) default(0.0), not null
# tax :float default(0.0), not null
# deposit :decimal(8, 2) default(0.0)
# fc_markup :float default(0.0), not null
# order_number :string(255)
# unit_quantity :integer(4) default(0), not null
# units_to_order :decimal(6, 3) default(0.0), not null
#
# An OrderArticleResult represents a single Article that is part of a *finished* Order.
class OrderArticleResult < ActiveRecord::Base
belongs_to :order
has_many :group_order_article_results, :dependent => :destroy
validates_presence_of :name, :unit, :net_price, :gross_price, :tax, :deposit, :fc_markup, :unit_quantity, :units_to_order
validates_numericality_of :net_price, :gross_price, :deposit, :unit_quantity, :units_to_order
validates_length_of :name, :minimum => 4
def make_gross # calculate the gross price and sets the attribute
self.gross_price = ((net_price + deposit) * (tax / 100 + 1) * (fc_markup / 100 + 1))
end
# Custom attribute setter that accepts decimal numbers using localized decimal separator.
def net_price=(net_price)
self[:net_price] = String.delocalized_decimal(net_price)
end
# Custom attribute setter that accepts decimal numbers using localized decimal separator.
def tax=(tax)
self[:tax] = String.delocalized_decimal(tax)
end
# Custom attribute setter that accepts decimal numbers using localized decimal separator.
def deposit=(deposit)
self[:deposit] = String.delocalized_decimal(deposit)
end
# Custom attribute setter that accepts decimal numbers using localized decimal separator.
def units_to_order=(units_to_order)
self[:units_to_order] = String.delocalized_decimal(units_to_order)
end
# counts from every GroupOrderArticleResult for this ArticleResult
# Return a hash with the total quantity (in Article-units) and the total (FC) price
def total
quantity = 0
price = 0
for result in self.group_order_article_results
quantity += result.quantity
price += result.quantity * self.gross_price
end
return {:quantity => quantity, :price => price}
end
# updates the price attribute for all appropriate GroupOrderResults
def after_update
group_order_article_results.each {|result| result.group_order_result.updatePrice}
end
protected
def validate
errors.add(:net_price, "should be positive") unless net_price.nil? || net_price > 0
end
end

View file

@ -0,0 +1,19 @@
# == Schema Information
# Schema version: 20090120184410
#
# Table name: order_comments
#
# id :integer(4) not null, primary key
# order_id :integer(4)
# user_id :integer(4)
# text :text
# created_at :datetime
#
class OrderComment < ActiveRecord::Base
belongs_to :order
belongs_to :user
validates_presence_of :order_id, :user_id, :text
end

View file

@ -30,45 +30,33 @@
# * account_updated (datetime)
# * actual_size (int) : how many persons are ordering through the Ordergroup
class Ordergroup < Group
has_many :financial_transactions, :dependent => :destroy
has_many :group_orders, :dependent => :destroy
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 :group_orders
has_many :orders, :through => :group_orders
has_many :group_order_article_results, :through => :group_orders # TODO: whats this???
has_many :group_order_results, :finder_sql => 'SELECT * FROM group_order_results as r WHERE r.group_name = "#{name}"'
validates_inclusion_of :actual_size, :in => 1..99
validates_numericality_of :account_balance, :message => 'ist keine gültige Zahl'
attr_accessible :actual_size, :account_updated
# messages
ERR_NAME_IS_USED_IN_ARCHIVE = "Der Name ist von einer ehemaligen Gruppe verwendet worden."
# if the ordergroup.name is changed, group_order_result.name has to be adapted
def before_update
ordergroup = Ordergroup.find(self.id)
unless (ordergroup.name == self.name) || ordergroup.group_order_results.empty?
# rename all finished orders
for result in ordergroup.group_order_results
result.update_attribute(:group_name, self.name)
end
end
def value_of_open_orders(exclude = nil)
group_orders.open.reject{|go| go == exclude}.collect(&:price).sum
end
# Returns the available funds for this order group (the account_balance minus price of all non-booked GroupOrders of this group).
# * excludeGroupOrder (GroupOrder): exclude this GroupOrder from the calculation
def getAvailableFunds(excludeGroupOrder = nil)
funds = account_balance
for order in GroupOrder.find_all_by_ordergroup_id(self.id)
unless order == excludeGroupOrder
funds -= order.price
def value_of_finished_orders(exclude = nil)
group_orders.finished.reject{|go| go == exclude}.collect(&:price).sum
end
# Returns the available funds for this order group (the account_balance minus price of all non-closed GroupOrders of this group).
# * exclude (GroupOrder): exclude this GroupOrder from the calculation
def get_available_funds(exclude = nil)
account_balance - value_of_open_orders(exclude) - value_of_finished_orders(exclude)
end
for order_result in self.findFinishedNotBooked
funds -= order_result.price
end
return funds
end
memoize :get_available_funds
# Creates a new FinancialTransaction for this Ordergroup and updates the account_balance accordingly.
# Throws an exception if it fails.
@ -129,13 +117,4 @@ class Ordergroup < Group
end
end
# before create or update, check if the name is already used in GroupOrderResults
def validate_on_create
errors.add(:name, ERR_NAME_IS_USED_IN_ARCHIVE) unless GroupOrderResult.find_all_by_group_name(self.name).empty?
end
def validate_on_update
ordergroup = Ordergroup.find(self.id)
errors.add(:name, ERR_NAME_IS_USED_IN_ARCHIVE) unless ordergroup.name == self.name || GroupOrderResult.find_all_by_group_name(self.name).empty?
end
end

View file

@ -43,7 +43,7 @@ class Supplier < ActiveRecord::Base
# 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.gross_price}
articles.select {|article| article.fc_price}
end
# sync all articles with the external database
@ -66,10 +66,10 @@ class Supplier < ActiveRecord::Base
# try to convert different units
new_price, new_unit_quantity = article.convert_units
if new_price and new_unit_quantity
article.net_price = new_price
article.price = new_price
article.unit_quantity = new_unit_quantity
else
article.net_price = shared_article.price
article.price = shared_article.price
article.unit_quantity = shared_article.unit_quantity
article.unit = shared_article.unit
end

View file

@ -10,8 +10,8 @@
<td><%= @article.unit_quantity -%></td>
<td class="currency">
<acronym title="zuletzt geändert: <%= format_date(@article.updated_at) -%>
| Brutto: <%= number_to_currency(@article.gross_price) -%>">
<%= number_to_currency(@article.net_price) -%>
| Brutto: <%= number_to_currency(@article.fc_price) -%>">
<%= number_to_currency(@article.price) -%>
</acronym>
</td>
<td><%= number_to_percentage(@article.tax) if @article.tax != 0 -%></td>

View file

@ -31,7 +31,7 @@
%th Pfand
%tbody
%tr
%td= form.text_field :net_price, :size => 5
%td= form.text_field :price, :size => 5
%td= form.text_field :unit_quantity, :size => 5
%td= form.text_field :order_number, :size => 10
%td= form.text_field :tax, :size => 5

View file

@ -44,7 +44,7 @@
<%= form.text_field 'name', :size => 0 -%>
</td>
<td><%= form.text_field 'unit', :size => 5 -%></td>
<td><%= form.text_field 'net_price', :size => 4 -%></td>
<td><%= form.text_field 'price', :size => 4 -%></td>
<td><%= form.text_field 'unit_quantity', :size => 4 -%></td>
<td><%= form.text_field 'order_number', :size => 6 -%></td>
<td><%= form.text_field 'note', :size => 15 -%></td>

View file

@ -28,7 +28,7 @@
%td= form.text_field 'manufacturer', :size => 6
%td= form.text_field 'origin', :size => 6
%td= form.text_field 'unit', :size => 5
%td= form.text_field 'net_price', :size => 4
%td= form.text_field 'price', :size => 4
%td= form.text_field 'tax', :size => 4
%td= form.text_field 'deposit', :size => 4
%td= form.text_field 'unit_quantity', :size => 4

View file

@ -46,7 +46,7 @@
%td= article.origin
%td= article.unit
%td= article.unit_quantity
%td= article.net_price
%td= article.price
%td= article.tax
%td= article.deposit
%td= article.article_category.name if article.article_category
@ -60,7 +60,7 @@
%td{:style => highlight_new(unequal_attributes, :origin)}= form.text_field 'origin', :size => 5
%td{:style => highlight_new(unequal_attributes, :unit)}= form.text_field 'unit', :size => 5
%td{:style => highlight_new(unequal_attributes, :unit_quantity)}= form.text_field 'unit_quantity', :size => 5
%td{:style => highlight_new(unequal_attributes, :net_price)}= form.text_field 'net_price', :size => 5
%td{:style => highlight_new(unequal_attributes, :price)}= form.text_field 'price', :size => 5
%td{:style => highlight_new(unequal_attributes, :tax)}= form.text_field 'tax', :size => 4
%td{:style => highlight_new(unequal_attributes, :deposit)}= form.text_field 'deposit', :size => 4
%td= select 'article[]', 'article_category_id', ArticleCategory.find(:all).collect {|a| [ a.name, a.id ] }, { :include_blank => true }

View file

@ -3,8 +3,8 @@
%td= @article.order_number
%td= @article.units_to_order
%td= @article.unit_quantity.to_s + ' * ' + @article.unit.to_s
%td= number_to_currency(@article.net_price)
%td= number_to_currency(@article.gross_price)
%td= number_to_currency(@article.price)
%td= number_to_currency(@article.fc_price)
%td= @article.tax
%td= @article.deposit
%td

View file

@ -19,7 +19,7 @@
%td= @form.text_field 'units_to_order', :size => 5
%td= @form.text_field 'unit_quantity', :size => 3
%td= @form.text_field 'unit', :size => 5
%td= @form.text_field 'net_price', :size => 3
%td= @form.text_field 'price', :size => 3
%td= @form.text_field 'tax', :size => 3
%td= @form.text_field 'deposit', :size => 3
= @form.hidden_field "order_id"

View file

@ -6,12 +6,12 @@
%table{:style=> "margin-bottom:1em; width:40em;"}[article]
%thead
%tr
%th{:colspan => "3"}= article.name + " (" + article.unit + " | " + article.unit_quantity.to_s + " | " + article.gross_price.to_s + ")"
%th{:colspan => "3"}= article.name + " (" + article.unit + " | " + article.unit_quantity.to_s + " | " + article.fc_price.to_s + ")"
%tbody
- for result in article.group_order_article_results
%tr{ :class => cycle('even', 'odd', :name => 'group')}
%td{:style=>"width:70%"}= result.group_order_result.group_name
%td= result.quantity
%td= article.gross_price * result.quantity
%td= article.fc_price * result.quantity
- reset_cycle("group")

View file

@ -1,7 +1,7 @@
%td
%td{:style=>"width:50%"}= @result.group_order_result.group_name
%td{:id => "group_order_article_result_#{@result.id}_quantity"}= @result.quantity
%td{:class => "currency"}= number_to_currency(@result.order_article_result.gross_price * @result.quantity)
%td{:class => "currency"}= number_to_currency(@result.order_article_result.fc_price * @result.quantity)
%td{:style=>"width:1em", :class => "actions"}
= link_to_remote image_tag('b_edit.png', :size => "16x16", :border => 0, :alt => 'Menge ändern'), |
:url => {:action => 'updateGroupResult', :id => @result}, |

View file

@ -11,7 +11,7 @@
%tbody
- total = 0
- for result in groupOrderResult.group_order_article_results
- price = result.order_article_result.gross_price
- price = result.order_article_result.fc_price
- quantity = result.quantity
- subTotal = price * quantity
- total += subTotal

View file

@ -18,7 +18,7 @@
%tr
%td
%abbr{:title => "gelieferten Artikel x Nettopreis"} Nettobetrag:
%td= number_to_currency(@order.sumPrice("clear"))
%td= number_to_currency(@order.sum(:clear))
%td
Rechnungsbetrag
%small (incl. Pfand/Gutschriften)
@ -26,7 +26,7 @@
%tr
%td
%abbr{:title => "Nettobetrag mit Pfand und MwSt."} Bruttobetrag:
%td= number_to_currency(@order.sumPrice("gross"))
%td= number_to_currency(@order.sum(:gross))
%td
%span - extra Pfand
%small (Kistenpfand etc.)
@ -34,7 +34,7 @@
%tr
%td
%abbr{:title => "Bruttobetrag mit Foodcoop Aufschlag"} FC Summe:
%td= number_to_currency(@order.sumPrice("fc"))
%td= number_to_currency(@order.sum(:fc))
%td{:style => "border-bottom: 1px solid grey"}
+ Pfandgutschriften
%td{:style => "border-bottom: 1px solid grey"}
@ -42,7 +42,7 @@
%tr
%td
%abbr{:title => "Zugeteilte Mengen x Bruttopreise (inkl. Aufschlag)"} Gruppenbeträge:
%td#groups_amount= number_to_currency(@order.sumPrice("groups"))
%td#groups_amount= number_to_currency(@order.sum(:groups))
%td
Summe
%small (Rechungsbetrag ohne Pfand)
@ -51,10 +51,10 @@
%td{:colspan => "4"}
%abbr{:title => "Gruppenbeträge ohne Aufschlag minus Rechnung ohne Pfand. |
Im Idealfall sollte hier 0.00 stehen."} Differenz ohne Aufschlag: |
%span#fcProfit= number_to_currency(@order.fcProfit(false))
%span#profit= number_to_currency(@order.profit(false))
%tr
%td{:colspan => "4"}
%b
%abbr{:title => "= Gruppenbeträge - Rechnung ohne Pfand"} Differenz mit Aufschlag
= "(#{number_to_percentage(APP_CONFIG[:price_markup])}):"
%span#fcProfit= number_to_currency(@order.fcProfit)
%span#profit= number_to_currency(@order.profit)

View file

@ -55,9 +55,9 @@
%tbody
- @orders.each do |order|
%tr{:class => cycle("even","odd", :name => "order")}
%td= order.name
%td= order.supplier.name
%td= format_date(order.ends)
%td{:class => "currency"}= number_to_currency(order.sumPrice("fc"))
%td{:class => "currency"}= number_to_currency(order.sum(:fc))
%td= link_to "abrechnen", :action => "editOrder", :id => order
- else
Super, alles schon abgerechnet...

View file

@ -23,13 +23,13 @@
%tbody
- @orders.each do |order|
%tr{:class => cycle("even","odd", :name => "order")}
%td= link_to truncate(order.name), :action => "new", :id => order
%td= link_to truncate(order.supplier.name), :action => "new", :id => order
%td=h order.supplier ? order.supplier.name : _('nonexistent')
%td=h format_time(order.ends) unless order.ends.nil?
%td= order.booked ? "abgerechnet (#{number_to_currency order.fcProfit})" : "beendet"
%td= order.closed? ? "abgerechnet (#{number_to_currency order.profit})" : "beendet"
%td= order.updated_by.nil? ? '??' : order.updated_by.nick
%td
- unless order.booked
- unless order.closed?
= link_to "abrechnen", :action => "new", :id => order
|
= link_to 'auf "gebucht" setzen', {:action => 'setAllBooked', :id => order}, :confirm => 'Wirklich alle Gruppenbestellungen für diese Bestellung auf "gebucht" setzen?', :method => "post"

View file

@ -1,12 +1,12 @@
%h1 Bestellung abrechnen
- if @order.booked
- if @order.closed?
%p
%b Achtung, Bestellung wurde schon abgerechnet!
.left_column{:style => 'width: 50em'}
.box_title
%h2
= @order.name + " | " + format_date(@order.starts) + ' --> ' + format_date(@order.ends)
= @order.supplier.name + " | " + format_date(@order.starts) + ' --> ' + format_date(@order.ends)
.column_content#summary
#order_summary
= render :partial => "summary"
@ -15,7 +15,7 @@
%h2 Aktionen
.column_content
%ul
- unless @order.booked
- unless @order.closed?
%li= link_to "Bestellung abschließen", :action => "confirm", :id => @order
.right_column{:style => 'clear:both;width: 28%'}

View file

@ -27,7 +27,7 @@
= _("There are") + " #{@unassigned_tasks_number} " + link_to(_("unassigned task(s)"), :controller => "tasks")
%p{:style => "clear:both"}= link_to _("My tasks"), :controller => "tasks", :action => "myTasks"
- if @orderGroup
- if @ordergroup
// Current orders
= render :partial => 'ordering/currentOrders'
@ -42,13 +42,13 @@
%h2=_ "My ordergroup"
.column_content
%p
%b= @orderGroup.name
%b= @ordergroup.name
|
=_ "Account balance:"
= number_to_currency(@orderGroup.account_balance)
= number_to_currency(@ordergroup.account_balance)
%span{:style => "color:grey"}
(zuletzt aktualisiert vor
= distance_of_time_in_words(Time.now, @orderGroup.account_updated) + ")"
= distance_of_time_in_words(Time.now, @ordergroup.account_updated) + ")"
%h3=_ "Last transactions"
%table
%tr

View file

@ -1,13 +1,13 @@
Liebe <%= group.name %>,
die Bestellung "<%= order.name %>" wurde am <%= order.ends.strftime('%d.%m.%Y um %H:%M') %> von <%= order.updated_by.nick %> beendet.
die Bestellung für "<%= order.supplier.name %>" wurde am <%= order.ends.strftime('%d.%m.%Y um %H:%M') %> von <%= order.updated_by.nick %> beendet.
Für Euch wurden die folgenden Artikel bestellt:
<% for result in results
article = result.order_article_result -%>
<%= article.name %>: <%= result.quantity %> x <%= article.unit %> = <%= result.quantity * article.gross_price %>
<% for group_order_article in group_order.group_order_articles.all(:include => :order_article)
article = group_order_article.order_article.article -%>
<%= article.name %>: <%= group_order_article.quantity %> x <%= article.unit %> = <%= group_order_article.quantity * article.fc_price %>
<% end -%>
Gesamtpreis: <%= total %>
Gesamtpreis: <%= group_order.price %>
Bestellung online einsehen: <%= ApplicationController.current.url_for(:controller => 'ordering', :action => 'my_order_result', :id => order.id) %>

View file

@ -1,31 +0,0 @@
- if controller.action_name == 'myOrders'
= pagination_links_remote @bookedOrders, :per_page => 10, :params => {:show_all => params[:show_all]}
%table.list
%thead
%tr
%th=_ 'Name'
%th=_ 'Supplier'
%th=_ 'End'
%th=_ 'Sum'
%tbody
- @bookedOrders.each do |order|
- if order.is_a?(GroupOrder) || order.is_a?(GroupOrderResult)
%tr{:class=> cycle('even', 'odd', :name => 'bookedOrders')}
%td= link_to order.order.name, :action => 'my_order_result', :id => order.order
%td=h order.order.supplier ? order.order.supplier.name : _("nonexistent")
%td= format_time(order.order.ends)
%td{:class => "currency"}= number_to_currency(order.price)
- else
// check if the Ordergroup has ordered
- if groupOrder = order.group_order(@orderGroup)
%tr{:class=> cycle('even', 'odd', :name => 'bookedOrders')}
%td= link_to order.name, :action => 'my_order_result', :id => order
%td=h order.supplier ? order.supplier.name : _("nonexistent")
%td= format_time(order.ends)
%td{:class => "currency"}= number_to_currency(groupOrder.price)
- else
%tr{:class=> cycle('even', 'odd', :name => 'bookedOrders'), :style => "color:grey"}
%td= link_to truncate(order.name), {:action => "my_order_result", :id => order}, :style => "color:grey"
%td= order.supplier ? order.supplier.name : _("nonexistent")
%td= format_time(order.ends)
%td{:class => "currency"} --

View file

@ -1,32 +0,0 @@
.box_title
%h2=_ "Running orders"
.column_content
- unless @currentOrders.empty?
%table.list
%thead
%tr
%th=_ "Name"
%th=_ "Supplier"
%th=_ "End"
%th=_ "Who ordered?"
%th=_ "Sum"
%tbody
- total = 0
- @currentOrders.each do |order|
%tr{:class => cycle('even', 'odd', :name => 'current_orders')}
%td= link_to order.name, :controller => 'ordering', :action => 'order', :id => order
%td=h order.supplier.name
%td=h format_time(order.ends) unless order.ends.nil?
- if (groupOrder = order.group_orders.find(:first, :conditions => ["ordergroup_id = ?", @orderGroup.id]))
- total += groupOrder.price
%td=h groupOrder.updated_by.nil? ? '??' : "#{groupOrder.updated_by.nick} (#{format_time(groupOrder.updated_on)})"
%td= number_to_currency(groupOrder.price)
- else
%td
%td
- if total > 0
%p
=_ "Total sum"
%b= number_to_currency(total)
- else
%i=_ "There aren't current orders at the moment."

View file

@ -1,30 +0,0 @@
%table.list
%thead
%tr
%th=_ 'Name'
%th=_ 'Supplier'
%th=_ 'End'
%th=_ 'Sum'
%tbody
- @finishedOrders.each do |order|
- if order.is_a?(GroupOrder) or order.is_a?(GroupOrderResult)
%tr{:class=> cycle('even', 'odd', :name => 'bookedOrders')}
%td= link_to order.order.name, :action => 'my_order_result', :id => order.order
%td=h order.order.supplier ? order.order.supplier.name : _("nonexistent")
%td= format_time(order.order.ends)
%td{:class => "currency"}= number_to_currency(order.price)
- else
// check if the Ordergroup has ordered
- if groupOrder = order.group_order(@orderGroup)
%tr{:class=> cycle('even', 'odd', :name => 'finishedOrders')}
%td= link_to order.name, :action => 'my_order_result', :id => order
%td=h order.supplier ? order.supplier.name : _("nonexistent")
%td= format_time(order.ends)
%td{:class => "currency"}= number_to_currency(groupOrder.price)
- else
%tr{:class=> cycle('even', 'odd', :name => 'finishedOrders'), :style => "color:grey"}
%td= link_to truncate(order.name), {:action => "my_order_result", :id => order}, :style => "color:grey"
%td= order.supplier ? order.supplier.name : _("nonexistent")
%td= format_time(order.ends)
%td{:class => "currency"} --

View file

@ -1,33 +0,0 @@
%table.list
%thead
%tr
%th{:style => "width:40%"}=_ "Name"
%th=_ "Unit quantity"
%th=_ "Unit price"
%th=_ "Received"
%th=_ "Total price"
%tbody
- for article in @groupOrderResult.group_order_article_results
- price = article.order_article_result.gross_price
- quantity = article.quantity
%tr{:class => cycle('even', 'odd', :name => 'articles')}
%td{:style=>"width:40%"}
=h article.order_article_result.name
- unless article.order_article_result.note.nil?
= image_tag "lamp_grey.png", {:alt => "Notiz anzeigen", :size => "15x16", :border => "0", :onmouseover => "$('note_#{article.id}').show();", :onmouseout => "$('note_#{article.id}').hide();" }
%td
= article.order_article_result.unit_quantity
x
= article.order_article_result.unit
%td= number_to_currency(price)
%td= quantity
%td= number_to_currency(quantity * price)
- unless article.order_article_result.note.nil?
%tr{:id => "note_#{article.id}", :style => "display:none"}
%td{:colspan => "5"}
Notiz:
=h article.order_article_result.note
%tr{:class => cycle('even', 'odd', :name => 'articles')}
%th{:colspan => "4"}=_ "Sum"
%th= number_to_currency(@groupOrderResult.price)

View file

@ -0,0 +1,30 @@
.box_title
%h2 Laufende Bestellungen
.column_content
- unless Order.open.empty?
%table.list
%thead
%tr
%th Lieferant
%th Ende
%th Wer hat bestellt?
%th Summe
%tbody
- total = 0
- Order.open.each do |order|
%tr{:class => cycle('even', 'odd', :name => 'open_orders')}
%td= link_to h(order.supplier.name), :controller => 'ordering', :action => 'order', :id => order
%td=h format_time(order.ends) unless order.ends.nil?
- if group_order = order.group_order(@ordergroup)
- total += group_order.price
%td=h "#{group_order.updated_by.nick} (#{format_time(group_order.updated_on)})"
%td= number_to_currency(group_order.price)
- else
%td
%td
- if total > 0
%p
Gesamtsumme:
%b= number_to_currency(total)
- else
%i Derzeit gibt es keine laufenden Bestellungen

View file

@ -0,0 +1,17 @@
- if controller.action_name == 'myOrders'
= pagination_links_remote @closed_orders, :per_page => 10, :update => 'closed_orders'
%table.list
%thead
%tr
%th Lieferant
%th Ende
%th Summe
%tbody
- for order in orders
- group_order = order.group_order(@ordergroup) # Get GroupOrder if possible
- order_class = group_order ? "" : "color:grey"
%tr{:class=> cycle('even', 'odd', :name => 'orders'), :style => order_class}
%td= link_to order.supplier.name, :action => 'my_order_result', :id => order
%td= format_time(order.ends)
%td{:class => "currency"}= group_order ? number_to_currency(group_order.price) : "--"

View file

@ -1,54 +0,0 @@
%table.list
%thead
%tr
%th{:style => "width:40%"} Name
%th Gebinde
%th Einzelpreis
%th
%abbr{:title => "Menge + Toleranz"} Bestellt
%th
%abbr{:title => "Unter Berücksichtigung der anderen Gruppen"} Zugeteilt
%th Gesamtpreis
%tbody
- total = 0 #set counter for order-sum
- for category, order_articles in @order.get_articles
%tr{:style => "background-color:#EFEFEF"}
%td{:style => "text-align:left;"}=h category
%td{:colspan => "9"}
- for order_article in order_articles
- article = order_article.article
- # get the order-results for the ordergroup
- group_order_article = GroupOrderArticle.find_by_group_order_id_and_order_article_id @group_order.id, order_article.id
- if group_order_article
- quantity = group_order_article.quantity
- tolerance = group_order_article.tolerance
- result = group_order_article.orderResult[:quantity] + group_order_article.orderResult[:tolerance]
- sub_total = article.gross_price * (quantity + tolerance)
- else
- quantity, tolerance, result, sub_total = 0, 0, 0, 0
- total += sub_total
- # give the article different colors, dependent on order-result
- style = "grey"
- if (quantity > 0)
- style = result > 0 ? 'green' : 'red'
%tr{:class => cycle('even', 'odd', :name => 'articles'), :style => "color:#{style}"}
%td{:style => "width:40%"}
=h order_article.article.name
- unless order_article.article.note.empty?
= image_tag("lamp_grey.png", {:alt => "Notiz anzeigen", :size => "15x16", :border => "0", :onmouseover => "$('note_#{order_article.id}').show();", :onmouseout => "$('note_#{order_article.id}').hide();"})
%td= "#{article.unit_quantity} x #{order_article.article.unit}"
%td= number_to_currency(article.gross_price)
%td
= quantity
= "+ #{tolerance}" if article.unit_quantity > 1
%td= result > 0 ? result : "0"
%td= number_to_currency(sub_total)
- unless order_article.article.note.empty?
%tr{:id => "note_#{order_article.id}", :class => "note even", :style => "display:none"}
%td{:colspan => "6"}=h order_article.article.note
%tr{:class => cycle('even', 'odd', :name => 'articles')}
%th{:colspan => "5"} Summe
%th= number_to_currency(total)

View file

@ -1,45 +1,44 @@
%h1= _('Order Overview')
- title "Bestellüberblick"
// Ordergroups Account Balance
.left_column{:style => "width:26%"}
.box_title
%h2=h @orderGroup.name
%h2=h @ordergroup.name
.column_content
%table
%tr
%td= _('Account balance')
%td{:class => "currency", :style => "width:5em"}= number_to_currency(@orderGroup.account_balance)
%td Kontostand:
%td{:class => "currency", :style => "width:5em"}= number_to_currency(@ordergroup.account_balance)
%tr
%td= "- " + _('Current orders')
%td{:class => "currency"}= number_to_currency(@currentOrdersValue)
%td - laufende Bestellungen:
%td{:class => "currency"}= number_to_currency(@ordergroup.value_of_open_orders)
%tr
%td= "- " +_('Unrecorded orders')
%td{:class => "currency"}= number_to_currency(@nonbookedOrdersValue)
%td - nicht abgerechnete Bestellungen:
%td{:class => "currency"}= number_to_currency(@ordergroup.value_of_finished_orders)
%tr
%th= _('Available')
%th{:class => "currency"}= number_to_currency(@orderGroup.account_balance - @currentOrdersValue - @nonbookedOrdersValue)
%th verfügbares Guthaben:
%th{:class => "currency"}= number_to_currency(@ordergroup.get_available_funds)
.right_column{:style => "width:70%"}
// Current Orders
- if @orderGroup
= render :partial => "currentOrders"
// open orders
= render :partial => "open_orders"
// finished, nonbooked Orders
- unless @finishedOrders.empty?
// finished orders
- unless Order.finished.empty?
.box_title
%h2= _('unrecorded orders')
%h2 Nicht abgerechnete Bestellungen
.column_content
= render :partial => "finishedOrders"
- if @nonbookedOrdersValue > 0
= render :partial => "orders", :locals => {:orders => Order.finished}
- if @ordergroup.value_of_finished_orders > 0
%p
= _('total order value')
%b= number_to_currency(@nonbookedOrdersValue)
Gesamtsumme:
%b= number_to_currency(@ordergroup.value_of_finished_orders)
// bookedOrders
- unless @bookedOrders.empty?
// closed orders
- unless Order.closed.empty?
.box_title
%h2= _('balanced orders')
%h2 Abgerechnete Bestellungen
.column_content
= render :partial => "bookedOrders"
= render :partial => "orders", :locals => {:orders => Order.closed.all(:limit => 5)}
%br/
= link_to _('more...'), :action => "myOrders"
= link_to "mehr...", :action => "myOrders"

View file

@ -1,27 +1,17 @@
%h1
=_ "Orders of"
= @orderGroup.name
- title "Bestellungen der #{@ordergroup.name}"
%p
%i
=_ "See current orders in"
= link_to _("Overview"), :action => "index"
%p
%i{:style => "float:left"}=_ "Also show orders, your ordergroup haven't participated:"
- form_tag({:action => "myOrders"}, :method => "get") do
-unless @show_all
%input{:type => "checkbox", :name => :show_all, :value => "1", :onclick => "submit();"}
-else
%input{:type => "checkbox", :name => :show_all, :value => "0", :checked => "checked", :onclick => "submit();"}
Siehe hier alle
= link_to "laufenden Bestellungen.", :action => "index"
.single_column{:style => "width:50em"}
.box_title
%h2=_ "finished/not balanced"
%h2 beendet/nicht abgerechnet
.column_content
= render :partial => "finishedOrders"
= render :partial => "orders", :locals => {:orders => Order.finished}
.single_column{:style => "width:50em"}
.box_title
%h2=_ "balanced"
%h2 abgerechnet
.column_content
#bookedOrders
= render :partial => "bookedOrders"
#closed_orders
= render :partial => "orders", :locals => {:orders => @closed_orders}

View file

@ -1,86 +1,126 @@
%h1= _("Your result for") + " #{@order.name}"
- title "Dein Bestellergebnis für #{@order.supplier.name}"
#element_navigation
= link_to_unless @order.previous == @order, _("Previous order"), :action => "my_order_result", :id => @order.previous
= link_to_unless @order.previous == @order, "<< #{@order.previous.supplier.name}", :action => "my_order_result", :id => @order.previous
|
= link_to _("Overview"), :controller => 'ordering'
|
= link_to_unless @order.next == @order, _("Next order"), :action => "my_order_result", :id => @order.next
= link_to_unless @order.next == @order, "#{@order.next.supplier.name} >>", :action => "my_order_result", :id => @order.next
// Order summary
.left_column{:style => "width:45em"}
.box_title
%h2=_ "Summary"
%h2 Zusammenfassung
.column_content
%table
%tr{:valign => "top"}
%td{:style => "width:50%"}
%p
= _("Name") + ":"
%b=h @order.name
|
= _("Supplier") + ":"
%b=h @order.supplier ? @order.supplier.name : _("nonexistent")
Lieferant:
%b=h @order.supplier.name
- unless @order.note.empty?
%p
= _("Note") + ":"
Notiz:
=h @order.note
%p
= _("End") + ":"
Ende:
%b=h format_time(@order.ends)
%p
= _("Order value") + ":"
- if @order_value
%b=h number_to_currency(@order_value)
Bestellsumme:
- if @group_order
%b=h number_to_currency(@group_order.price)
- else
%b --
%b Du hast nicht bestellt.
%p
- if @finished
= @order.booked ? _("Cleared by") + " #{@order.updated_by.nick}" : "<b>" + _("Order isn't balanced yet") + "</b>"
= link_to _("read/add comments"), "#comments"
= "Abgerechnet von #{@order.updated_by.nick}" if @order.finished?
= "<b>Bestellung</b>" if @order.closed?
= link_to "Kommentare lesen/schreiben", "#comments"
// directly switch to active orders
.right_column{:style => "width:23em;"}
.box_title
%h2= _("Running orders")
%h2 Laufende Bestellungen
.column_content
%table
- @current_orders.each do |order|
- for order in Order.open
%tr
%td= link_to order.name, :action => 'order', :id => order
%td= "("+ time_ago_in_words(order.ends) + ")" if @order.ends
%td= link_to order.supplier.name, :action => 'order', :id => order
%td= "("+ time_ago_in_words(order.ends) + ")" if order.ends
// Article box
.single_column{:style => "clear:both; width:70em;"}
.box_title
%h2=_ "Overview of articles"
%h2 Artikelübersicht
.column_content#result
- if @finished
// order is finished, show results ...
- unless @groupOrderResult.nil?
= render :partial => "finished_order_result"
- else
=_ "You haven't ordered"
- else
// order isn't finished yet, show ordered articles
- if @group_order
%p= link_to("Bestellung ändern", :action => "order", :id => @order) if @order.current?
= render :partial => 'unfinished_order_result'
%p= link_to("Bestellung ändern", :action => "order", :id => @order) if @order.open?
%table.list
%thead
%tr
%th{:style => "width:40%"} Name
%th Gebinde
%th Einzelpreis
%th
%abbr{:title => "Menge + Toleranz"} Bestellt
%th
%abbr{:title => "Unter Berücksichtigung der anderen Gruppen"} Zugeteilt
%th Gesamtpreis
%tbody
- total = 0 #set counter for order-sum
- for category_name, order_articles in @order.get_articles
%tr{:style => "background-color:#EFEFEF"}
%td{:style => "text-align:left;"}=h category_name
%td{:colspan => "9"}
- for oa in order_articles
- # get the order-results for the ordergroup
- goa = oa.group_order_articles.first :conditions => {:group_order_id => @group_order.id}
- if goa
- quantity = goa.quantity
- tolerance = goa.tolerance
- result = goa.orderResult[:quantity] + goa.orderResult[:tolerance]
- sub_total = oa.price.fc_price * (quantity + tolerance)
- else
- quantity, tolerance, result, sub_total = 0, 0, 0, 0
- total += sub_total
- # give the article different colors, dependent on order-result
- style = "grey"
- if (quantity > 0)
- style = result > 0 ? 'green' : 'red'
%tr{:class => cycle('even', 'odd', :name => 'articles'), :style => "color:#{style}"}
%td{:style => "width:40%"}
=h oa.article.name
- unless oa.article.note.empty?
= 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)
%td
= quantity
= "+ #{tolerance}" if oa.price.unit_quantity > 1
%td= result > 0 ? result : "0"
%td= number_to_currency(sub_total)
- unless oa.article.note.empty?
%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')}
%th{:colspan => "5"} Summe
%th= number_to_currency(total)
%br/
= link_to_top
- else
= _("You haven't ordered yet.")
= link_to _("Order now"), :action => "order", :id => @order
Du hast noch nicht bestellt.
= link_to "Das ist Deine Chance!", :action => "order", :id => @order
// Comments box
- if @finished
.single_column{:style => "width:70em;"}
.box_title
%h2=_ "Comments"
.column_content#comments
= render :partial => 'shared/comments'
= render :partial => 'shared/comments', :locals => { :comments => @order.comments }
%p
= link_to_remote _("New comment"), :url => {:action => 'newComment', :id => @order}, |
:before => "Element.show('loader')", |
:success => "Element.hide('loader')" |
#newComment
- form_for :comment, :url => { :action => :add_comment, :id => @order } do |form|
%p
%b Neuen Kommentar hinzufügen:
%br/
= form.text_area :text, :cols => 50, :rows => 6
%br/
= submit_tag "Kommentar hinzufügen"
= link_to_top

View file

@ -1,7 +1,7 @@
<h1>Bestellen</h1>
<div class="left_column" style="width:49em">
<div class="box_title"><h2><%=h @order.name %></h2></div>
<div class="box_title"><h2><%=h @order.supplier.name %></h2></div>
<div class="column_content">
<table>
<tr valign="top">
@ -28,7 +28,7 @@
<% end %>
<p>
<b><%=_ "Order quanitity so far" %>:</b>
<%= number_to_currency @order.sumPrice %>
<%= number_to_currency @order.sum %>
</p>
</td>
</tr>
@ -46,7 +46,7 @@
<% for order in @other_orders -%>
<tr>
<td>
<%= link_to_function order.name, "if (confirmSwitchOrder()) (window.location = '#{ url_for(:action => 'order', :id => order) }' )" %>
<%= link_to_function order.supplier.name, "if (confirmSwitchOrder()) (window.location = '#{ url_for(:action => 'order', :id => order) }' )" %>
</td>
<td>noch <%= time_ago_in_words(order.ends) if order.ends -%></td>
</tr>
@ -125,7 +125,7 @@
<%= button_to_function('-', "decreaseTolerance(#{i})") %>
<% end -%>
</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> <%= L18n.number.currency.format.unit %></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? -%>
<tr id="note_<%= i %>" class="note" style="display:none">
@ -139,7 +139,7 @@
<tfoot>
<tr>
<td colspan="6"></td>
<td colspan="3" class="currency"><%=_ "Total amount" %>: <span id="total_price"><%= total %></span> <%= L18n.number.currency.format.unit %></td>
<td colspan="3" class="currency"><%=_ "Total amount" %>: <span id="total_price"><%= total %></span> </td>
</tr>
<tr>
<td colspan="6"></td>
@ -147,7 +147,7 @@
</tr>
<tr>
<td colspan="6"></td>
<td colspan="3" class="currency"><%=_ "New account balance"%>: <strong><span id="new_balance"><%= @ordergroup.account_balance - total %></span> <%= L18n.number.currency.format.unit %></strong></td>
<td colspan="3" class="currency"><%=_ "New account balance"%>: <strong><span id="new_balance"><%= @ordergroup.account_balance - total %></span> </strong></td>
</tr>
<tr>
<td style="text-align:left;"><%= link_to_top %></td>
@ -171,7 +171,7 @@
setGroupBalance(<%= @availableFunds %>);
// localization
setDecimalSeparator("<%= L18n.number.currency.format.separator %>");
setDecimalSeparator(",");
// initialize javascript
updateBalance();

View file

@ -0,0 +1,31 @@
%table
%tr
%th Name
%th Gebinde
%th Netto/FC-Preis
%th Bestellte Einheiten
%th Volle Gebinde
- total_net, total_gross, counter = 0, 0, 0
- order.get_articles.each do |category_name, order_articles|
%tr{:style => "background-color:#EFEFEF"}
%td{:style => "text-align:left; color: grey;"}=h category_name
%td{:colspan => "9"}
- order_articles.each do |order_article|
- net_price = order_article.price.price
- fc_price = order_article.price.fc_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
%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= "#{order_article.quantity} + #{order_article.tolerance}" if unit_quantity > 1
%td= units
%p
Summe (Netto/FC-Preise):
= "#{number_to_currency(total_net)} / #{number_to_currency(total_gross)}"
%p
Bestellte Artikel.
= order.order_articles.ordered.count

View file

@ -0,0 +1,23 @@
.legend
%table.legend{:style => "margin-bottom:1em"}
%tr
%th{:colspan => '3'} Legende
%tr
%th{:style => 'width:70%'} Bestellgruppe
%th Menge
%th Gesamtpreis
- for order_article in order.order_articles.all(:include => [:article, :article_price])
%table{:style => "margin-bottom:1em"}
%thead
%tr
%th{:colspan => "3"}
= order_article.article.name
= "(#{order_article.article.unit} | #{order_article.price.unit_quantity} | #{number_to_currency(order_article.price.fc_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= number_to_currency(order_article.price.fc_price * goa.quantity)
- reset_cycle('groups')

View file

@ -0,0 +1,36 @@
.legend
%table.legend{:style => "margin-bottom:1em"}
%tr
%th{:style => "width:40%"} Name
%th
%acronym{:title => "zugeteilte Einheiten (davon aus Toleranzmenge)"} Menge
%th
%acronym{:title => "Preis incl. MwSt, Pfand und Foodcoop-Aufschlag"} FC-Preis
%th
%acronym{:title => "Gebindegröße"} GebGr
%th Einheit
%th Gesamtpreis
- for group_order in order.group_orders.all
%table{:style => "margin-bottom:1em"}
%thead
%tr
%th{:colspan => "6"}=h group_order.ordergroup.name
%tbody
- total = 0
- for goa in group_order.group_order_articles.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= number_to_currency(fc_price)
%td= goa.order_article.price.unit_quantity
%td= goa.order_article.article.unit
%td= number_to_currency(subTotal)
%tr{:class => cycle('even', 'odd', :name => 'articles')}
%th{:colspan => "5"} Summe
%th= number_to_currency(total)
- reset_cycle("articles")

View file

@ -1,31 +1,28 @@
= error_messages_for 'order'
= form.error_messages
.single_column
.box_title
%h2=_ "Order"
%h2 Bestellung
.column_content
= hidden_field 'order', 'supplier_id'
= form.hidden_field :supplier_id
%p
=h _("Supplier") + ": #{@order.supplier.name}"
Lieferant:
= @order.supplier.name
%p
%label{:for => 'order_name'}=_ "Name"
Notiz
%br/
= text_field 'order', 'name'
= form.text_area :note, :cols => 50, :rows => 5
%p
%label{:for => 'order_note'}=_ "Note"
Start
%br/
= text_area 'order', 'note', :cols => 50, :rows => 5
= form.datetime_select :starts, :start_year => Time.now.year - 1
%p
%label{:for => 'order_starts'}=_ "Start"
Ende
%br/
= datetime_select 'order', 'starts', :start_year => Time.now.year - 1
%p
%label{:for => 'order_ends'}=_ "End"
%br/
= datetime_select 'order', 'ends', :start_year => Time.now.year - 1, :include_blank => true
= form.datetime_select :ends, :start_year => Time.now.year - 1, :include_blank => true
.box_title
%h2=_ "Articles"
%h2 Artikel
.column_content
- if (@template_orders && !@template_orders.empty?)
%p
@ -34,7 +31,7 @@
%option{:value => "-1", :selected => "selected"}=_ "Choose an order..."
- i = -1
- for order in @template_orders
%option{:value => (i += 1)}=h order.name
%option{:value => (i += 1)}=h order.supplier.name
%table.list
%tr
%th= check_box_tag 'checkall', "1", false, { :onclick => "checkUncheckAll(this)" }
@ -52,14 +49,15 @@
- for article in articles
/ check if the article is selected
- included = @order.order_articles.detect { |order_article| order_article.article_id == article.id }
%tr{:class => cycle('even', 'odd') + (included ? ' selected' : ''), :id => article.id.to_s, :onclick => "checkRow('#{article.id}')"}
%td= check_box_tag "order[article_ids][]", article.id.to_s, included, { :id => "checkbox_#{article.id}", :onclick => "checkRow('#{article.id}')" }
- included_class = included ? ' selected' : ''
%tr{:class => cycle('even', 'odd') + ' click-me' + included_class, :id => article.id.to_s, :onclick => "checkRow('#{article.id}')"}
%td= check_box_tag "order[article_ids][]", article.id, included, { :id => "checkbox_#{article.id}", :onclick => "checkRow('#{article.id}')" }
%td=h article.name
%td=h truncate article.note, 25
%td=h truncate article.origin, 15
%td=h truncate article.manufacturer, 15
%td=h truncate article.note, :length => 25
%td=h truncate article.origin, :length => 15
%td=h truncate article.manufacturer, :length => 15
%td= "#{article.unit_quantity} x #{article.unit}"
%td= "#{number_to_currency(article.net_price)} / #{number_to_currency(article.gross_price)}"
%td= "#{number_to_currency(article.price)} / #{number_to_currency(article.fc_price)}"
%tr
%td{:colspan => "6"}
= check_box_tag 'checkall', "1", false, { :onclick => "checkUncheckAll(this)" }

View file

@ -1,22 +0,0 @@
= pagination_links_remote @orders, :params => {:sort => params[:sort]}
%table.list{:style => "width: 100%"}
%thead
%tr
%th=_ "Name"
%th[sort_td_class_helper "supplier"]
= sort_link_helper _("Supplier"), "supplier"
%th=_ "Start"
%th[sort_td_class_helper "ends"]
= sort_link_helper _("End"), "ends"
%th=_ "Status"
%th{:colspan => "2"}
%tbody
- @orders.each do |order|
%tr{:class => cycle('even', 'odd', :name => 'orders') + ((!order.finished? and order.ends < Time.now) ? " active" : "")}
%td= link_to order.name, :action => "show", :id => order
%td=h order.supplier ? order.supplier.name : _("nonexistent")
%td=h format_time(order.starts)
%td=h format_time(order.ends)
%td= order.status == _("expired") ? link_to( _("finish now") + (" !!"), {:action => 'finish', :id => order}, :confirm => _("Are you really sure to finish the order?"), :method => "post") : order.status
%td= link_to(image_tag('b_edit.png', :size => "16x16", :border => "0", :alt => _('Edit')), :action => 'edit', :id => order) unless order.finished?
%td= link_to image_tag('b_drop.png', :size => "16x16", :border => "0", :alt => _("Destroy")), { :action => 'destroy', :id => order }, :confirm => _("Are you really sure you want to destroy the order?"), :method => "post"

View file

@ -0,0 +1,19 @@
= pagination_links_remote @orders, :params => {:sort => params[:sort]}
%table.list{:style => "width: 100%"}
%thead
%tr
%th[sort_td_class_helper "supplier"]
= sort_link_helper "Lieferant", "supplier"
%th Start
%th[sort_td_class_helper "ends"]
= sort_link_helper "Ende", "ends"
%th Status
%th{:colspan => "2"}
%tbody
- @orders.each do |order|
%tr{:class => cycle('even', 'odd', :name => 'orders')}
%td=h order.supplier.name
%td=h format_time(order.starts)
%td=h format_time(order.ends)
%td= order.state
%td= link_to "Anzeigen", order

View file

@ -1,30 +0,0 @@
<table class="list">
<thead>
<tr>
<th><acronym title="Bestellnummer">Nr.</acronym></th>
<th><acronym title="Gebinde insgesamt">Menge</acronym></th>
<th>Artikel</th>
<th><acronym title="Gebindegröße">GebGr</acronym></th>
<th>Einheit</th>
<th>Notiz</th>
<th><acronym title="Bruttopreis inkl. MwSt, Aufschlag, Pfand">Preis</acronym></th>
<th>MwSt</th>
<th>Pfand</th>
</tr>
</thead>
<tbody>
<% for article in @order_articles %>
<tr class="<%= cycle('even', 'odd', :name => 'articles') %>">
<td><%=h article.order_number %></td>
<td><%=h article.units_to_order %></td>
<td><%=h article.name %></td>
<td><%=h article.unit_quantity %></td>
<td><%=h article.unit %></td>
<td><%=h article.note %></td>
<td><%= number_to_currency(article.gross_price) %></td>
<td><%=h article.tax %></td>
<td><%=h article.deposit %></td>
</tr>
<% end %>
</tbody>
</table>

View file

@ -1,31 +0,0 @@
<div class="legend">
<table style="margin-bottom:1em" class="legend">
<tr>
<th colspan="3">Legende</th>
</tr>
<tr>
<td style="width:70%">Bestellgruppe</td>
<td>Menge</td>
<td>Gesamtpreis</td>
</tr>
</table>
</div>
<% for article in @order_articles %>
<table style="margin-bottom:1em">
<thead>
<tr>
<th colspan="3"><%= article.name %> (<%= article.unit %> | <%= article.unit_quantity %> | <%= number_to_currency(article.gross_price) %>)</th>
</tr>
</thead>
<tbody>
<% for result in article.group_order_article_results %>
<tr class="<%= cycle('even', 'odd', :name => 'groups') %>">
<td style="width:70%"><%=h result.group_order_result.group_name %></td>
<td><%=h result.quantity %> (<%=h result.tolerance %>)</td>
<td><%= number_to_currency(article.gross_price * result.quantity) %></td>
</tr>
<% end %>
</tbody>
</table>
<%- reset_cycle("groups") -%>
<% end %>

View file

@ -1,45 +0,0 @@
<div class="legend">
<table style="margin-bottom:1em" class="legend">
<tr>
<th style="width:40%">Name</th>
<th><acronym title="zugeteilte Einheiten (davon aus Toleranzmenge)">Menge</acronym></th>
<th><acronym title="Bruttopreis incl. MwSt, Aufschlag, Pfand">Preis</acronym></th>
<th><acronym title="Gebindegröße">GebGr</acronym></th>
<th>Einheit</th>
<th>Gesamtpreis</th>
</tr>
</table>
</div>
<% for groupOrderResult in @order.group_order_results %>
<table style="margin-bottom:1em">
<thead>
<tr>
<th colspan="6"><%=h groupOrderResult.group_name %></th>
</tr>
</thead>
<tbody>
<%
total = 0
for result in groupOrderResult.group_order_article_results
price = result.order_article_result.gross_price
quantity = result.quantity
subTotal = price * quantity
total += subTotal
%>
<tr class="<%= cycle('even', 'odd', :name => 'articles') %>">
<td style="width:40%"><%=h result.order_article_result.name %></td>
<td><%=h quantity %> (<%=h result.tolerance %>)</td>
<td><%= number_to_currency(price) %></td>
<td><%=h result.order_article_result.unit_quantity %></td>
<td><%=h result.order_article_result.unit %></td>
<td><%= number_to_currency(subTotal) %></td>
</tr>
<% end %>
<tr class="<%= cycle('even', 'odd', :name => 'articles') %>">
<th colspan="5">Summe</th>
<th><%= number_to_currency(total) %></th>
</tr>
</tbody>
</table>
<%- reset_cycle("articles") -%>
<% end %>

View file

@ -1,33 +0,0 @@
%table
%tr
%th=_ "Name"
%th=_ "Unit quantity"
%th=_ "Price"
%th=_ "Units ordered"
%th=_ "Result/Unit quantity"
- totalNetto, totalBrutto, counter = 0, 0, 0
- @order_articles.each do |category, order_articles|
%tr{:style => "background-color:#EFEFEF"}
%td{:style => "text-align:left; color: grey;"}=h category
%td{:colspan => "9"}
- order_articles.each do |order_article|
- nettoPrice = order_article.article.net_price
- bruttoPrice = order_article.article.gross_price
- units = order_article.units_to_order
- unitQuantity = order_article.article.unit_quantity
- totalNetto += units * unitQuantity * nettoPrice
- totalBrutto += units * unitQuantity * bruttoPrice
- counter += 1 if units > 0
%tr{:class => cycle('even', 'odd', :name => 'articles'), :style => "color: #{units > 0 ? 'green' : 'red'}"}
%td=h order_article.article.name
%td= "#{unitQuantity} x #{order_article.article.unit}"
%td= "#{number_to_currency(nettoPrice)} / #{number_to_currency(bruttoPrice)}"
%td= "#{order_article.quantity} + #{order_article.tolerance}" if unitQuantity > 1
%td= units
%p
=_ "Total value"
=_ "(net/gross)"
= "#{number_to_currency(totalNetto)} / #{number_to_currency(totalBrutto)}"
%p
=_ "Ordered articles:"
= counter

View file

@ -1,7 +1,5 @@
# Get ActiveRecord objects
order_articles = @order.order_article_results
end_date = @order.ends.strftime('%d.%m.%Y')
title = "#{@order.name} | beendet am #{end_date}"
title = "#{@order.supplier.name} | beendet am #{end_date}"
# Define header and footer
pdf.header [pdf.margin_box.left,pdf.margin_box.top+30] do
@ -14,15 +12,16 @@ end
# Start rendering
for article in order_articles
pdf.text "#{article.name} (#{article.unit} | #{article.unit_quantity.to_s} | #{number_to_currency(article.gross_price)})",
for order_article in @order.order_articles.ordered
pdf.text "#{order_article.article.name} (#{order_article.article.unit} |\
#{order_article.price.unit_quantity.to_s} | #{number_to_currency(order_article.price.fc_price)})",
:style => :bold, :size => 10
pdf.move_down 5
data = []
for result in article.group_order_article_results
data << [result.group_order_result.group_name,
result.quantity,
article.gross_price * result.quantity]
for goa in order_article.group_order_articles
data << [goa.group_order.ordergroup.name,
goa.quantity,
number_with_precision(order_article.price.fc_price * goa.quantity)]
end
pdf.table data,
@ -31,6 +30,7 @@ for article in order_articles
:widths => { 0 => 200, 1 => 40, 2 => 40 },
:border_style => :grid,
:row_colors => ['ffffff','ececec'],
:vertical_padding => 3
:vertical_padding => 3,
:align => { 2 => :right }
pdf.move_down 10
end

View file

@ -1,7 +1,7 @@
- title _("Edit order")
- form_tag :action => 'update', :id => @order do
= render :partial => 'form'
- form_for @order do |form|
= render :partial => 'form', :locals => { :form => form }
= submit_tag _("Save")
|
= link_to _("Cancel"), :action => 'show', :id => @order

View file

@ -41,12 +41,13 @@ pdf.text "Ansprechpartner: " + @order.supplier.contact_person
pdf.move_down 10
# Articles
data = @order.order_article_results.collect do |a|
[a.order_number, a.units_to_order, a.name,
a.unit_quantity, a.unit, a.net_price]
data = @order.order_articles.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
pdf.table data,
:font_size => 8,
:vertical_padding => 3,
:border_style => :grid,
:headers => ["BestellNr.", "Menge","Name", "Gebinde", "Einheit","Preis/Einheit"]
:headers => ["BestellNr.", "Menge","Name", "Gebinde", "Einheit","Preis/Einheit"],
:align => {0 => :left}

View file

@ -1,5 +1,5 @@
end_date = @order.ends.strftime('%d.%m.%Y')
title = "Gruppensortierung für #{@order.name}, beendet am #{end_date}"
title = "Gruppensortierung für #{@order.supplier.name}, beendet am #{end_date}"
# Define header and footer
pdf.header [pdf.margin_box.left,pdf.margin_box.top+20] do
@ -12,28 +12,28 @@ end
# Start rendering
groups = @order.group_order_results.size
groups = @order.group_orders.size
counter = 1
for group_result in @order.group_order_results
pdf.text group_result.group_name, :style => :bold
for group_order in @order.group_orders
pdf.text group_order.ordergroup.name, :style => :bold
pdf.move_down 5
pdf.text "Gruppe #{counter.to_s}/#{groups.to_s}", :size => 8
pdf.move_down 5
total = 0
data = []
group_result.group_order_article_results.each do |result|
price = result.order_article_result.gross_price
quantity = result.quantity
group_order.group_order_articles.each do |goa|
price = goa.order_article.price.fc_price
quantity = goa.quantity
sub_total = price * quantity
total += sub_total
data << [result.order_article_result.name,
quantity, price,
result.order_article_result.unit_quantity,
result.order_article_result.unit,
sub_total]
data << [goa.order_article.article.name,
quantity, number_with_precision(price),
goa.order_article.price.unit_quantity,
goa.order_article.article.unit,
number_with_precision(sub_total)]
end
data << [ {:text => "Summe", :colspan => 5}, total]
data << [ {:text => "Summe", :colspan => 5}, number_with_precision(total)]
pdf.table data,
:font_size => 8,
@ -41,7 +41,8 @@ for group_result in @order.group_order_results
:vertical_padding => 3,
:headers => ["Artikel", "Menge", "Preis", "GebGr", "Einheit", "Summe"],
:widths => { 0 => 250 },
:row_colors => ['ffffff','ececec']
:row_colors => ['ffffff','ececec'],
:align => { 0 => :right, 5 => :right }
counter += 1
pdf.move_down 10

View file

@ -3,39 +3,40 @@
- if @current_user.role_orders?
%p
- form_tag do
=_ "New Order"
=_ "for"
Neue Bestellung anlegen für
%select{:onchange => "redirectTo(this)", :style => "font-size: 0.9em;margin-left:1em;"}
%option{:selected => 'selected'}=_ "Choose a supplier..."
= options_for_select(Supplier.find(:all).collect {|s| [ s.name, url_for(:action => "new", :id => s)] })
= options_for_select(Supplier.find(:all).collect {|s| [ s.name, url_for(:action => "new", :supplier_id => s)] })
%br/
.left_column{:style => "width:55em"}
.box_title
%h2=_ "Running orders"
%h2 Laufende Bestellungen
.column_content
- if (@current_orders.length > 0)
- unless @open_orders.empty?
%table.list
%thead
%tr
%th=_ "Name"
%th=_ "Supplier"
%th=_ "End"
%th Lieferant
%th Ende
%th Notiz
%th{:colspan => "2"}
%tbody
- for order in @current_orders
%tr{:class => cycle('even', 'odd', :name => 'current_orders')}
%td= link_to order.name, :controller => 'orders', :action => 'show', :id => order
- for order in @open_orders
- active = (order.open? and order.ends < Time.now) ? " active" : ""
%tr{:class => cycle('even', 'odd', :name => 'open_orders') + active}
%td=h order.supplier.name
%td=h format_time(order.ends) unless order.ends.nil?
%td= link_to _("finish"), {:action => 'finish', :id => order}, :confirm => _("Are you really sure to finish the order?"), :method => "post"
%td=h truncate(order.note)
%td= link_to "Beenden", finish_order_path(order), :confirm => _("Are you really sure to finish the order?"), :method => :post
%td
= link_to image_tag('b_edit.png', :size => "16x16", :border => 0, :alt => _("Edit")), :action => 'edit', :id => order
= link_to image_tag('b_drop.png', :size => "16x16", :border => 0, :alt => _("Destroy")), { :action => 'destroy', :id => order }, :confirm => _("Are you really sure you want to destroy the order?"), :method => "post"
= link_to "Anzeigen", order
= link_to icon(:edit), edit_order_path(order)
= link_to icon(:delete), order, :confirm => _("Are you really sure you want to destroy the order?"), :method => :delete
- else
=_ "There aren't current orders at the moment."
=_ "There aren't open orders at the moment."
.left_column{:style => "width:75em"}
.box_title
%h2=_ "Expired/finished orders"
%h2 Beendete Bestellungen
.column_content#orders_table
= render :partial => 'list'
= render :partial => 'orders'

View file

@ -1,4 +1,4 @@
title = "#{@order.name}, beendet am #{@order.ends.strftime('%d.%m.%Y')}"
title = "#{@order.supplier.name}, beendet am #{@order.ends.strftime('%d.%m.%Y')}"
# Define header and footer
pdf.header [pdf.margin_box.left,pdf.margin_box.top+20] do
@ -9,64 +9,64 @@ pdf.footer [pdf.margin_box.left, pdf.margin_box.bottom-5] do
pdf.text "Seite #{pdf.page_count}", :size => 8
end
max_articles_per_page = 17 # How many articles shoud written on a page
articles = @order.order_article_results
max_order_articles_per_page = 17 # How many order_articles shoud written on a page
order_articles = @order.order_articles
pdf.text "Artikelübersicht", :style => :bold
pdf.move_down 5
pdf.text "Insgesamt #{articles.size} Artikel", :size => 8
pdf.text "Insgesamt #{order_articles.size} Artikel", :size => 8
pdf.move_down 10
articles_data = articles.collect do |a|
[a.name, a.unit, a.unit_quantity, a.gross_price, a.units_to_order]
order_articles_data = order_articles.collect do |a|
[a.article.name, a.article.unit, a.price.unit_quantity, a.price.fc_price, a.units_to_order]
end
pdf.table articles_data,
pdf.table order_articles_data,
:font_size => 8,
:border_style => :grid,
:vertical_padding => 3,
:headers => ["Artikel", "Einheit", "Gebinde", "Preis", "Menge"]
:headers => ["Artikel", "Einheit", "Gebinde", "Preis", "Menge"],
:align => { 3 => :right }
page_number = 0
total_num_articles = articles.size
total_num_order_articles = order_articles.size
while (page_number * max_articles_per_page < total_num_articles) do # Start page generating
while (page_number * max_order_articles_per_page < total_num_order_articles) do # Start page generating
page_number += 1
pdf.start_new_page(:layout => :landscape)
# Collect articles for this page
current_articles = articles.select do |a|
articles.index(a) >= (page_number-1) * max_articles_per_page and
articles.index(a) < page_number * max_articles_per_page
# Collect order_articles for this page
current_order_articles = order_articles.select do |a|
order_articles.index(a) >= (page_number-1) * max_order_articles_per_page and
order_articles.index(a) < page_number * max_order_articles_per_page
end
# Make articles header
# Make order_articles header
header = [""]
for header_article in current_articles
name = header_article.name.split("-").join(" ").split(".").join(". ").split("/").join(" ")
for header_article in current_order_articles
name = header_article.article.name.split("-").join(" ").split(".").join(". ").split("/").join(" ")
name = name.split.collect { |w| truncate(w, 8, "..") }.join(" ")
header << truncate(name, 30, " ..")
end
# Collect group results
groups_data = []
for group_order_result in @order.group_order_results
for group_order in @order.group_orders.all(:include => :ordergroup)
group_result = [truncate(group_order_result.group_name, 20)]
group_result = [truncate(group_order.ordergroup.name, 20)]
for article in current_articles
# get the OrdergroupResult for this article
result = GroupOrderArticleResult.find(:first,
:conditions => ['order_article_result_id = ? AND group_order_result_id = ?', article.id, group_order_result.id])
group_result << ((result.nil? || result == 0) ? "" : result.quantity.to_i)
for order_article in current_order_articles
# get the Ordergroup result for this order_article
goa = order_article.group_order_articles.first :conditions => { :group_order_id => group_order.id }
group_result << ((goa.nil? || goa == 0) ? "" : goa.quantity.to_i)
end
groups_data << group_result
end
# Make table
widths = { }
(max_articles_per_page + 1).times { |i| widths.merge!({ i => 40 }) unless i == 0 }
widths = { } # Generate widths-hash for table layout
(max_order_articles_per_page + 1).times { |i| widths.merge!({ i => 40 }) unless i == 0 }
pdf.table groups_data,
:font_size => 8,
:border_style => :grid,

View file

@ -1,7 +1,7 @@
- title _("New order")
- form_tag :action => 'create' do
= render :partial => 'form'
- form_for @order do |form|
= render :partial => 'form', :locals => { :form => form }
= submit_tag _("Put the order online")
|
= link_to _("Cancel"), :action => 'index'
= link_to "Abbrechen", orders_path

View file

@ -1,90 +1,88 @@
- title _("Show order")
#element_navigation
= link_to_unless @order.previous == @order, _("Previous order"), :action => "show", :id => @order.previous
= link_to_unless @order.previous == @order, _("Previous order"), @order.previous
|
= link_to _("Overview"), :controller => 'orders'
= link_to _("Overview"), orders_path
|
= link_to_unless @order.next == @order, _("Next order"), :action => "show", :id => @order.next
= link_to_unless @order.next == @order, _("Next order"), @order.next
// Order summary
.left_column{:style => "width:55em"}
.left_column{:style => "width:65em"}
.box_title
%h2=_ "Summary"
%h2 Zusammenfassung
.column_content
- if !@order.booked? and @finished
- if @order.finished? and !@order.closed?
%p
%b{:style => "color:red"}=_ "Order isn't balanced yet"
%b{:style => "color:red"}=_ "Order isn't closed yet"
%p
= _("Name") + ":"
%b=h @order.name
|
= _("Supplier") + ":"
%b=h @order.supplier ? @order.supplier.name : _('nonexistent')
Lieferant:
%b=h @order.supplier.name
- unless @order.note.empty?
%p
= _("Note") + ":"
Notiz:
=h @order.note
%p
= _("Begin") + ":"
Beginn:
%b=h format_time(@order.starts)
|
= _("End") + ":"
Ende:
%b=h format_time(@order.ends)
%p
= _("Groups ordered") + ":"
%b= @group_orders.size
- unless @finished
= "[#{@group_orders.collect{|g| g.ordergroup.name}.join(', ')}]" unless @group_orders.empty?
- else
= "[#{@group_orders.collect{|g| g.group_name}.join(', ')}]" unless @group_orders.empty?
Gruppenbestellungen:
%b= @order.group_orders.count
= "[#{@order.group_orders.find(:all, :include => :ordergroup).collect{|g| g.ordergroup.name}.join(', ')}]"
%p
=_ "Total price"
%b= number_to_currency(@order.sumPrice('gross'))
- if @order.finished
Bruttosummer aller Artikel
%b= number_to_currency(@order.sum(:gross))
- if @order.finished?
|
=_ "Ordered articles:"
%b= @order_articles.size
- unless @finished
= link_to(image_tag('b_edit.png', :size => "16x16", :border => "0", :alt => 'Edit'), :action => 'edit', :id => @order)
= link_to(image_tag('b_drop.png', :size => "16x16", :border => "0", :alt => 'Delete'), { :action => 'destroy', :id => @order }, :confirm => "Willst du wirklich die Bestellung '#{@order.name}' löschen?", :method => "post")
= link_to('[beenden]', {:action => 'finish', :id => @order}, :confirm => "Willst du wirklich die Bestellung '#{@order.name}' beenden?", :method => "post")
- else
Bestellte Artikel:
%b= @order.order_articles.ordered.count
- if @order.open?
%p
= link_to_remote _("All articles"), :update => 'result', :url => {:action => 'show', :id => @order, :view => 'normal'}, :before => "Element.show('loader')", :success => "Element.hide('loader')"
= 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
= update_articles_link(@order, "Artikelübersicht", :normal)
|
= link_to_remote _("Sort by groups"), :update => 'result', :url => {:action => 'show', :id => @order, :view => 'groups'}, :before => "Element.show('loader')", :success => "Element.hide('loader')"
= link_to image_tag("save_pdf.png", :size => "16x16", :border => "0", :alt => "PDF erstellen"), { :action => 'groupsPdf', :id => @order, :format => :pdf }, { :title => _("Download file") }
= update_articles_link(@order, "Sortiert nach Gruppen", :groups)
= link_to_pdf(@order, 'groupsPdf')
|
= link_to_remote _("Sort by articles"), :update => 'result', :url => {:action => 'show', :id => @order, :view => 'articles'}, :before => "Element.show('loader')", :success => "Element.hide('loader')"
= link_to image_tag("save_pdf.png", :size => "16x16", :border => "0", :alt => "PDF erstellen"), { :action => 'articlesPdf', :id => @order, :format => :pdf}, { :title => _("Download file") }
= update_articles_link(@order, "Sortiert nach Artikeln", :articles)
= link_to_pdf(@order, 'articlesPdf')
|
=_ "Matrix" + ":"
= link_to image_tag("save_pdf.png", :size => "16x16", :border => "0", :alt => "PDF erstellen"), { :action => 'matrixPdf', :id => @order, :format => :pdf }, { :title => _("Download file") }
Matrix:
= link_to_pdf(@order, 'matrixPdf')
|
=_ "FAX-template" + ":"
= link_to image_tag("save_pdf.png", :size => "16x16", :border => "0", :alt => "PDF erstellen"), { :action => 'faxPdf', :id => @order, :format => :pdf }, { :title => _("Download file") }
Faxvorlage:
= link_to_pdf(@order, 'faxPdf')
= link_to image_tag("text_file.png", :size => "16x16", :border => "0", :alt => "Textdatei erstellen"), { :action => 'text_fax_template', :id => @order }, { :title => _("Download file") }
|
= link_to 'Kommentare', '#comments'
// Ordered articles
.single_column{:style => "clear:both; width:70em;"}
.box_title
%h2=_ "Articles"
.column_content#result
- unless @finished
= render :partial => "show_unfinished"
- else
= render :partial => "showResult"
%h2 Artikel
.column_content#articles
= render :partial => 'articles', :locals => { :order => @order }
// comments
- if @finished
.single_column{:style => "width:70em;"}
.box_title
%h2=_ "Comments"
%h2 Kommentare
.column_content#comments
= render :partial => "/shared/comments"
= render :partial => "/shared/comments", :locals => { :comments => @order.comments }
%p
= link_to_remote "neuer Kommentar", :url => {:action => 'newComment', :id => @order}
#newComment
- form_for :comment, :url => add_comment_order_path(@order) do |form|
%p
%b Neuen Kommentar hinzufügen:
%br/
= form.text_area :comment, :cols => 50, :rows => 6
%br/
= submit_tag "Kommentar hinzufügen"
= link_to_top

View file

@ -1,10 +1,9 @@
- unless @comments.empty?
- @comments.each do |comment|
- unless comments.empty?
- comments.each do |comment|
.comment[comment]
%h3
= "#{comment.user.find_ordergroup.name} :" if comment.user.find_ordergroup
=h comment.title
= simple_format(comment.comment)
= simple_format(comment.text)
.timestamp
Erstellt am
= format_time(comment.created_at)

View file

@ -1,12 +0,0 @@
- form_for :comment, :url => {:action => 'addComment', :id => @order } do |form|
%p
Titel:
%br/
= form.text_field :title, :cols => 40
%p
Kommentar:
%br/
= form.text_area :comment, :cols => 60, :rows => 8
= submit_tag "Speichern"
|
= link_to_function "Abbrechen", "Element.hide('newComment')"

View file

@ -23,5 +23,5 @@
%td=h article.name
%td= article.quantity
%td= article.unit
%td= article.net_price
%td= article.price
%td= link_to article.supplier.name, article.supplier

View file

@ -121,5 +121,5 @@ de:
article: Artikel
attributes:
article:
net_price: Nettopreis
price: Nettopreis
gross_price: Bruttopreis

View file

@ -3,6 +3,8 @@ ActionController::Routing::Routes.draw do |map|
map.my_profile '/home/profile', :controller => 'home', :action => 'profile'
map.my_tasks '/home/tasks', :controller => 'tasks', :action => 'myTasks'
map.resources :orders, :member => { :finish => :post, :add_comment => :post }
map.resources :messages, :only => [:index, :show, :new, :create],
:member => { :reply => :get, :user => :get, :group => :get }

View file

@ -0,0 +1,68 @@
class RefactorOrderLogic < ActiveRecord::Migration
def self.up
# TODO: Combine migrations since foodsoft3-development into one file
# and try to build a migration path from old data.
# articles
rename_column :articles, :net_price, :price
remove_column :articles, :gross_price
# orders
drop_table :orders
drop_table :group_order_results
drop_table :order_article_results
drop_table :group_order_article_results
GroupOrder.delete_all; OrderArticle.delete_all; GroupOrderArticle.delete_all; GroupOrderArticleQuantity.delete_all
create_table :orders do |t|
t.references :supplier
t.text :note
t.datetime :starts
t.datetime :ends
t.string :state, :default => "open" # Statemachine ... open -> finished -> closed
t.integer :lock_version, :default => 0, :null => false
t.integer :updated_by_user_id
end
# invoices
add_column :invoices, :order_id, :integer
add_column :invoices, :deposit, :decimal, :precision => 8, :scale => 2, :default => 0.0, :null => false
add_column :invoices, :deposit_credit, :decimal, :precision => 8, :scale => 2, :default => 0.0, :null => false
# comments
drop_table :comments
create_table :order_comments do |t|
t.references :order
t.references :user
t.text :text
t.datetime :created_at
end
# article_prices
create_table :article_prices do |t|
t.references :article
t.decimal :price, :precision => 8, :scale => 2, :default => 0.0, :null => false
t.decimal :tax, :precision => 8, :scale => 2, :default => 0.0, :null => false
t.decimal :deposit, :precision => 8, :scale => 2, :default => 0.0, :null => false
t.integer :unit_quantity
t.datetime :created_at
end
# Create price history for every Article
Article.all.each do |a|
a.article_prices.create :price => a.price, :tax => a.tax,
:deposit => a.deposit, :unit_quantity => a.unit_quantity
end
# Every Article has now a Category. Fix it if neccessary.
Article.all(:conditions => { :article_category_id => nil }).each do |article|
article.update_attribute(:article_category, ArticleCategory.first)
end
# order-articles
add_column :order_articles, :article_price_id, :integer
# ordergroups
add_column :groups, :deleted_at, :datetime
end
def self.down
end
end

View file

@ -9,7 +9,7 @@
#
# It's strongly recommended to check this file into your version control system.
ActiveRecord::Schema.define(:version => 20090119155930) do
ActiveRecord::Schema.define(:version => 20090120184410) do
create_table "article_categories", :force => true do |t|
t.string "name", :default => "", :null => false
@ -18,6 +18,15 @@ ActiveRecord::Schema.define(:version => 20090119155930) do
add_index "article_categories", ["name"], :name => "index_article_categories_on_name", :unique => true
create_table "article_prices", :force => true do |t|
t.integer "article_id"
t.decimal "price", :precision => 8, :scale => 2, :default => 0.0, :null => false
t.decimal "tax", :precision => 8, :scale => 2, :default => 0.0, :null => false
t.decimal "deposit", :precision => 8, :scale => 2, :default => 0.0, :null => false
t.integer "unit_quantity"
t.datetime "created_at"
end
create_table "articles", :force => true do |t|
t.string "name", :default => "", :null => false
t.integer "supplier_id", :default => 0, :null => false
@ -28,8 +37,7 @@ ActiveRecord::Schema.define(:version => 20090119155930) do
t.string "manufacturer"
t.string "origin"
t.datetime "shared_updated_on"
t.decimal "net_price", :precision => 8, :scale => 2
t.decimal "gross_price", :precision => 8, :scale => 2, :default => 0.0, :null => false
t.decimal "price", :precision => 8, :scale => 2
t.float "tax"
t.decimal "deposit", :precision => 8, :scale => 2, :default => 0.0
t.integer "unit_quantity", :default => 1, :null => false
@ -50,17 +58,6 @@ ActiveRecord::Schema.define(:version => 20090119155930) do
add_index "assignments", ["user_id", "task_id"], :name => "index_assignments_on_user_id_and_task_id", :unique => true
create_table "comments", :force => true do |t|
t.string "title", :limit => 50, :default => ""
t.text "comment"
t.datetime "created_at", :null => false
t.integer "commentable_id", :default => 0, :null => false
t.string "commentable_type", :limit => 15, :default => "", :null => false
t.integer "user_id", :default => 0, :null => false
end
add_index "comments", ["user_id"], :name => "fk_comments_user"
create_table "configurable_settings", :force => true do |t|
t.integer "configurable_id"
t.string "configurable_type"
@ -94,16 +91,6 @@ ActiveRecord::Schema.define(:version => 20090119155930) do
t.datetime "created_on", :null => false
end
create_table "group_order_article_results", :force => true do |t|
t.integer "order_article_result_id", :default => 0, :null => false
t.integer "group_order_result_id", :default => 0, :null => false
t.decimal "quantity", :precision => 6, :scale => 3, :default => 0.0
t.integer "tolerance"
end
add_index "group_order_article_results", ["group_order_result_id"], :name => "index_group_order_article_results_on_group_order_result_id"
add_index "group_order_article_results", ["order_article_result_id"], :name => "index_group_order_article_results_on_order_article_result_id"
create_table "group_order_articles", :force => true do |t|
t.integer "group_order_id", :default => 0, :null => false
t.integer "order_article_id", :default => 0, :null => false
@ -114,14 +101,6 @@ ActiveRecord::Schema.define(:version => 20090119155930) do
add_index "group_order_articles", ["group_order_id", "order_article_id"], :name => "goa_index", :unique => true
create_table "group_order_results", :force => true do |t|
t.integer "order_id", :default => 0, :null => false
t.string "group_name", :default => "", :null => false
t.decimal "price", :precision => 8, :scale => 2, :default => 0.0, :null => false
end
add_index "group_order_results", ["group_name", "order_id"], :name => "index_group_order_results_on_group_name_and_order_id", :unique => true
create_table "group_orders", :force => true do |t|
t.integer "ordergroup_id", :default => 0, :null => false
t.integer "order_id", :default => 0, :null => false
@ -151,6 +130,7 @@ ActiveRecord::Schema.define(:version => 20090119155930) do
t.string "task_name"
t.string "task_description"
t.integer "task_required_users", :default => 1
t.datetime "deleted_at"
end
add_index "groups", ["name"], :name => "index_groups_on_name", :unique => true
@ -175,6 +155,9 @@ ActiveRecord::Schema.define(:version => 20090119155930) do
t.decimal "amount", :precision => 8, :scale => 2, :default => 0.0, :null => false
t.datetime "created_at"
t.datetime "updated_at"
t.integer "order_id"
t.decimal "deposit", :precision => 8, :scale => 2, :default => 0.0, :null => false
t.decimal "deposit_credit", :precision => 8, :scale => 2, :default => 0.0, :null => false
end
create_table "memberships", :force => true do |t|
@ -194,23 +177,6 @@ ActiveRecord::Schema.define(:version => 20090119155930) do
t.datetime "created_at"
end
create_table "order_article_results", :force => true do |t|
t.integer "order_id", :default => 0, :null => false
t.string "name", :default => "", :null => false
t.string "unit", :default => "", :null => false
t.string "note"
t.decimal "net_price", :precision => 8, :scale => 2, :default => 0.0
t.decimal "gross_price", :precision => 8, :scale => 2, :default => 0.0, :null => false
t.float "tax", :default => 0.0, :null => false
t.decimal "deposit", :precision => 8, :scale => 2, :default => 0.0
t.float "fc_markup", :default => 0.0, :null => false
t.string "order_number"
t.integer "unit_quantity", :default => 0, :null => false
t.decimal "units_to_order", :precision => 6, :scale => 3, :default => 0.0, :null => false
end
add_index "order_article_results", ["order_id"], :name => "index_order_article_results_on_order_id"
create_table "order_articles", :force => true do |t|
t.integer "order_id", :default => 0, :null => false
t.integer "article_id", :default => 0, :null => false
@ -218,30 +184,27 @@ ActiveRecord::Schema.define(:version => 20090119155930) do
t.integer "tolerance", :default => 0, :null => false
t.integer "units_to_order", :default => 0, :null => false
t.integer "lock_version", :default => 0, :null => false
t.integer "article_price_id"
end
add_index "order_articles", ["order_id", "article_id"], :name => "index_order_articles_on_order_id_and_article_id", :unique => true
create_table "orders", :force => true do |t|
t.string "name", :default => "", :null => false
t.integer "supplier_id", :default => 0, :null => false
t.datetime "starts", :null => false
t.datetime "ends"
t.string "note"
t.boolean "finished", :default => false, :null => false
t.boolean "booked", :default => false, :null => false
t.integer "lock_version", :default => 0, :null => false
t.integer "updated_by_user_id"
t.decimal "invoice_amount", :precision => 8, :scale => 2, :default => 0.0, :null => false
t.decimal "deposit", :precision => 8, :scale => 2, :default => 0.0
t.decimal "deposit_credit", :precision => 8, :scale => 2, :default => 0.0
t.string "invoice_number"
t.string "invoice_date"
create_table "order_comments", :force => true do |t|
t.integer "order_id"
t.integer "user_id"
t.text "text"
t.datetime "created_at"
end
add_index "orders", ["ends"], :name => "index_orders_on_ends"
add_index "orders", ["finished"], :name => "index_orders_on_finished"
add_index "orders", ["starts"], :name => "index_orders_on_starts"
create_table "orders", :force => true do |t|
t.integer "supplier_id"
t.text "note"
t.datetime "starts"
t.datetime "ends"
t.string "state", :default => "open"
t.integer "lock_version", :default => 0, :null => false
t.integer "updated_by_user_id"
end
create_table "stock_changes", :force => true do |t|
t.integer "delivery_id"

View file

@ -202,6 +202,8 @@ table {
color: #008000; }
table tr.selected, table tr.active {
background-color: #ffffc2; }
table tr.click-me {
cursor: pointer; }
table.list tr {
border: 1px solid #e3e3e3; }

View file

@ -202,6 +202,8 @@ table {
color: #008000; }
table tr.selected, table tr.active {
background-color: #ffffc2; }
table tr.click-me {
cursor: pointer; }
table.list tr {
border: 1px solid #e3e3e3; }

View file

@ -227,6 +227,8 @@ table
:color #008000
tr.selected, tr.active
:background-color #ffffc2
tr.click-me
:cursor pointer
table.list
//:border 2px solid #78b74e

27
test/fixtures/article_prices.yml vendored Normal file
View file

@ -0,0 +1,27 @@
# == Schema Information
# Schema version: 20090120184410
#
# Table name: article_prices
#
# id :integer(4) not null, primary key
# article_id :integer(4)
# price :decimal(8, 2) default(0.0), not null
# tax :decimal(8, 2) default(0.0), not null
# deposit :decimal(8, 2) default(0.0), not null
# unit_quantity :integer(4)
# created_at :datetime
#
# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
one:
price: 9.99
tax: 9.99
deposit: 9.99
unit_quantity: 1
two:
price: 9.99
tax: 9.99
deposit: 9.99
unit_quantity: 1

View file

@ -1,25 +1,27 @@
# == Schema Information
# Schema version: 20090119155930
# Schema version: 20090120184410
#
# Table name: articles
#
# id :integer(4) not null, primary key
# name :string(255) not null
# supplier_id :integer(4) not null
# number :string(255)
# name :string(255) default(""), not null
# supplier_id :integer(4) default(0), not null
# article_category_id :integer(4) default(0), not null
# unit :string(255) default(""), not null
# note :string(255)
# availability :boolean(1) default(TRUE), not null
# manufacturer :string(255)
# origin :string(255)
# unit :string(255)
# price :decimal(8, 2) default(0.0), not null
# tax :decimal(3, 1) default(7.0), not null
# deposit :decimal(8, 2) default(0.0), not null
# unit_quantity :decimal(4, 1) default(1.0), not null
# scale_quantity :decimal(4, 2)
# scale_price :decimal(8, 2)
# created_on :datetime
# updated_on :datetime
# list :string(255)
# shared_updated_on :datetime
# price :decimal(8, 2)
# tax :float
# deposit :decimal(8, 2) default(0.0)
# unit_quantity :integer(4) default(1), not null
# order_number :string(255)
# created_at :datetime
# updated_at :datetime
# quantity :decimal(6, 2) default(0.0)
# deleted_at :datetime
#
# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html

View file

@ -1,17 +0,0 @@
# == Schema Information
# Schema version: 20090102171850
#
# Table name: group_order_article_results
#
# id :integer(4) not null, primary key
# order_article_result_id :integer(4) default(0), not null
# group_order_result_id :integer(4) default(0), not null
# quantity :decimal(6, 3) default(0.0)
# tolerance :integer(4)
#
# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
first:
id: 1
another:
id: 2

View file

@ -1,23 +0,0 @@
# == Schema Information
# Schema version: 20090102171850
#
# Table name: group_order_results
#
# id :integer(4) not null, primary key
# order_id :integer(4) default(0), not null
# group_name :string(255) default(""), not null
# price :decimal(8, 2) default(0.0), not null
#
# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
one:
id: 1
order_id: 1
group_name: Order Group 1
price: 99.95
two:
id: 2
order_id: 1
group_name: Order Group 2
price: 99.95

View file

@ -1,25 +0,0 @@
# == Schema Information
# Schema version: 20090102171850
#
# Table name: order_article_results
#
# id :integer(4) not null, primary key
# order_id :integer(4) default(0), not null
# name :string(255) default(""), not null
# unit :string(255) default(""), not null
# note :string(255)
# net_price :decimal(8, 2) default(0.0)
# gross_price :decimal(8, 2) default(0.0), not null
# tax :float default(0.0), not null
# deposit :decimal(8, 2) default(0.0)
# fc_markup :float default(0.0), not null
# order_number :string(255)
# unit_quantity :integer(4) default(0), not null
# units_to_order :decimal(6, 3) default(0.0), not null
#
# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
first:
id: 1
another:
id: 2

19
test/fixtures/order_comments.yml vendored Normal file
View file

@ -0,0 +1,19 @@
# == Schema Information
# Schema version: 20090120184410
#
# Table name: order_comments
#
# id :integer(4) not null, primary key
# order_id :integer(4)
# user_id :integer(4)
# text :text
# created_at :datetime
#
# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
# one:
# column: value
#
# two:
# column: value

View file

@ -1,23 +1,16 @@
# == Schema Information
# Schema version: 20090102171850
# Schema version: 20090120184410
#
# Table name: orders
#
# id :integer(4) not null, primary key
# name :string(255) default(""), not null
# supplier_id :integer(4) default(0), not null
# starts :datetime not null
# supplier_id :integer(4)
# note :text
# starts :datetime
# ends :datetime
# note :string(255)
# finished :boolean(1) not null
# booked :boolean(1) not null
# state :string(255) default("open")
# lock_version :integer(4) default(0), not null
# updated_by_user_id :integer(4)
# invoice_amount :decimal(8, 2) default(0.0), not null
# deposit :decimal(8, 2) default(0.0)
# deposit_credit :decimal(8, 2) default(0.0)
# invoice_number :string(255)
# invoice_date :string(255)
#
# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html

View file

@ -1,24 +1,21 @@
# == Schema Information
# Schema version: 20090119155930
# Schema version: 20090120184410
#
# Table name: suppliers
#
# id :integer(4) not null, primary key
# name :string(255) default(""), not null
# address :string(255) default(""), not null
# phone :string(255) default(""), not null
# 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)
# contact_person :string(255)
# customer_number :string(255)
# delivery_days :string(255)
# order_howto :string(255)
# note :string(255)
# shared_supplier_id :integer(4)
# min_order_quantity :string(255)
# deleted_at :datetime
# created_on :datetime
# updated_on :datetime
# lists :string(255)
#
# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html

View file

@ -0,0 +1,8 @@
require 'test_helper'
class ArticlePriceTest < ActiveSupport::TestCase
# Replace this with your real tests.
test "the truth" do
assert true
end
end

View file

@ -1,10 +0,0 @@
require File.dirname(__FILE__) + '/../test_helper'
class GroupOrderArticleResultTest < Test::Unit::TestCase
fixtures :group_order_article_results
# Replace this with your real tests.
def test_truth
assert true
end
end

View file

@ -1,10 +0,0 @@
require File.dirname(__FILE__) + '/../test_helper'
class GroupOrderResultTest < Test::Unit::TestCase
fixtures :group_order_results
# Replace this with your real tests.
def test_truth
assert true
end
end

View file

@ -1,10 +0,0 @@
require File.dirname(__FILE__) + '/../test_helper'
class OrderArticleResultTest < Test::Unit::TestCase
fixtures :order_article_results
# Replace this with your real tests.
def test_truth
assert true
end
end

View file

@ -0,0 +1,8 @@
require 'test_helper'
class OrderCommentTest < ActiveSupport::TestCase
# Replace this with your real tests.
test "the truth" do
assert true
end
end

View file

@ -1,7 +0,0 @@
* revision 8: Changed has_many :dependent => true to :dependent => :destroy for Rails 1.2.2
+ Thanks Josh Martin
Added an order clause in the has_many relationship.
Made comment column type to text from string in migration example in README
+ Thanks Patrick Crowley
Added this CHANGELOG file.

View file

@ -1,20 +0,0 @@
Copyright (c) 2006 Cosmin Radoi
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View file

@ -1,59 +0,0 @@
Acts As Commentable
=================
Allows for comments to be added to multiple and different models.
== Resources
Install
* Run the following command:
script/plugin install http://juixe.com/svn/acts_as_commentable
* Create a new rails migration and add the following self.up and self.down methods
def self.up
create_table "comments", :force => true do |t|
t.column "title", :string, :limit => 50, :default => ""
t.column "comment", :text, :default => ""
t.column "created_at", :datetime, :null => false
t.column "commentable_id", :integer, :default => 0, :null => false
t.column "commentable_type", :string, :limit => 15, :default => "", :null => false
t.column "user_id", :integer, :default => 0, :null => false
end
add_index "comments", ["user_id"], :name => "fk_comments_user"
end
def self.down
drop_table :comments
end
== Usage
* Make you ActiveRecord model act as commentable.
class Model < ActiveRecord::Base
acts_as_commentable
end
* Add a comment to a model instance
model = Model.new
comment = Comment.new
comment.comment = 'Some comment'
model.comments << comment
* Each comment reference commentable object
model = Model.find(1)
model.comments.get(0).commtable == model
== Credits
Xelipe - This plugin is heavily influced by Acts As Tagglable.
== More
http://www.juixe.com/techknow/index.php/2006/06/18/acts-as-commentable-plugin/
http://www.juixe.com/projects/acts_as_commentable

View file

@ -1,3 +0,0 @@
# Include hook code here
require 'acts_as_commentable'
ActiveRecord::Base.send(:include, Juixe::Acts::Commentable)

View file

@ -1 +0,0 @@
# Install hook code here

View file

@ -1,62 +0,0 @@
# ActsAsCommentable
module Juixe
module Acts #:nodoc:
module Commentable #:nodoc:
def self.included(base)
base.extend ClassMethods
end
module ClassMethods
def acts_as_commentable
has_many :comments, :as => :commentable, :dependent => :destroy, :order => 'created_at ASC'
include Juixe::Acts::Commentable::InstanceMethods
extend Juixe::Acts::Commentable::SingletonMethods
end
end
# This module contains class methods
module SingletonMethods
# Helper method to lookup for comments for a given object.
# This method is equivalent to obj.comments.
def find_comments_for(obj)
commentable = ActiveRecord::Base.send(:class_name_of_active_record_descendant, self).to_s
Comment.find(:all,
:conditions => ["commentable_id = ? and commentable_type = ?", obj.id, commentable],
:order => "created_at DESC"
)
end
# Helper class method to lookup comments for
# the mixin commentable type written by a given user.
# This method is NOT equivalent to Comment.find_comments_for_user
def find_comments_by_user(user)
commentable = ActiveRecord::Base.send(:class_name_of_active_record_descendant, self).to_s
Comment.find(:all,
:conditions => ["user_id = ? and commentable_type = ?", user.id, commentable],
:order => "created_at DESC"
)
end
end
# This module contains instance methods
module InstanceMethods
# Helper method to sort comments by date
def comments_ordered_by_submitted
Comment.find(:all,
:conditions => ["commentable_id = ? and commentable_type = ?", id, self.type.name],
:order => "created_at DESC"
)
end
# Helper method that defaults the submitted time.
def add_comment(comment)
comments << comment
end
end
end
end
end

View file

@ -1,34 +0,0 @@
class Comment < ActiveRecord::Base
belongs_to :commentable, :polymorphic => true
# NOTE: install the acts_as_votable plugin if you
# want user to vote on the quality of comments.
#acts_as_voteable
# NOTE: Comments belong to a user
belongs_to :user
# Helper class method to lookup all comments assigned
# to all commentable types for a given user.
def self.find_comments_by_user(user)
find(:all,
:conditions => ["user_id = ?", user.id],
:order => "created_at DESC"
)
end
# Helper class method to look up all comments for
# commentable class name and commentable id.
def self.find_comments_for_commentable(commentable_str, commentable_id)
find(:all,
:conditions => ["commentable_type = ? and commentable_id = ?", commentable_str, commentable_id],
:order => "created_at DESC"
)
end
# Helper class method to look up a commentable object
# given the commentable class name and id
def self.find_commentable(commentable_str, commentable_id)
commentable_str.constantize.find(commentable_id)
end
end

View file

@ -1,4 +0,0 @@
# desc "Explaining what the task does"
# task :acts_as_commentable do
# # Task goes here
# end

View file

@ -1,8 +0,0 @@
require 'test/unit'
class ActsAsCommentableTest < Test::Unit::TestCase
# Replace this with your real tests.
def test_this_plugin
flunk
end
end

View file

@ -8,6 +8,7 @@ require 'prawnto/action_view'
require 'prawnto/template_handler/compile_support'
require 'prawnto/template_handlers/base'
require 'prawn/layout' # Added by benni
#require 'prawnto/template_handlers/raw'
# for now applying to all Controllers