Ordering refactored: Made everything RESTful.
This commit is contained in:
parent
45e0048490
commit
eb4705857b
19 changed files with 340 additions and 222 deletions
|
@ -3,71 +3,51 @@
|
|||
class OrderingController < ApplicationController
|
||||
# Security
|
||||
before_filter :ensure_ordergroup_member
|
||||
before_filter :ensure_open_order, :only => [:order, :stock_order, :saveOrder]
|
||||
before_filter :ensure_open_order, :only => [:new, :create, :edit, :update, :order, :stock_order, :saveOrder]
|
||||
|
||||
# Index page.
|
||||
def index
|
||||
end
|
||||
|
||||
# Edit a current order.
|
||||
def order
|
||||
redirect_to :action => 'stock_order', :id => @order if @order.stockit?
|
||||
def new
|
||||
@group_order = @order.group_orders.build(:ordergroup => @ordergroup, :updated_by => current_user)
|
||||
@ordering_data = @group_order.load_data
|
||||
end
|
||||
|
||||
# Load order article data...
|
||||
@articles_grouped_by_category = @order.articles_grouped_by_category
|
||||
# save results of earlier orders in array
|
||||
ordered_articles = Array.new
|
||||
@group_order = @order.group_orders.find(:first,
|
||||
:conditions => "ordergroup_id = #{@ordergroup.id}", :include => :group_order_articles)
|
||||
|
||||
if @group_order
|
||||
# Group has already ordered, so get the results...
|
||||
for goa in @group_order.group_order_articles
|
||||
ordered_articles[goa.order_article_id] = {:quantity => goa.quantity,
|
||||
:tolerance => goa.tolerance,
|
||||
:quantity_result => goa.result(:quantity),
|
||||
:tolerance_result => goa.result(:tolerance)}
|
||||
end
|
||||
@version = @group_order.lock_version
|
||||
@availableFunds = @ordergroup.get_available_funds(@group_order)
|
||||
else
|
||||
@version = 0
|
||||
@availableFunds = @ordergroup.get_available_funds
|
||||
def create
|
||||
@group_order = GroupOrder.new(params[:group_order])
|
||||
begin
|
||||
@group_order.save_ordering!
|
||||
redirect_to group_order_url(@group_order), :notice => 'Die Bestellung wurde gespeichert.'
|
||||
rescue ActiveRecord::StaleObjectError
|
||||
redirect_to group_orders_url, :alert => 'In der Zwischenzeit hat jemand anderes auch bestellt, daher konnte die Bestellung nicht aktualisiert werden.'
|
||||
rescue => exception
|
||||
logger.error('Failed to update order: ' + exception.message)
|
||||
redirect_to group_orders_url, :alert => 'Die Bestellung konnte nicht aktualisiert werden, da ein Fehler auftrat.'
|
||||
end
|
||||
end
|
||||
|
||||
# load prices ....
|
||||
@price = Array.new; @unit = Array.new;
|
||||
@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_grouped_by_category.each do |category_name, order_articles|
|
||||
for order_article in order_articles
|
||||
# price/unit size
|
||||
@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)
|
||||
@others_quantity[i] = order_article.quantity - @quantity[i]
|
||||
@used_quantity[i] = (ordered_articles[order_article.id] ? ordered_articles[order_article.id][:quantity_result] : 0)
|
||||
# tolerance
|
||||
@tolerance[i] = (ordered_articles[order_article.id] ? ordered_articles[order_article.id][:tolerance] : 0)
|
||||
@others_tolerance[i] = order_article.tolerance - @tolerance[i]
|
||||
@used_tolerance[i] = (ordered_articles[order_article.id] ? ordered_articles[order_article.id][:tolerance_result] : 0)
|
||||
i += 1
|
||||
end
|
||||
end
|
||||
def show
|
||||
@group_order = GroupOrder.find(params[:id])
|
||||
@order= @group_order.order
|
||||
end
|
||||
|
||||
@add_data_to_js = []
|
||||
if Foodsoft.config[:tolerance_is_costly]
|
||||
for i in 0...@price.size
|
||||
@add_data_to_js << [@price[i], @unit[i], @price[i] * (@tolerance[i] + @quantity[i]), @others_quantity[i],
|
||||
@others_tolerance[i], @used_quantity[i], 0]
|
||||
end
|
||||
else
|
||||
for j in 0...@price.size
|
||||
@add_data_to_js << [@price[j], @unit[j], @price[j] * @quantity[j], @others_quantity[j],
|
||||
@others_tolerance[j], @used_quantity[j], 0]
|
||||
end
|
||||
def edit
|
||||
@group_order = GroupOrder.find(params[:id])
|
||||
@ordering_data = @group_order.load_data
|
||||
end
|
||||
|
||||
def update
|
||||
@group_order = GroupOrder.find(params[:id])
|
||||
@group_order.attributes = params[:group_order]
|
||||
begin
|
||||
@group_order.save_ordering!
|
||||
redirect_to group_order_url(@group_order), :notice => 'Die Bestellung wurde gespeichert.'
|
||||
rescue ActiveRecord::StaleObjectError
|
||||
redirect_to group_orders_url, :alert => 'In der Zwischenzeit hat jemand anderes auch bestellt, daher konnte die Bestellung nicht aktualisiert werden.'
|
||||
rescue => exception
|
||||
logger.error('Failed to update order: ' + exception.message)
|
||||
redirect_to group_orders_url, :alert => 'Die Bestellung konnte nicht aktualisiert werden, da ein Fehler auftrat.'
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -112,68 +92,9 @@ class OrderingController < ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
# Update changes to a current order.
|
||||
def saveOrder
|
||||
if (params[:total_balance].to_i < 0) #TODO: Better use a real test on sufficiant funds
|
||||
flash[:error] = 'Der Bestellwert übersteigt das verfügbare Guthaben.'
|
||||
redirect_to :action => 'order'
|
||||
elsif (ordered = params[:ordered])
|
||||
begin
|
||||
Order.transaction do
|
||||
# Try to find group_order
|
||||
group_order = @order.group_orders.first :conditions => "ordergroup_id = #{@ordergroup.id}",
|
||||
:include => [:group_order_articles]
|
||||
# Create group order if necessary...
|
||||
unless group_order.nil?
|
||||
# check for conflicts well ahead
|
||||
if (params[:version].to_i != group_order.lock_version)
|
||||
raise ActiveRecord::StaleObjectError
|
||||
end
|
||||
else
|
||||
group_order = @ordergroup.group_orders.create!(:order => @order, :updated_by => @current_user, :price => 0)
|
||||
end
|
||||
|
||||
# Create/update group_order_articles...
|
||||
for order_article in @order.order_articles
|
||||
|
||||
# Find the group_order_article, create a new one if necessary...
|
||||
group_order_article = group_order.group_order_articles.detect { |v| v.order_article_id == order_article.id }
|
||||
if group_order_article.nil?
|
||||
group_order_article = group_order.group_order_articles.create(:order_article_id => order_article.id)
|
||||
end
|
||||
|
||||
# Get ordered quantities and update group_order_articles/_quantities...
|
||||
quantities = ordered.fetch(order_article.id.to_s, {:quantity => 0, :tolerance => 0})
|
||||
group_order_article.update_quantities(quantities[:quantity].to_i, quantities[:tolerance].to_i)
|
||||
|
||||
# Also update results for the order_article
|
||||
order_article.update_results!
|
||||
end
|
||||
|
||||
group_order.update_price!
|
||||
group_order.update_attribute(:updated_by, @current_user)
|
||||
end
|
||||
flash[:notice] = 'Die Bestellung wurde gespeichert.'
|
||||
rescue ActiveRecord::StaleObjectError
|
||||
flash[:error] = 'In der Zwischenzeit hat jemand anderes auch bestellt, daher konnte die Bestellung nicht aktualisiert werden.'
|
||||
rescue => exception
|
||||
logger.error('Failed to update order: ' + exception.message)
|
||||
flash[:error] = 'Die Bestellung konnte nicht aktualisiert werden, da ein Fehler auftrat.'
|
||||
end
|
||||
redirect_to :action => 'my_order_result', :id => @order
|
||||
end
|
||||
end
|
||||
|
||||
# Shows the Result for the Ordergroup the current user belongs to
|
||||
# this method decides between finished and unfinished orders
|
||||
def my_order_result
|
||||
@order= Order.find(params[:id])
|
||||
@group_order = @order.group_order(@ordergroup)
|
||||
end
|
||||
|
||||
# Shows all Orders of the Ordergroup
|
||||
# if selected, it shows all orders of the foodcoop
|
||||
def myOrders
|
||||
def archive
|
||||
# get only orders belonging to the ordergroup
|
||||
@closed_orders = Order.paginate :page => params[:page], :per_page => 10,
|
||||
:conditions => { :state => 'closed' }, :order => "orders.ends DESC"
|
||||
|
@ -194,7 +115,7 @@ class OrderingController < ApplicationController
|
|||
else
|
||||
flash[:error] = "Kommentar konnte nicht erstellt werden. Leerer Kommentar?"
|
||||
end
|
||||
redirect_to :action => 'my_order_result', :id => order
|
||||
redirect_to :action => 'show', :id => order
|
||||
end
|
||||
|
||||
private
|
||||
|
@ -209,7 +130,8 @@ class OrderingController < ApplicationController
|
|||
end
|
||||
|
||||
def ensure_open_order
|
||||
@order = Order.find(params[:id], :include => [:supplier, :order_articles])
|
||||
@order = Order.find((params[:order_id] || params[:group_order][:order_id]),
|
||||
:include => [:supplier, :order_articles])
|
||||
unless @order.open?
|
||||
flash[:notice] = 'Diese Bestellung ist bereits abgeschlossen.'
|
||||
redirect_to :action => 'index'
|
||||
|
|
29
app/helpers/ordering_helper.rb
Normal file
29
app/helpers/ordering_helper.rb
Normal file
|
@ -0,0 +1,29 @@
|
|||
module OrderingHelper
|
||||
def data_to_js(ordering_data)
|
||||
ordering_data[:order_articles].map do |id, data|
|
||||
if Foodsoft.config[:tolerance_is_costly]
|
||||
[id, data[:price], data[:unit], data[:price] * (data[:tolerance] + data[:quantity]), data[:others_quantity], data[:others_tolerance], data[:used_quantity], 0]
|
||||
else
|
||||
[id, data[:price], data[:unit], data[:price] * data[:quantity], data[:others_quantity], data[:others_tolerance], data[:used_quantity], 0]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def link_to_ordering(order)
|
||||
path = if group_order = order.group_order(current_user.ordergroup)
|
||||
edit_group_order_path(group_order, :order_id => order.id)
|
||||
else
|
||||
new_group_order_path(:order_id => order.id)
|
||||
end
|
||||
link_to order.name, path
|
||||
end
|
||||
|
||||
# Return css class names for order result table
|
||||
def order_article_class_name(quantity, tolerance, result)
|
||||
if (quantity + tolerance > 0)
|
||||
result > 0 ? 'success' : 'failed'
|
||||
else
|
||||
'ignored'
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,6 +1,8 @@
|
|||
# A GroupOrder represents an Order placed by an Ordergroup.
|
||||
class GroupOrder < ActiveRecord::Base
|
||||
|
||||
|
||||
attr_accessor :group_order_articles_attributes
|
||||
|
||||
belongs_to :order
|
||||
belongs_to :ordergroup
|
||||
has_many :group_order_articles, :dependent => :destroy
|
||||
|
@ -14,27 +16,74 @@ class GroupOrder < ActiveRecord::Base
|
|||
|
||||
scope :open, lambda { {:conditions => ["order_id IN (?)", Order.open.collect(&:id)]} }
|
||||
scope :finished, lambda { {:conditions => ["order_id IN (?)", Order.finished_not_closed.collect(&:id)]} }
|
||||
|
||||
# Updates the "price" attribute.
|
||||
# Until the order is finished this will be the maximum price or
|
||||
# the minimum price depending on configuration. When the order is finished it
|
||||
# will be the value depending of the article results.
|
||||
def update_price!
|
||||
total = 0
|
||||
for article in group_order_articles.find(:all, :include => :order_article)
|
||||
unless order.finished?
|
||||
if Foodsoft.config[:tolerance_is_costly]
|
||||
total += article.order_article.article.fc_price * (article.quantity + article.tolerance)
|
||||
else
|
||||
total += article.order_article.article.fc_price * article.quantity
|
||||
end
|
||||
else
|
||||
total += article.order_article.price.fc_price * article.result
|
||||
|
||||
# Generate some data for the javascript methods in ordering view
|
||||
def load_data
|
||||
data = {}
|
||||
data[:available_funds] = ordergroup.get_available_funds(self)
|
||||
|
||||
unless new_record?
|
||||
# Group has already ordered, so get the results...
|
||||
goas = {}
|
||||
group_order_articles.all.each do |goa|
|
||||
goas[goa.order_article_id] = {:quantity => goa.quantity,
|
||||
:tolerance => goa.tolerance,
|
||||
:quantity_result => goa.result(:quantity),
|
||||
:tolerance_result => goa.result(:tolerance)}
|
||||
end
|
||||
end
|
||||
|
||||
# load prices ....
|
||||
data[:order_articles] = {}
|
||||
order.order_articles.each do |order_article|
|
||||
data[:order_articles][order_article.id] = {
|
||||
:price => order_article.article.fc_price,
|
||||
:unit => order_article.article.unit_quantity,
|
||||
:quantity => (new_record? ? 0 : goas[order_article.id][:quantity]),
|
||||
:others_quantity => order_article.quantity - (new_record? ? 0 : goas[order_article.id][:quantity]),
|
||||
:used_quantity => (new_record? ? 0 : goas[order_article.id][:quantity_result]),
|
||||
:tolerance => (new_record? ? 0 : goas[order_article.id][:tolerance]),
|
||||
:others_tolerance => order_article.tolerance - (new_record? ? 0 : goas[order_article.id][:tolerance]),
|
||||
:used_tolerance => (new_record? ? 0 : goas[order_article.id][:tolerance_result])
|
||||
}
|
||||
end
|
||||
|
||||
data
|
||||
end
|
||||
|
||||
def save_group_order_articles
|
||||
for order_article in order.order_articles
|
||||
# Find the group_order_article, create a new one if necessary...
|
||||
group_order_article = group_order_articles.find_or_create_by_order_article_id(order_article.id)
|
||||
|
||||
# Get ordered quantities and update group_order_articles/_quantities...
|
||||
quantities = group_order_articles_attributes.fetch(order_article.id.to_s, {:quantity => 0, :tolerance => 0})
|
||||
group_order_article.update_quantities(quantities[:quantity].to_i, quantities[:tolerance].to_i)
|
||||
|
||||
# Also update results for the order_article
|
||||
logger.debug "[save_group_order_articles] update order_article.results!"
|
||||
order_article.update_results!
|
||||
end
|
||||
|
||||
# set attributes to nil to avoid and infinite loop of
|
||||
end
|
||||
|
||||
# Updates the "price" attribute.
|
||||
def update_price!
|
||||
total = group_order_articles.includes(:order_article => :article).all.map(&:total_price).sum
|
||||
update_attribute(:price, total)
|
||||
end
|
||||
|
||||
|
||||
# Save GroupOrder and updates group_order_articles/quantities accordingly
|
||||
def save_ordering!
|
||||
transaction do
|
||||
save!
|
||||
save_group_order_articles
|
||||
update_price!
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# == Schema Information
|
||||
|
|
|
@ -14,15 +14,10 @@ class GroupOrderArticle < ActiveRecord::Base
|
|||
validates_inclusion_of :tolerance, :in => 0..99
|
||||
validates_uniqueness_of :order_article_id, :scope => :group_order_id # just once an article per group order
|
||||
|
||||
attr_accessor :ordergroup_id # To create an new GroupOrder if neccessary
|
||||
|
||||
scope :ordered, :conditions => 'result > 0'
|
||||
|
||||
# Custom attribute setter that accepts decimal numbers using localized decimal separator.
|
||||
def result=(result)
|
||||
self[:result] = String.delocalized_decimal(result)
|
||||
end
|
||||
|
||||
localize_input_of :result
|
||||
|
||||
# Updates the quantity/tolerance for this GroupOrderArticle by updating both GroupOrderArticle properties
|
||||
# and the associated GroupOrderArticleQuantities chronologically.
|
||||
#
|
||||
|
@ -30,17 +25,17 @@ class GroupOrderArticle < ActiveRecord::Base
|
|||
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.
|
||||
quantities = group_order_article_quantities.find(:all, :order => 'created_on desc')
|
||||
logger.debug("GroupOrderArticleQuantity items found: #{quantities.size}")
|
||||
|
||||
if (quantities.size == 0)
|
||||
if (quantities.size == 0)
|
||||
# There is no GroupOrderArticleQuantity item yet, just insert with desired quantities...
|
||||
logger.debug("No quantities entry at all, inserting a new one with the desired quantities")
|
||||
quantities.push(GroupOrderArticleQuantity.new(:group_order_article => self, :quantity => quantity, :tolerance => tolerance))
|
||||
self.quantity, self.tolerance = quantity, tolerance
|
||||
else
|
||||
self.quantity, self.tolerance = quantity, tolerance
|
||||
else
|
||||
# Decrease quantity/tolerance if necessary by going through the existing items and decreasing their values...
|
||||
i = 0
|
||||
while (i < quantities.size && (quantity < self.quantity || tolerance < self.tolerance))
|
||||
|
@ -50,31 +45,31 @@ class GroupOrderArticle < ActiveRecord::Base
|
|||
delta = (delta > quantities[i].quantity ? quantities[i].quantity : delta)
|
||||
logger.debug("Decreasing quantity by #{delta}")
|
||||
quantities[i].quantity -= delta
|
||||
self.quantity -= delta
|
||||
self.quantity -= delta
|
||||
end
|
||||
if (tolerance < self.tolerance && quantities[i].tolerance > 0)
|
||||
delta = self.tolerance - tolerance
|
||||
delta = (delta > quantities[i].tolerance ? quantities[i].tolerance : delta)
|
||||
logger.debug("Decreasing tolerance by #{delta}")
|
||||
quantities[i].tolerance -= delta
|
||||
self.tolerance -= delta
|
||||
self.tolerance -= delta
|
||||
end
|
||||
i += 1
|
||||
end
|
||||
end
|
||||
# If there is at least one increased value: insert a new GroupOrderArticleQuantity object
|
||||
if (quantity > self.quantity || tolerance > self.tolerance)
|
||||
logger.debug("Inserting a new GroupOrderArticleQuantity")
|
||||
quantities.insert(0, GroupOrderArticleQuantity.new(
|
||||
:group_order_article => self,
|
||||
:quantity => (quantity > self.quantity ? quantity - self.quantity : 0),
|
||||
:tolerance => (tolerance > self.tolerance ? tolerance - self.tolerance : 0)
|
||||
:group_order_article => self,
|
||||
:quantity => (quantity > self.quantity ? quantity - self.quantity : 0),
|
||||
:tolerance => (tolerance > self.tolerance ? tolerance - self.tolerance : 0)
|
||||
))
|
||||
# Recalc totals:
|
||||
self.quantity += quantities[0].quantity
|
||||
self.tolerance += quantities[0].tolerance
|
||||
self.tolerance += quantities[0].tolerance
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# Check if something went terribly wrong and quantites have not been adjusted as desired.
|
||||
if (self.quantity != quantity || self.tolerance != tolerance)
|
||||
raise 'Invalid state: unable to update GroupOrderArticle/-Quantities to desired quantities!'
|
||||
|
@ -82,7 +77,7 @@ class GroupOrderArticle < ActiveRecord::Base
|
|||
|
||||
# Remove zero-only items.
|
||||
quantities = quantities.reject { | q | q.quantity == 0 && q.tolerance == 0}
|
||||
|
||||
|
||||
# Save
|
||||
transaction do
|
||||
quantities.each { | i | i.save! }
|
||||
|
@ -90,7 +85,7 @@ class GroupOrderArticle < ActiveRecord::Base
|
|||
save!
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# Determines how many items of this article the Ordergroup receives.
|
||||
# Returns a hash with three keys: :quantity / :tolerance / :total
|
||||
#
|
||||
|
@ -102,15 +97,15 @@ class GroupOrderArticle < ActiveRecord::Base
|
|||
# Get total
|
||||
total = stockit ? order_article.article.quantity : order_article.units_to_order * order_article.price.unit_quantity
|
||||
logger.debug("<#{order_article.article.name}>.unitsToOrder => items ordered: #{order_article.units_to_order} => #{total}")
|
||||
|
||||
|
||||
if (total > 0)
|
||||
# In total there are enough units ordered. Now check the individual result for the ordergroup (group_order).
|
||||
#
|
||||
# Get all GroupOrderArticleQuantities for this OrderArticle...
|
||||
order_quantities = GroupOrderArticleQuantity.all(
|
||||
:conditions => ["group_order_article_id IN (?)", order_article.group_order_article_ids], :order => 'created_on')
|
||||
:conditions => ["group_order_article_id IN (?)", order_article.group_order_article_ids], :order => 'created_on')
|
||||
logger.debug("GroupOrderArticleQuantity records found: #{order_quantities.size}")
|
||||
|
||||
|
||||
# Determine quantities to be ordered...
|
||||
total_quantity = i = 0
|
||||
while (i < order_quantities.size && total_quantity < total)
|
||||
|
@ -137,10 +132,10 @@ class GroupOrderArticle < ActiveRecord::Base
|
|||
i += 1
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
logger.debug("determined quantity/tolerance/total: #{quantity} / #{tolerance} / #{quantity + tolerance}")
|
||||
end
|
||||
|
||||
|
||||
{:quantity => quantity, :tolerance => tolerance, :total => quantity + tolerance}
|
||||
end
|
||||
memoize :calculate_result
|
||||
|
@ -156,7 +151,23 @@ class GroupOrderArticle < ActiveRecord::Base
|
|||
def save_results!
|
||||
self.update_attribute(:result, calculate_result[:total])
|
||||
end
|
||||
|
||||
|
||||
# Returns total price for this individual article
|
||||
# Until the order is finished this will be the maximum price or
|
||||
# the minimum price depending on configuration. When the order is finished it
|
||||
# will be the value depending of the article results.
|
||||
def total_price
|
||||
unless order_article.order.finished?
|
||||
if Foodsoft.config[:tolerance_is_costly]
|
||||
order_article.article.fc_price * (quantity + tolerance)
|
||||
else
|
||||
order_article.article.fc_price * quantity
|
||||
end
|
||||
else
|
||||
order_article.price.fc_price * result
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
|
|
@ -85,16 +85,16 @@ class Order < ActiveRecord::Base
|
|||
|
||||
# search GroupOrder of given Ordergroup
|
||||
def group_order(ordergroup)
|
||||
group_orders.first :conditions => { :ordergroup_id => ordergroup.id }
|
||||
group_orders.where(:ordergroup_id => ordergroup.id).first
|
||||
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 articles_grouped_by_category
|
||||
order_articles.all(:include => [:article, :article_price], :order => 'articles.name').group_by { |a|
|
||||
a.article.article_category.name
|
||||
}.sort { |a, b| a[0] <=> b[0] }
|
||||
order_articles.includes(:article, :article_price).order('articles.name').
|
||||
group_by { |a| a.article.article_category.name }.
|
||||
sort { |a, b| a[0] <=> b[0] }
|
||||
end
|
||||
memoize :articles_grouped_by_category
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
:active => ["orders", "ordering"],
|
||||
:subnav => [
|
||||
{ :name => "Bestellen!", :url => ordering_path },
|
||||
{ :name => "Meine Bestellungen", :url => my_orders_path },
|
||||
{ :name => "Meine Bestellungen", :url => archive_group_orders_path },
|
||||
{ :name => "Bestellverwaltung", :url => orders_path, :access_denied? => (!u.role_orders?) }
|
||||
]
|
||||
},
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
<script>
|
||||
//<![CDATA[
|
||||
$(function() {
|
||||
<% for row in @add_data_to_js %>
|
||||
<% for row in data_to_js(@ordering_data) %>
|
||||
addData(<%= row.join(", ") %>);
|
||||
<% end %>
|
||||
setGroupBalance(<%= @availableFunds %>);
|
||||
setGroupBalance(<%= @ordering_data[:available_funds] %>);
|
||||
|
||||
// localization
|
||||
setDecimalSeparator(",");
|
||||
|
|
23
app/views/ordering/_footer.html.haml
Normal file
23
app/views/ordering/_footer.html.haml
Normal file
|
@ -0,0 +1,23 @@
|
|||
#order-footer
|
||||
#info-box
|
||||
#total-sum
|
||||
%table
|
||||
%tr
|
||||
%td Gesamtbetrag:
|
||||
%td.currency
|
||||
%span#total_price= total
|
||||
€
|
||||
%tr
|
||||
%td Verfügbares Guthaben:
|
||||
%td.currency= number_to_currency(@ordering_data[:available_funds])
|
||||
%tr
|
||||
%td Neuer Kontostand:
|
||||
%td.currency
|
||||
%strong
|
||||
%span#new_balance= @ordergroup.account_balance - total
|
||||
€
|
||||
#order-button
|
||||
= submit_tag( "Bestellung speichern", :id => 'submit_button' )
|
||||
oder #{link_to "abbrechen", :controller => 'ordering'}
|
||||
%input#total_balance{:name => "total_balance", :type => "hidden", :value => @ordergroup.account_balance - total}/
|
||||
%input{:name => "version", :type => "hidden", :value => @version}/
|
90
app/views/ordering/_form.html.haml
Normal file
90
app/views/ordering/_form.html.haml
Normal file
|
@ -0,0 +1,90 @@
|
|||
- content_for :head do
|
||||
= render 'data'
|
||||
|
||||
= render :partial => 'order_head'
|
||||
|
||||
- form_for @group_order do |f|
|
||||
= f.hidden_field :lock_version
|
||||
= f.hidden_field :order_id
|
||||
= f.hidden_field :updated_by_user_id
|
||||
= f.hidden_field :ordergroup_id
|
||||
.single_column{:style => "clear:both;margin-bottom:7em;"}
|
||||
.box_title
|
||||
%h2 Artikel
|
||||
.column_content
|
||||
%table#order.list
|
||||
%thead
|
||||
%tr
|
||||
%th Name
|
||||
%th{:style => "width:13px;"}
|
||||
%th{:style => "width:4.5em;"} Preis
|
||||
%th{:style => "width:4.5em;"} Einheit
|
||||
%th{:style => "width:70px;"} Fehlende Einheiten
|
||||
%th#col_required Menge
|
||||
- if not @order.stockit?
|
||||
%th#col_tolerance Toleranz
|
||||
%th{:style => "width:15px;"} Summe
|
||||
%tbody
|
||||
- total = 0
|
||||
- @order.articles_grouped_by_category.each do |category, order_articles|
|
||||
%tr{:style => "background-color:#EFEFEF"}
|
||||
%td{:style => "text-align:left"}
|
||||
%b= h category
|
||||
%td{:colspan => "9"}
|
||||
- order_articles.each do |order_article|
|
||||
- if Foodsoft.config[:tolerance_is_costly]
|
||||
- article_total = @ordering_data[:order_articles][order_article.id][:price] * (@ordering_data[:order_articles][order_article.id][:tolerance] + @ordering_data[:order_articles][order_article.id][:quantity])
|
||||
- else
|
||||
- article_total = @ordering_data[:order_articles][order_article.id][:price] * @ordering_data[:order_articles][order_article.id][:quantity]
|
||||
- total += article_total
|
||||
%tr{:class => "#{cycle('even', 'odd', :name => 'articles')} order-article", :valign => "top"}
|
||||
%td.name= order_article.article.name
|
||||
%td= h order_article.article.origin
|
||||
%td= number_to_currency(@ordering_data[:order_articles][order_article.id][:price])
|
||||
%td= order_article.article.unit
|
||||
%td
|
||||
%span{:id => "missing_units_#{order_article.id}"}
|
||||
- if @order.stockit?
|
||||
- order_article.article.quantity_available
|
||||
- else
|
||||
- missing_units = @ordering_data[:order_articles][order_article.id][:unit] - (((@ordering_data[:order_articles][order_article.id][:quantity] + @ordering_data[:order_articles][order_article.id][:others_quantity]) % @ordering_data[:order_articles][order_article.id][:unit]) + @ordering_data[:order_articles][order_article.id][:tolerance] + @ordering_data[:order_articles][order_article.id][:others_tolerance])
|
||||
- missing_units < 0 ? 0 : missing_units
|
||||
%td.quantity
|
||||
%input{:id => "q_#{order_article.id}", :name => "group_order[group_order_articles_attributes][#{order_article.id}][quantity]", :size => "2", :type => "hidden", :value => @ordering_data[:order_articles][order_article.id][:quantity]}/
|
||||
%span.used{:id => "q_used_#{order_article.id}"}= @ordering_data[:order_articles][order_article.id][:used_quantity]
|
||||
+
|
||||
%span.unused{:id => "q_unused_#{order_article.id}"}= @ordering_data[:order_articles][order_article.id][:quantity] - @ordering_data[:order_articles][order_article.id][:used_quantity]
|
||||
%input{:type => 'button', :value => '+', 'data-increase_quantity' => order_article.id}
|
||||
%input{:type => 'button', :value => '-', 'data-decrease_quantity' => order_article.id}
|
||||
- unless @order.stockit?
|
||||
%td.tolerance
|
||||
%input{:id => "t_#{order_article.id}", :name => "group_order[group_order_articles_attributes][#{order_article.id}][tolerance]", :size => "2", :type => "hidden", :value => @ordering_data[:order_articles][order_article.id][:tolerance]}/
|
||||
- if (@ordering_data[:order_articles][order_article.id][:unit] > 1)
|
||||
%span.used{:id => "t_used_#{order_article.id}"}= @ordering_data[:order_articles][order_article.id][:used_tolerance]
|
||||
+
|
||||
%span.unused{:id => "t_unused_#{order_article.id}"}= @ordering_data[:order_articles][order_article.id][:tolerance] - @ordering_data[:order_articles][order_article.id][:used_tolerance]
|
||||
%input{:type => 'button', :value => '+', 'data-increase_tolerance' => order_article.id}
|
||||
%input{:type => 'button', :value => '-', 'data-decrease_tolerance' => order_article.id}
|
||||
%td{:id => "td_price_#{order_article.id}", :style => "text-align:right; padding-right:10px; width:4em"}
|
||||
%span{:id => "price_#{order_article.id}_display"}= number_to_currency(article_total, :unit => "")
|
||||
€
|
||||
.article-info
|
||||
%h3= order_article.article.name
|
||||
.right
|
||||
Volle Gebinde:
|
||||
%span{:id => "units_#{order_article.id}"}= order_article.units_to_order
|
||||
%br/
|
||||
Gesamt-Einheiten:
|
||||
%span{:id => "q_total_#{order_article.id}"}= @ordering_data[:order_articles][order_article.id][:quantity] + @ordering_data[:order_articles][order_article.id][:others_quantity]
|
||||
%br/
|
||||
Gesamt-Toleranz:
|
||||
%span{:id => "t_total_#{order_article.id}"}= @ordering_data[:order_articles][order_article.id][:tolerance] + @ordering_data[:order_articles][order_article.id][:others_tolerance]
|
||||
%br/
|
||||
.left
|
||||
Hersteller: #{order_article.article.manufacturer}
|
||||
%br/
|
||||
Gebinde: #{@order.stockit? ? order_article.article.quantity_available : @ordering_data[:order_articles][order_article.id][:unit]} * #{h order_article.article.unit}
|
||||
%br/
|
||||
Notiz: #{order_article.article.note}
|
||||
%br/
|
||||
= render "footer", :total => total
|
|
@ -20,7 +20,7 @@
|
|||
= "(#{format_time(@group_order.updated_on)})"
|
||||
%p
|
||||
%b Verfügbares Guthaben:
|
||||
= number_to_currency(@availableFunds)
|
||||
= number_to_currency(@ordering_data[:available_funds])
|
||||
%td
|
||||
- unless @order.note.empty?
|
||||
%p
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
- title "Bestellungen der #{@ordergroup.name}"
|
||||
%p
|
||||
Siehe hier alle
|
||||
= link_to "laufenden Bestellungen.", :action => "index"
|
||||
= link_to "laufenden Bestellungen.", ordering_path
|
||||
|
||||
.single_column{:style => "width:50em"}
|
||||
.box_title
|
1
app/views/ordering/edit.html.haml
Normal file
1
app/views/ordering/edit.html.haml
Normal file
|
@ -0,0 +1 @@
|
|||
= render 'form'
|
|
@ -10,18 +10,17 @@
|
|||
%td Kontostand:
|
||||
%td{:class => "currency", :style => "width:5em"}= number_to_currency(@ordergroup.account_balance)
|
||||
%tr
|
||||
%td - laufende Bestellungen:
|
||||
%td= "- laufende Bestellungen:"
|
||||
%td{:class => "currency"}= number_to_currency(@ordergroup.value_of_open_orders)
|
||||
%tr
|
||||
%td - nicht abgerechnete Bestellungen:
|
||||
%td= "- nicht abgerechnete Bestellungen:"
|
||||
%td{:class => "currency"}= number_to_currency(@ordergroup.value_of_finished_orders)
|
||||
%tr
|
||||
%th verfügbares Guthaben:
|
||||
%th{:class => "currency"}= number_to_currency(@ordergroup.get_available_funds)
|
||||
|
||||
.right_column{:style => "width:70%"}
|
||||
// open orders
|
||||
= render :partial => "shared/open_orders"
|
||||
= render :partial => "shared/open_orders", :locals => {:ordergroup => @ordergroup}
|
||||
|
||||
// finished orders
|
||||
- unless Order.finished.empty?
|
||||
|
@ -41,4 +40,4 @@
|
|||
.column_content
|
||||
= render :partial => "orders", :locals => {:orders => Order.closed.all(:limit => 5), :pagination => false}
|
||||
%br/
|
||||
= link_to "mehr...", :action => "myOrders"
|
||||
= link_to "mehr...", archive_group_orders_path
|
1
app/views/ordering/new.html.haml
Normal file
1
app/views/ordering/new.html.haml
Normal file
|
@ -0,0 +1 @@
|
|||
= render 'form'
|
|
@ -1,21 +1,10 @@
|
|||
- content_for :head do
|
||||
:javascript
|
||||
document.observe("dom:loaded", function() {
|
||||
// initially hide all ignored articles
|
||||
$$('tr.ignored').invoke('hide');
|
||||
$(function() {
|
||||
$('tr.ignored').hide();
|
||||
});
|
||||
function toggleIgnoredArticles() {
|
||||
$$('tr.ignored').invoke('toggle');
|
||||
};
|
||||
|
||||
|
||||
- title "Dein Bestellergebnis für #{@order.name}"
|
||||
#element_navigation
|
||||
= link_to_unless @order.previous == @order, "<< #{@order.previous.name}", :action => "my_order_result", :id => @order.previous
|
||||
|
|
||||
= link_to "Übersicht", :controller => 'ordering'
|
||||
|
|
||||
= link_to_unless @order.next == @order, "#{@order.next.name} >>", :action => "my_order_result", :id => @order.next
|
||||
|
||||
// Order summary
|
||||
.left_column{:style => "width:45em"}
|
||||
|
@ -54,7 +43,7 @@
|
|||
%table
|
||||
- for order in Order.open
|
||||
%tr
|
||||
%td= link_to order.name, :action => 'order', :id => order
|
||||
%td= link_to_ordering(order)
|
||||
%td= "("+ time_ago_in_words(order.ends) + ")" if order.ends
|
||||
|
||||
// Article box
|
||||
|
@ -63,8 +52,8 @@
|
|||
%h2 Artikelübersicht
|
||||
.column_content#result
|
||||
- if @group_order
|
||||
%p(style="float:right")= link_to_function "Zeige/Verstecke nicht bestellte Artikel", "toggleIgnoredArticles();"
|
||||
%p= link_to("Bestellung ändern", :action => "order", :id => @order) if @order.open?
|
||||
%p(style="float:right")= link_to "Zeige/Verstecke nicht bestellte Artikel", '#', 'data-toggle-this' => 'tr.ignored'
|
||||
%p= link_to("Bestellung ändern", edit_group_order_path(@group_order, :order_id => @order.id)) if @order.open?
|
||||
%table.list
|
||||
%thead
|
||||
%tr
|
||||
|
@ -87,26 +76,13 @@
|
|||
%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.result
|
||||
- if @order.open?
|
||||
- if Foodsoft.config[:tolerance_is_costly]
|
||||
- sub_total = oa.price.fc_price * (quantity + tolerance)
|
||||
- else
|
||||
- sub_total = oa.price.fc_price * quantity
|
||||
- else
|
||||
- sub_total = oa.price.fc_price * result
|
||||
- else
|
||||
- quantity, tolerance, result, sub_total = 0, 0, 0, 0
|
||||
- goa = oa.group_order_articles.find_by_group_order_id(@group_order.id)
|
||||
- quantity = goa.quantity
|
||||
- tolerance = goa.tolerance
|
||||
- result = goa.result
|
||||
- sub_total = goa.total_price
|
||||
- total += sub_total
|
||||
- # give the article different colors, dependent on order-result
|
||||
- class_name = "ignored"
|
||||
- if (quantity + tolerance > 0)
|
||||
- class_name = result > 0 ? 'success' : 'failed'
|
||||
%tr{:class => cycle('even', 'odd', :name => 'articles') + " " + class_name}
|
||||
%tr{:class => cycle('even', 'odd', :name => 'articles') + " " + order_article_class_name(quantity, tolerance, result)}
|
||||
%td{:style => "width:40%"}
|
||||
=h oa.article.name
|
||||
- unless oa.article.note.blank?
|
|
@ -13,7 +13,7 @@
|
|||
- total = 0
|
||||
- Order.open.each do |order|
|
||||
%tr{:class => cycle('even', 'odd', :name => 'open_orders')}
|
||||
%td= link_to h(order.name), :controller => 'ordering', :action => 'order', :id => order
|
||||
%td= link_to_ordering(order)
|
||||
%td=h format_time(order.ends) unless order.ends.nil?
|
||||
- if group_order = order.group_order(ordergroup)
|
||||
- total += group_order.price
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
# TODO: When to use class or module. It seems this could also be a Foodsoft-class?
|
||||
module Foodsoft
|
||||
mattr_accessor :env, :config, :database
|
||||
CONFIGS = YAML.load(File.read(RAILS_ROOT + "/config/app_config.yml"))
|
||||
DATABASES = YAML.load(File.read(RAILS_ROOT + "/config/database.yml"))
|
||||
CONFIGS = YAML.load(File.read(File.join(Rails.root, "/config/app_config.yml")))
|
||||
DATABASES = YAML.load(File.read(File.join(Rails.root, "/config/database.yml")))
|
||||
|
||||
class << self
|
||||
def env=(env)
|
||||
|
@ -15,7 +15,7 @@ module Foodsoft
|
|||
end
|
||||
end
|
||||
# Initial load the default config and database from rails environment
|
||||
Foodsoft.env = RAILS_ENV
|
||||
Foodsoft.env = Rails.env
|
||||
|
||||
# Set action mailer default host for url generating
|
||||
url_options = {
|
||||
|
|
|
@ -39,7 +39,9 @@ Foodsoft::Application.routes.draw do
|
|||
end
|
||||
end
|
||||
|
||||
match '/ordering/myOrders' => 'ordering#myOrders', :as => 'my_orders'
|
||||
resources :group_orders, :controller => 'ordering', :path => 'ordering' do
|
||||
get :archive, :on => :collection
|
||||
end
|
||||
match '/ordering' => 'ordering#index', :as => 'ordering'
|
||||
|
||||
############ Foodcoop orga
|
||||
|
|
|
@ -31,8 +31,8 @@ function setGroupBalance(amount) {
|
|||
groupBalance = amount;
|
||||
}
|
||||
|
||||
function addData(itemPrice, itemUnit, itemSubtotal, itemQuantityOthers, itemToleranceOthers, allocated, available) {
|
||||
i = price.length;
|
||||
function addData(orderArticleId, itemPrice, itemUnit, itemSubtotal, itemQuantityOthers, itemToleranceOthers, allocated, available) {
|
||||
i = orderArticleId;
|
||||
price[i] = itemPrice;
|
||||
unit[i] = itemUnit;
|
||||
itemTotal[i] = itemSubtotal;
|
||||
|
@ -77,7 +77,7 @@ function update(item, quantity, tolerance) {
|
|||
// calculate how many units would be ordered in total
|
||||
units = calcUnits(unit[item], quantityOthers[item] + Number(quantity), toleranceOthers[item] + Number(tolerance));
|
||||
if (unitCompletedFromTolerance(unit[item], quantityOthers[item] + Number(quantity), toleranceOthers[item] + Number(tolerance))) {
|
||||
$('#units_' + item).html('<span style="color:grey">' + String(units) + "</span>");
|
||||
$('#units_' + item).html('<span style=\"color:grey\">' + String(units) + '</span>');
|
||||
} else {
|
||||
$('#units_' + item).html(String(units));
|
||||
}
|
||||
|
@ -140,7 +140,7 @@ function updateStockQuantity(item, quantity) {
|
|||
modified = true
|
||||
|
||||
// update hidden input fields
|
||||
$('#q_' + item).val() = quantity;
|
||||
$('#q_' + item).val(quantity);
|
||||
|
||||
// update used/unused quantity
|
||||
available = Math.max(0, quantityAvailable[item] - quantityOthers[item]);
|
||||
|
@ -179,7 +179,7 @@ function unitCompletedFromTolerance(unitSize, quantity, tolerance) {
|
|||
function updateBalance() {
|
||||
// update total price and order balance
|
||||
total = 0;
|
||||
for (i = 0; i < itemTotal.length; i++) {
|
||||
for (i in itemTotal) {
|
||||
total += itemTotal[i];
|
||||
}
|
||||
$('#total_price').html(asMoney(total));
|
||||
|
@ -195,7 +195,7 @@ function updateBalance() {
|
|||
$('#submit_button').disabled = false;
|
||||
}
|
||||
// update bgcolor
|
||||
for (i = 0; i < itemTotal.length; i++) {
|
||||
for (i in itemTotal) {
|
||||
$('#ltd_price_' + i).css('background-color', bgcolor);
|
||||
}
|
||||
}
|
||||
|
@ -203,3 +203,18 @@ function updateBalance() {
|
|||
function confirmSwitchOrder() {
|
||||
return (!modified || confirm('Änderungen an dieser Bestellung gehen verloren, wenn zu einer anderen Bestellung gewechselt wird.'))
|
||||
}
|
||||
|
||||
$(function() {
|
||||
$('input[data-increase_quantity]').click(function() {
|
||||
increaseQuantity($(this).data('increase_quantity'));
|
||||
})
|
||||
$('input[data-decrease_quantity]').click(function() {
|
||||
decreaseQuantity($(this).data('decrease_quantity'));
|
||||
})
|
||||
$('input[data-increase_tolerance]').click(function() {
|
||||
increaseTolerance($(this).data('increase_tolerance'));
|
||||
})
|
||||
$('input[data-decrease_tolerance]').click(function() {
|
||||
decreaseTolerance($(this).data('decrease_tolerance'));
|
||||
})
|
||||
})
|
||||
|
|
Loading…
Reference in a new issue