Merge remote-tracking branch 'upstream/master' into multiple-recurring-tasks

Conflicts:
	config/locales/de.yml
This commit is contained in:
Robert Waltemath 2013-06-12 10:00:11 +02:00
commit 46b07a6136
257 changed files with 5408 additions and 1931 deletions

21
Gemfile
View file

@ -11,22 +11,22 @@ group :assets do
gem 'coffee-rails', '~> 3.2.1'
# See https://github.com/sstephenson/execjs#readme for more supported runtimes
gem 'therubyracer', :platforms => :ruby
gem 'therubyracer', platforms: :ruby
gem 'uglifier', '>= 1.0.3'
end
gem 'jquery-rails'
gem 'mysql2'
gem 'prawn'
gem 'haml-rails'
gem 'kaminari'
gem 'client_side_validations'
gem 'simple_form'
gem 'rails3_acts_as_paranoid', "~>0.2.0"
gem 'inherited_resources'
gem 'localize_input', :git => "git://github.com/bennibu/localize_input.git"
gem 'localize_input', git: "git://github.com/bennibu/localize_input.git"
gem 'wikicloth'
gem 'daemons'
gem 'twitter-bootstrap-rails'
@ -37,14 +37,15 @@ gem 'acts_as_versioned', git: 'git://github.com/technoweenie/acts_as_versioned.g
gem 'acts_as_tree'
gem 'acts_as_configurable', git: 'git://github.com/bwalding/acts_as_configurable.git'
gem 'resque'
gem 'whenever', :require => false # For defining cronjobs, see config/schedule.rb
gem 'whenever', require: false # For defining cronjobs, see config/schedule.rb
group :production do
gem 'exception_notification', :require => 'exception_notifier'
gem 'exception_notification', require: 'exception_notifier'
end
group :development do
gem 'sqlite3'
gem 'mailcatcher'
# Better error output
gem 'better_errors'
@ -56,4 +57,14 @@ group :development do
# Get infos when not using proper eager loading
gem 'bullet'
# Hide assets requests in log
gem 'quiet_assets'
# Deploy with Capistrano
gem 'capistrano', '2.13.5'
gem 'capistrano-ext'
#gem 'common_deploy', require: false, path: '../../common_deploy' # pending foodcoops/foodsoft#34, git: 'git://github.com/fsmanuel/common_deploy.git'
# Avoid having content-length warnings
gem 'thin'
end

View file

@ -22,32 +22,32 @@ GEM
remote: https://rubygems.org/
specs:
Ascii85 (1.0.2)
actionmailer (3.2.11)
actionpack (= 3.2.11)
mail (~> 2.4.4)
actionpack (3.2.11)
activemodel (= 3.2.11)
activesupport (= 3.2.11)
actionmailer (3.2.13)
actionpack (= 3.2.13)
mail (~> 2.5.3)
actionpack (3.2.13)
activemodel (= 3.2.13)
activesupport (= 3.2.13)
builder (~> 3.0.0)
erubis (~> 2.7.0)
journey (~> 1.0.4)
rack (~> 1.4.0)
rack (~> 1.4.5)
rack-cache (~> 1.2)
rack-test (~> 0.6.1)
sprockets (~> 2.2.1)
activemodel (3.2.11)
activesupport (= 3.2.11)
activemodel (3.2.13)
activesupport (= 3.2.13)
builder (~> 3.0.0)
activerecord (3.2.11)
activemodel (= 3.2.11)
activesupport (= 3.2.11)
activerecord (3.2.13)
activemodel (= 3.2.13)
activesupport (= 3.2.13)
arel (~> 3.0.2)
tzinfo (~> 0.3.29)
activeresource (3.2.11)
activemodel (= 3.2.11)
activesupport (= 3.2.11)
activesupport (3.2.11)
i18n (~> 0.6)
activeresource (3.2.13)
activemodel (= 3.2.13)
activesupport (= 3.2.13)
activesupport (3.2.13)
i18n (= 0.6.1)
multi_json (~> 1.0)
acts_as_tree (1.2.0)
activerecord (>= 3.0.0)
@ -59,6 +59,14 @@ GEM
builder (3.0.4)
bullet (4.3.0)
uniform_notifier
capistrano (2.13.5)
highline
net-scp (>= 1.0.0)
net-sftp (>= 2.0.0)
net-ssh (>= 2.0.14)
net-ssh-gateway (>= 1.1.0)
capistrano-ext (1.2.1)
capistrano (>= 1.0.0)
chronic (0.9.0)
client_side_validations (3.1.4)
coderay (1.0.8)
@ -72,6 +80,7 @@ GEM
commonjs (0.2.6)
daemons (1.1.9)
erubis (2.7.0)
eventmachine (1.0.3)
exception_notification (2.6.1)
actionmailer (>= 3.0.4)
execjs (1.4.0)
@ -85,6 +94,7 @@ GEM
railties (>= 3.1, < 4.1)
has_scope (0.5.1)
hashery (2.0.1)
highline (1.6.19)
hike (1.2.1)
i18n (0.6.1)
inherited_resources (1.3.1)
@ -94,7 +104,7 @@ GEM
jquery-rails (2.1.3)
railties (>= 3.1.0, < 5.0)
thor (~> 0.14)
json (1.7.6)
json (1.7.7)
kaminari (0.14.1)
actionpack (>= 3.0.0)
activesupport (>= 3.0.0)
@ -104,18 +114,35 @@ GEM
actionpack (>= 3.1)
less (~> 2.2.0)
libv8 (3.3.10.4)
mail (2.4.4)
mail (2.5.3)
i18n (>= 0.4.0)
mime-types (~> 1.16)
treetop (~> 1.4.8)
mailcatcher (0.5.11)
activesupport (~> 3.0)
eventmachine (~> 1.0.0)
haml (>= 3.1, < 5)
mail (~> 2.3)
sinatra (~> 1.2)
skinny (~> 0.2.3)
sqlite3 (~> 1.3)
thin (~> 1.5.0)
meta_search (1.1.3)
actionpack (~> 3.1)
activerecord (~> 3.1)
activesupport (~> 3.1)
polyamorous (~> 0.5.0)
mime-types (1.19)
multi_json (1.5.0)
mime-types (1.21)
mono_logger (1.1.0)
multi_json (1.7.3)
mysql2 (0.3.11)
net-scp (1.1.1)
net-ssh (>= 2.6.5)
net-sftp (2.1.2)
net-ssh (>= 2.6.5)
net-ssh (2.6.7)
net-ssh-gateway (1.2.0)
net-ssh (>= 2.6.5)
pdf-reader (1.2.0)
Ascii85 (~> 1.0.0)
hashery (~> 2.0)
@ -126,43 +153,44 @@ GEM
prawn (0.12.0)
pdf-reader (>= 0.9.0)
ttfunk (~> 1.0.2)
rack (1.4.3)
quiet_assets (1.0.2)
railties (>= 3.1, < 5.0)
rack (1.4.5)
rack-cache (1.2)
rack (>= 0.4)
rack-protection (1.3.2)
rack-protection (1.5.0)
rack
rack-ssl (1.3.2)
rack-ssl (1.3.3)
rack
rack-test (0.6.2)
rack (>= 1.0)
rails (3.2.11)
actionmailer (= 3.2.11)
actionpack (= 3.2.11)
activerecord (= 3.2.11)
activeresource (= 3.2.11)
activesupport (= 3.2.11)
rails (3.2.13)
actionmailer (= 3.2.13)
actionpack (= 3.2.13)
activerecord (= 3.2.13)
activeresource (= 3.2.13)
activesupport (= 3.2.13)
bundler (~> 1.0)
railties (= 3.2.11)
rails3_acts_as_paranoid (0.2.4)
activerecord (~> 3.2)
railties (3.2.11)
actionpack (= 3.2.11)
activesupport (= 3.2.11)
railties (= 3.2.13)
railties (3.2.13)
actionpack (= 3.2.13)
activesupport (= 3.2.13)
rack-ssl (~> 1.3.2)
rake (>= 0.8.7)
rdoc (~> 3.4)
thor (>= 0.14.6, < 2.0)
rake (10.0.3)
rdoc (3.12)
rdoc (3.12.2)
json (~> 1.4)
redis (3.0.2)
redis-namespace (1.2.1)
redis (3.0.4)
redis-namespace (1.3.0)
redis (~> 3.0.0)
responders (0.9.3)
railties (~> 3.1)
resque (1.23.0)
resque (1.24.1)
mono_logger (~> 1.0)
multi_json (~> 1.0)
redis-namespace (~> 1.0)
redis-namespace (~> 1.2)
sinatra (>= 0.9.2)
vegas (~> 0.1.2)
ruby-prof (0.11.2)
@ -179,10 +207,13 @@ GEM
simple_form (2.0.3)
actionpack (~> 3.0)
activemodel (~> 3.0)
sinatra (1.3.3)
rack (~> 1.3, >= 1.3.6)
rack-protection (~> 1.2)
sinatra (1.3.6)
rack (~> 1.4)
rack-protection (~> 1.3)
tilt (~> 1.3, >= 1.3.3)
skinny (0.2.3)
eventmachine (~> 1.0.0)
thin (~> 1.5.0)
sprockets (2.2.2)
hike (~> 1.2)
multi_json (~> 1.0)
@ -192,8 +223,12 @@ GEM
test-unit (2.5.3)
therubyracer (0.10.2)
libv8 (~> 3.3.10)
thor (0.16.0)
tilt (1.3.3)
thin (1.5.1)
daemons (>= 1.0.9)
eventmachine (>= 0.12.6)
rack (>= 1.0.0)
thor (0.17.0)
tilt (1.4.1)
treetop (1.4.12)
polyglot
polyglot (>= 0.3.1)
@ -203,7 +238,7 @@ GEM
less-rails (~> 2.2.3)
railties (>= 3.1)
therubyracer (~> 0.10.2)
tzinfo (0.3.35)
tzinfo (0.3.37)
uglifier (1.3.0)
execjs (>= 0.3.0)
multi_json (~> 1.0, >= 1.0.2)
@ -227,6 +262,8 @@ DEPENDENCIES
better_errors
binding_of_caller
bullet
capistrano (= 2.13.5)
capistrano-ext
client_side_validations
coffee-rails (~> 3.2.1)
daemons
@ -236,11 +273,12 @@ DEPENDENCIES
jquery-rails
kaminari
localize_input!
mailcatcher
meta_search
mysql2
prawn
quiet_assets
rails (~> 3.2.9)
rails3_acts_as_paranoid (~> 0.2.0)
resque
ruby-prof
sass-rails (~> 3.2.3)
@ -250,6 +288,7 @@ DEPENDENCIES
sqlite3
test-unit
therubyracer
thin
twitter-bootstrap-rails
uglifier (>= 1.0.3)
whenever

View file

@ -1,4 +0,0 @@
MULTI_COOP_INSTALL
------------------
TODO ...

View file

@ -1,17 +1,22 @@
== FoodSoft
Important
--------
We changed the branch structure. The rails3 branch is now master. But you can safely send pull requests to rails3. It'll remain there for a couple of weeks.
FoodSoft
=========
Web-based software to manage a non-profit food coop (product catalog, ordering, accounting, job scheduling).
== Install
More information about using this software and contributing can be found on the [wiki](https://github.com/foodcoops/foodsoft/wiki).
Have a look on README_DEVEL.
Install
--------
Update, it is highly recommended to checkout the rails3 branch. As soon as possible I will merge this branch
into master. So for beginnners, better start with the new (I hope much easier) code.
Have a look at [DEVELOPMENT](https://github.com/foodcoops/foodsoft/blob/master/doc/DEVELOPMENT) (possibly outdated) and the (more recent) [Developing](https://github.com/foodcoops/foodsoft/wiki/Developing) page on the wiki.
git checkout -b rails3 origin/rails3
== License
License
-------
FoodSoft - a webbased foodcoop management software
Copyright (C) 2011 Benni and Lasse

View file

@ -35,11 +35,14 @@ $(function() {
// Check/Uncheck all checkboxes for a specific form
$('input[data-check-all]').live('click', function() {
var status = $(this).is(':checked')
$($(this).data('check-all')).find('input[type="checkbox"]').each(function() {
$(this).attr('checked', status);
highlightRow($(this));
});
var status = $(this).is(':checked');
var context = $(this).data('check-all');
var elms = $('input[type="checkbox"]', context);
for(i=elms.length-1; i>=0; --i) { // performance can be an issue here, so use native loop
var elm = elms[i];
elm.checked = status;
highlightRow($(elm));
}
});
// Submit form when changing a select menu.
@ -102,7 +105,7 @@ $(function() {
// gives the row an yellow background
function highlightRow(checkbox) {
var row = checkbox.parents('tr');
var row = checkbox.closest('tr');
if (checkbox.is(':checked')) {
row.addClass('selected');
} else {

View file

@ -49,7 +49,7 @@ function addData(orderArticleId, itemPrice, itemUnit, itemSubtotal, itemQuantity
function increaseQuantity(item) {
var value = Number($('#q_' + item).val()) + 1;
if (!isStockit || (value <= (quantityAvailable[item] - quantityOthers[item]))) {
if (!isStockit || (value <= (quantityAvailable[item] + itemsAllocated[item]))) {
update(item, value, $('#t_' + item).val());
}
}

View file

@ -200,3 +200,11 @@ tr.unavailable {
border-color: red;
}
}
// ********* Tweaks & fixes
// need more space for supplier&order information (in German, at least)
.dl-horizontal {
dt { width: 160px; }
dd { margin-left: 170px; }
}

View file

@ -3,7 +3,7 @@ class Admin::OrdergroupsController < Admin::BaseController
inherit_resources
def index
@ordergroups = Ordergroup.order('name ASC')
@ordergroups = Ordergroup.undeleted.order('name ASC')
# if somebody uses the search field:
unless params[:query].blank?
@ -15,9 +15,9 @@ class Admin::OrdergroupsController < Admin::BaseController
def destroy
@ordergroup = Ordergroup.find(params[:id])
@ordergroup.destroy
redirect_to admin_ordergroups_url, :notice => "Bestellgruppe wurde gelöscht"
@ordergroup.mark_as_deleted
redirect_to admin_ordergroups_url, notice: t('admin.ordergroups.destroy.notice')
rescue => error
redirect_to admin_ordergroups_url, :alert => "Bestellgruppe konnte nicht gelöscht werden: #{error}"
redirect_to admin_ordergroups_url, alert: t('admin.ordergroups.destroy.error')
end
end

View file

@ -13,8 +13,8 @@ class Admin::WorkgroupsController < Admin::BaseController
def destroy
@workgroup = Workgroup.find(params[:id])
@workgroup.destroy
redirect_to admin_workgroups_url, :notice => "Arbeitsgruppe wurde gelöscht"
redirect_to admin_workgroups_url, notice: t('admin.workgroups.destroy.notice')
rescue => error
redirect_to admin_workgroups_url, :alert => "Arbeitsgruppe konnte nicht gelöscht werden: #{error}"
redirect_to admin_workgroups_url, alert: t('admin.workgroups.destroy.error')
end
end

View file

@ -5,17 +5,17 @@ class ArticleCategoriesController < ApplicationController
before_filter :authenticate_article_meta
def create
create!(:notice => "Die Kategorie wurde gespeichert") { article_categories_path }
create!(:notice => I18n.t('article_categories.create.notice')) { article_categories_path }
end
def update
update!(:notice => "Die Kategorie wurde aktualisiert") { article_categories_path }
update!(:notice => I18n.t('article_categories.update.notice')) { article_categories_path }
end
def destroy
destroy!
rescue => error
redirect_to article_categories_path, alert: t('controller.article_categories.destroy.error', message: error.message)
redirect_to article_categories_path, alert: I18n.t('article_categories.destroy.error', message: error.message)
end
protected

View file

@ -20,7 +20,7 @@ class ArticlesController < ApplicationController
sort = "article_categories.name, articles.name"
end
@articles = Article.where(supplier_id: @supplier, :type => nil).includes(:article_category).order(sort)
@articles = Article.undeleted.where(supplier_id: @supplier, :type => nil).includes(:article_category).order(sort)
@articles = @articles.where('articles.name LIKE ?', "%#{params[:query]}%") unless params[:query].nil?
@articles = @articles.page(params[:page]).per(@per_page)
@ -64,22 +64,22 @@ class ArticlesController < ApplicationController
# Deletes article from database. send error msg, if article is used in a current order
def destroy
@article = Article.find(params[:id])
@article.destroy unless @order = @article.in_open_order # If article is in an active Order, the Order will be returned
@article.mark_as_deleted unless @order = @article.in_open_order # If article is in an active Order, the Order will be returned
render :layout => false
end
# Renders a form for editing all articles from a supplier
def edit_all
@articles = @supplier.articles
@articles = @supplier.articles.undeleted
end
# Updates all article of specific supplier
# deletes all articles from params[outlisted_articles]
def update_all
invalid_articles = false
begin
Article.transaction do
unless params[:articles].blank?
invalid_articles = false
# Update other article attributes...
@articles = Article.find(params[:articles].keys)
@articles.each do |article|
@ -88,52 +88,46 @@ class ArticlesController < ApplicationController
end
end
raise "Artikel sind fehlerhaft. Bitte überprüfe Deine Eingaben." if invalid_articles
end
# delete articles
if params[:outlisted_articles]
params[:outlisted_articles].keys.each {|id| Article.find(id).destroy }
raise ActiveRecord::Rollback if invalid_articles # Rollback all changes
end
end
# Successfully done.
redirect_to supplier_articles_path(@supplier), notice: "Alle Artikel und Preise wurden aktalisiert"
end
rescue => e
if invalid_articles
# An error has occurred, transaction has been rolled back.
if params[:sync]
flash[:error] = "Es trat ein Fehler beim Aktualisieren des Artikels '#{current_article.name}' auf: #{e.message}"
redirect_to(supplier_articles_path(@supplier))
else
flash.now.alert = e.message
render :edit_all
end
flash.now.alert = I18n.t('articles.controller.error_invalid')
render :edit_all
else
# Successfully done.
redirect_to supplier_articles_path(@supplier), notice: I18n.t('articles.controller.update_all.notice')
end
end
# makes different actions on selected articles
def update_selected
raise 'Du hast keine Artikel ausgewählt' if params[:selected_articles].nil?
raise I18n.t('articles.controller.error_nosel') if params[:selected_articles].nil?
articles = Article.find(params[:selected_articles])
case params[:selected_action]
when 'destroy'
articles.each {|a| a.destroy }
flash[:notice] = 'Alle gewählten Artikel wurden gelöscht'
when 'setNotAvailable'
articles.each {|a| a.update_attribute(:availability, false) }
flash[:notice] = 'Alle gewählten Artikel wurden auf "nicht verfügbar" gesetzt'
when 'setAvailable'
articles.each {|a| a.update_attribute(:availability, true) }
flash[:notice] = 'Alle gewählten Artikel wurden auf "verfügbar" gesetzt'
else
flash[:alert] = 'Keine Aktion ausgewählt!'
Article.transaction do
case params[:selected_action]
when 'destroy'
articles.each(&:mark_as_deleted)
flash[:notice] = I18n.t('articles.controller.update_sel.notice_destroy')
when 'setNotAvailable'
articles.each {|a| a.update_attribute(:availability, false) }
flash[:notice] = I18n.t('articles.controller.update_sel.notice_unavail')
when 'setAvailable'
articles.each {|a| a.update_attribute(:availability, true) }
flash[:notice] = I18n.t('articles.controller.update_sel.notice_avail')
else
flash[:alert] = I18n.t('articles.controller.update_sel.notice_noaction')
end
end
# action succeded
redirect_to supplier_articles_url(@supplier, :per_page => params[:per_page])
rescue => error
redirect_to supplier_articles_url(@supplier, :per_page => params[:per_page]),
:alert => "Ein Fehler ist aufgetreten: #{error}"
:alert => I18n.t('errors.general_msg', :msg => error)
end
# lets start with parsing articles from uploaded file, yeah
@ -166,13 +160,13 @@ class ArticlesController < ApplicationController
:tax => row[:tax])
# stop parsing, when an article isn't valid
unless article.valid?
raise article.errors.full_messages.join(", ") + " ..in line " + (articles.index(row) + 2).to_s
raise I18n.t('articles.controller.error_parse', :msg => article.errors.full_messages.join(", "), :line => (articles.index(row) + 2).to_s)
end
@articles << article
end
flash.now[:notice] = "#{@articles.size} articles are parsed successfully."
flash.now[:notice] = I18n.t('articles.controller.parse_upload.notice', :count => @articles.size)
rescue => error
redirect_to upload_supplier_articles_path(@supplier), :alert => "An error has occurred: #{error.message}"
redirect_to upload_supplier_articles_path(@supplier), :alert => I18n.t('errors.general_msg', :msg => error.message)
end
end
@ -187,14 +181,14 @@ class ArticlesController < ApplicationController
invalid_articles = true unless article.save
end
raise "Artikel sind fehlerhaft" if invalid_articles
raise I18n.t('articles.controller.error_invalid') if invalid_articles
end
# Successfully done.
redirect_to supplier_articles_path(@supplier), notice: "Es wurden #{@articles.size} neue Artikel gespeichert."
redirect_to supplier_articles_path(@supplier), notice: I18n.t('articles.controller.create_from_upload.notice', :count => @articles.size)
rescue => error
# An error has occurred, transaction has been rolled back.
flash.now[:error] = "An error occured: #{error.message}"
flash.now[:error] = I18n.t('errors.general_msg', :msg => error.message)
render :parse_upload
end
end
@ -221,14 +215,43 @@ class ArticlesController < ApplicationController
def sync
# check if there is an shared_supplier
unless @supplier.shared_supplier
redirect_to supplier_articles_url(@supplier), :alert => "#{@supplier.name} ist nicht mit einer externen Datenbank verknüpft."
redirect_to supplier_articles_url(@supplier), :alert => I18n.t('articles.controller.sync.shared_alert', :supplier => @supplier.name)
end
# sync articles against external database
@updated_articles, @outlisted_articles = @supplier.sync_all
# convert to db-compatible-string
@updated_articles.each {|a, b| a.shared_updated_on = a.shared_updated_on.to_formatted_s(:db)}
if @updated_articles.empty? && @outlisted_articles.empty?
redirect_to supplier_articles_path(@supplier), :notice => "Der Katalog ist aktuell."
redirect_to supplier_articles_path(@supplier), :notice => I18n.t('articles.controller.sync.notice')
end
end
# Updates, deletes articles when sync form is submitted
def update_synchronized
begin
Article.transaction do
# delete articles
if params[:outlisted_articles]
Article.find(params[:outlisted_articles].keys).each(&:mark_as_deleted)
end
# Update articles
params[:articles].each do |id, attrs|
Article.find(id).update_attributes! attrs
end
end
# Successfully done.
redirect_to supplier_articles_path(@supplier), notice: I18n.t('articles.controller.update_sync.notice')
rescue ActiveRecord::RecordInvalid => invalid
# An error has occurred, transaction has been rolled back.
redirect_to supplier_articles_path(@supplier),
alert: I18n.t('articles.controller.error_update', :article => invalid.record.name, :msg => invalid.record.errors.full_messages)
rescue => error
redirect_to supplier_articles_path(@supplier),
alert: I18n.t('errors.general_msg', :msg => error.message)
end
end
end

View file

@ -35,7 +35,7 @@ class DeliveriesController < ApplicationController
respond_to do |format|
if @delivery.save
flash[:notice] = 'Lieferung wurde erstellt. Bitte nicht vergessen die Rechnung anzulegen!'
flash[:notice] = I18n.t('deliveries.create.notice')
format.html { redirect_to([@supplier,@delivery]) }
format.xml { render :xml => @delivery, :status => :created, :location => @delivery }
else
@ -54,7 +54,7 @@ class DeliveriesController < ApplicationController
respond_to do |format|
if @delivery.update_attributes(params[:delivery])
flash[:notice] = 'Lieferung wurde aktualisiert.'
flash[:notice] = I18n.t('deliveries.update.notice')
format.html { redirect_to([@supplier,@delivery]) }
format.xml { head :ok }
else
@ -68,7 +68,7 @@ class DeliveriesController < ApplicationController
@delivery = Delivery.find(params[:id])
@delivery.destroy
flash[:notice] = "Lieferung wurde gelöscht."
flash[:notice] = I18n.t('deliveries.destroy.notice')
respond_to do |format|
format.html { redirect_to(supplier_deliveries_url(@supplier)) }
format.xml { head :ok }

View file

@ -6,7 +6,7 @@ class FeedbackController < ApplicationController
def create
if params[:message].present?
Mailer.feedback(current_user, params[:message]).deliver
redirect_to root_url, :notice => "Das Feedback wurde erfolgreich verschickt. Vielen Dank!"
redirect_to root_url, notice: t('feedback.create.notice')
else
render :action => 'new'
end

View file

@ -7,10 +7,10 @@ class Finance::BalancingController < Finance::BaseController
def new
@order = Order.find(params[:order_id])
flash.now.alert = "Achtung, Bestellung wurde schon abgerechnet" if @order.closed?
flash.now.alert = t('finance.balancing.new.alert') if @order.closed?
@comments = @order.comments
@articles = @order.order_articles.ordered.includes(:order, :article_price,
@articles = @order.order_articles.ordered.includes(:article, :article_price,
group_order_articles: {group_order: :ordergroup})
sort_param = params['sort'] || 'name'
@ -30,6 +30,10 @@ class Finance::BalancingController < Finance::BaseController
render layout: false if request.xhr?
end
def update_summary
@order = Order.find(params[:id])
end
def edit_note
@order = Order.find(params[:id])
render :layout => false
@ -53,19 +57,19 @@ class Finance::BalancingController < Finance::BaseController
def close
@order = Order.find(params[:id])
@order.close!(@current_user)
redirect_to finance_root_url, notice: "Bestellung wurde erfolgreich abgerechnet, die Kontostände aktualisiert."
redirect_to finance_order_index_url, notice: t('finance.balancing.close.notice')
rescue => error
redirect_to new_finance_order_url(order_id: @order.id), alert: "Ein Fehler ist beim Abrechnen aufgetreten: #{error.message}"
redirect_to new_finance_order_url(order_id: @order.id), alert: t('finance.balancing.close.alert', message: error.message)
end
# Close the order directly, without automaticly updating ordergroups account balances
def close_direct
@order = Order.find(params[:id])
@order.close_direct!(@current_user)
redirect_to finance_balancing_url, notice: "Bestellung wurde geschlossen."
redirect_to finance_order_index_url, notice: t('finance.balancing.close_direct.notice')
rescue => error
redirect_to finance_balancing_url, alert: "Bestellung kann nicht geschlossen werden: #{error.message}"
redirect_to finance_order_index_url, alert: t('finance.balancing.close_direct.alert', message: error.message)
end
end

View file

@ -34,7 +34,7 @@ class Finance::FinancialTransactionsController < ApplicationController
@financial_transaction = FinancialTransaction.new(params[:financial_transaction])
@financial_transaction.user = current_user
@financial_transaction.add_transaction!
redirect_to finance_ordergroup_transactions_url(@ordergroup), :notice => "Die Transaktion wurde gespeichert."
redirect_to finance_ordergroup_transactions_url(@ordergroup), notice: t('finance.financial_transactions.create.notice')
rescue ActiveRecord::RecordInvalid => error
flash.now[:alert] = error.message
render :action => :new
@ -51,9 +51,9 @@ class Finance::FinancialTransactionsController < ApplicationController
Ordergroup.find(trans[:ordergroup_id]).add_financial_transaction!(trans[:amount], params[:note], @current_user)
end
end
redirect_to finance_ordergroups_url, notice: "Alle Transaktionen wurden gespeichert."
redirect_to finance_ordergroups_url, notice: t('finance.create_collection.create.notice')
rescue => error
redirect_to finance_new_transaction_collection_url, alert: "Ein Fehler ist aufgetreten: " + error.to_s
redirect_to finance_new_transaction_collection_url, alert: t('finance.create_collection.create.alert', error: error.to_s)
end
protected

View file

@ -22,7 +22,7 @@ class Finance::InvoicesController < ApplicationController
@invoice = Invoice.new(params[:invoice])
if @invoice.save
flash[:notice] = "Rechnung wurde erstellt."
flash[:notice] = I18n.t('finance.create.notice')
if @invoice.order
# Redirect to balancing page
redirect_to new_finance_order_url(order_id: @invoice.order.id)
@ -38,7 +38,7 @@ class Finance::InvoicesController < ApplicationController
@invoice = Invoice.find(params[:id])
if @invoice.update_attributes(params[:invoice])
redirect_to [:finance, @invoice], notice: "Rechnung wurde aktualisiert."
redirect_to [:finance, @invoice], notice: I18n.t('finance.update.notice')
else
render :edit
end

View file

@ -26,7 +26,7 @@ class Finance::OrderArticlesController < ApplicationController
@order = Order.find(params[:order_id])
@order_article = OrderArticle.find(params[:id])
begin
@order_article.update_article_and_price!(params[:article], params[:article_price], params[:order_article])
@order_article.update_article_and_price!(params[:order_article], params[:article], params[:article_price])
rescue
render action: :edit
end

View file

@ -12,7 +12,7 @@ class Finance::OrdergroupsController < Finance::BaseController
sort = "name"
end
@ordergroups = Ordergroup.order(sort)
@ordergroups = Ordergroup.undeleted.order(sort)
@ordergroups = @ordergroups.where('name LIKE ?', "%#{params[:query]}%") unless params[:query].nil?
@ordergroups = @ordergroups.page(params[:page]).per(@per_page)

View file

@ -1,7 +1,7 @@
class Foodcoop::OrdergroupsController < ApplicationController
def index
@ordergroups = Ordergroup.order('name DESC')
@ordergroups = Ordergroup.undeleted.order('name DESC')
unless params[:name].blank? # Search by name
@ordergroups = @ordergroups.where('name LIKE ?', "%#{params[:name]}%")

View file

@ -14,7 +14,7 @@ class Foodcoop::WorkgroupsController < ApplicationController
def update
@workgroup = Workgroup.find(params[:id])
if @workgroup.update_attributes(params[:workgroup])
redirect_to foodcoop_workgroups_url, :notice => "Arbeitsgruppe wurde aktualisiert"
redirect_to foodcoop_workgroups_url, :notice => I18n.t('workgroups.update.notice')
else
render :action => 'edit'
end

View file

@ -20,12 +20,12 @@ class GroupOrdersController < ApplicationController
@group_order = GroupOrder.new(params[:group_order])
begin
@group_order.save_ordering!
redirect_to group_order_url(@group_order), :notice => 'Die Bestellung wurde gespeichert.'
redirect_to group_order_url(@group_order), :notice => I18n.t('group_orders.create.notice')
rescue ActiveRecord::StaleObjectError
redirect_to group_orders_url, :alert => 'In der Zwischenzeit hat jemand anderes auch bestellt, daher konnte die Bestellung nicht aktualisiert werden.'
redirect_to group_orders_url, :alert => I18n.t('group_orders.create.error_stale')
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.'
redirect_to group_orders_url, :alert => I18n.t('group_orders.create.error_general')
end
end
@ -41,12 +41,12 @@ class GroupOrdersController < ApplicationController
@group_order.attributes = params[:group_order]
begin
@group_order.save_ordering!
redirect_to group_order_url(@group_order), :notice => 'Die Bestellung wurde gespeichert.'
redirect_to group_order_url(@group_order), :notice => I18n.t('group_orders.update.notice')
rescue ActiveRecord::StaleObjectError
redirect_to group_orders_url, :alert => 'In der Zwischenzeit hat jemand anderes auch bestellt, daher konnte die Bestellung nicht aktualisiert werden.'
redirect_to group_orders_url, :alert => I18n.t('group_orders.update.error_stale')
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.'
redirect_to group_orders_url, :alert => I18n.t('group_orders.update.error_general')
end
end
@ -69,7 +69,7 @@ class GroupOrdersController < ApplicationController
def ensure_ordergroup_member
@ordergroup = @current_user.ordergroup
if @ordergroup.nil?
redirect_to root_url, :alert => "Du bist kein Mitglieder einer Bestellgruppe."
redirect_to root_url, :alert => I18n.t('group_orders.errors.no_member')
end
end
@ -77,7 +77,7 @@ class GroupOrdersController < ApplicationController
@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.'
flash[:notice] = I18n.t('group_orders.error_closed')
redirect_to :action => 'index'
end
end
@ -85,7 +85,7 @@ class GroupOrdersController < ApplicationController
def ensure_my_group_order
@group_order = @ordergroup.group_orders.find(params[:id])
rescue ActiveRecord::RecordNotFound
redirect_to group_orders_url, alert: 'Fehlerhafte URL, das ist nicht Deine Bestellung.'
redirect_to group_orders_url, alert: I18n.t('group_orders.errors.notfound')
end
def enough_apples?

View file

@ -16,7 +16,7 @@ class HomeController < ApplicationController
def update_profile
if @current_user.update_attributes(params[:user])
redirect_to my_profile_url, notice: 'Änderungen wurden gespeichert.'
redirect_to my_profile_url, notice: I18n.t('home.changes_saved')
else
render :profile
end
@ -45,7 +45,7 @@ class HomeController < ApplicationController
@financial_transactions = @financial_transactions.where("note LIKE ?", "%#{params[:query]}%") if params[:query].present?
else
redirect_to root_path, :alert => "Leider bist Du kein Mitglied einer Bestellgruppe"
redirect_to root_path, :alert => I18n.t('home.no_ordergroups')
end
end
@ -54,9 +54,9 @@ class HomeController < ApplicationController
membership = Membership.find(params[:membership_id])
if membership.user == current_user
membership.destroy
flash[:notice] = "Du bist jetzt kein Mitglied der Gruppe #{membership.group.name} mehr."
flash[:notice] = I18n.t('home.ordergroup_cancelled', :group => membership.group.name)
else
flash[:error] = "Ein Problem ist aufgetreten."
flash[:error] = I18n.t('errors.general')
end
redirect_to my_profile_path
end

View file

@ -1,7 +1,7 @@
class InvitesController < ApplicationController
before_filter :authenticate_membership_or_admin, :only => [:new]
#TODO: auhtorize also for create action.
#TODO: authorize also for create action.
def new
@invite = Invite.new(:user => @current_user, :group => @group)
@ -14,7 +14,7 @@ class InvitesController < ApplicationController
respond_to do |format|
format.html do
redirect_to back_or_default_path, notice: "Benutzerin wurde erfolgreich eingeladen."
redirect_to back_or_default_path, notice: I18n.t('invites.success')
end
format.js { render layout: false }
end

View file

@ -10,6 +10,10 @@ class LoginController < ApplicationController
# Sends an email to a user with the token that allows setting a new password through action "password".
def reset_password
if request.get? || params[:user].nil? # Catch for get request and give better error message.
redirect_to forgot_password_url, alert: 'Ein Problem ist aufgetreten. Bitte erneut versuchen' and return
end
if (user = User.find_by_email(params[:user][:email]))
user.reset_password_token = user.new_random_password(16)
user.reset_password_expires = Time.now.advance(:days => 2)
@ -18,7 +22,7 @@ class LoginController < ApplicationController
logger.debug("Sent password reset email to #{user.email}.")
end
end
redirect_to login_url, :notice => "Wenn Deine E-Mail hier registiert ist bekommst Du jetzt eine Nachricht mit einem Passwort-Zurücksetzen-Link."
redirect_to login_url, :notice => I18n.t('login.controller.reset_password.notice')
end
# Set a new password with a token from the password reminder email.
@ -34,7 +38,7 @@ class LoginController < ApplicationController
@user.reset_password_token = nil
@user.reset_password_expires = nil
@user.save
redirect_to login_url, :notice => "Dein Passwort wurde aktualisiert. Du kannst Dich jetzt anmelden."
redirect_to login_url, :notice => I18n.t('login.controller.update_password.notice')
else
render :new_password
end
@ -43,27 +47,23 @@ class LoginController < ApplicationController
# For invited users.
def accept_invitation
@invite = Invite.find_by_token(params[:token])
if (@invite.nil? || @invite.expires_at < Time.now)
flash[:error] = "Deine Einladung ist nicht (mehr) gültig."
render :action => 'login'
if @invite.nil? || @invite.expires_at < Time.now
redirect_to login_url, alert: I18n.t('login.controller.error_invite_invalid')
elsif @invite.group.nil?
flash[:error] = "Die Gruppe, in die Du eingeladen wurdest, existiert leider nicht mehr."
render :action => 'login'
elsif (request.post?)
redirect_to login_url, alert: I18n.t('login.controller.error_group_invalid')
elsif request.post?
User.transaction do
@user = User.new(params[:user])
@user.email = @invite.email
if @user.save
Membership.new(:user => @user, :group => @invite.group).save!
@invite.destroy
redirect_to login_url, notice: "Herzlichen Glückwunsch, Dein Account wurde erstellt. Du kannst Dich nun einloggen."
redirect_to login_url, notice: I18n.t('login.controller.accept_invitation.notice')
end
end
else
@user = User.new(:email => @invite.email)
end
rescue
flash[:error] = "Ein Fehler ist aufgetreten. Bitte erneut versuchen."
end
protected
@ -71,8 +71,7 @@ class LoginController < ApplicationController
def validate_token
@user = User.find_by_id_and_reset_password_token(params[:id], params[:token])
if (@user.nil? || @user.reset_password_expires < Time.now)
flash.now.error = "Ungültiger oder abgelaufener Token. Bitte versuch es erneut."
render :action => 'forgot_password'
redirect_to forgot_password_url, alert: I18n.t('login.controller.error_token_invalid')
end
end
end

View file

@ -8,6 +8,9 @@ class MessagesController < ApplicationController
# Creates a new message object.
def new
@message = Message.new(params[:message])
if @message.reply_to and not @message.reply_to.is_readable_for?(current_user)
redirect_to new_message_url, alert: 'Nachricht ist privat!'
end
end
# Creates a new message.
@ -15,7 +18,7 @@ class MessagesController < ApplicationController
@message = @current_user.send_messages.new(params[:message])
if @message.save
Resque.enqueue(UserNotifier, FoodsoftConfig.scope, 'message_deliver', @message.id)
redirect_to messages_url, :notice => "Nachricht ist gespeichert und wird versendet."
redirect_to messages_url, :notice => I18n.t('messages.create.notice')
else
render :action => 'new'
end
@ -24,5 +27,8 @@ class MessagesController < ApplicationController
# Shows a single message.
def show
@message = Message.find(params[:id])
unless @message.is_readable_for?(current_user)
redirect_to messages_url, alert: 'Nachricht ist privat!'
end
end
end

View file

@ -62,7 +62,7 @@ class OrdersController < ApplicationController
@order = Order.new(params[:order])
@order.created_by = current_user
if @order.save
flash[:notice] = "Die Bestellung wurde erstellt."
flash[:notice] = I18n.t('orders.create.notice')
redirect_to @order
else
logger.debug "[debug] order errors: #{@order.errors.messages}"
@ -80,7 +80,7 @@ class OrdersController < ApplicationController
def update
@order = Order.find params[:id]
if @order.update_attributes params[:order]
flash[:notice] = "Die Bestellung wurde aktualisiert."
flash[:notice] = I18n.t('orders.update.notice')
redirect_to :action => 'show', :id => @order
else
render :action => 'edit'
@ -97,7 +97,7 @@ class OrdersController < ApplicationController
def finish
order = Order.find(params[:id])
order.finish!(@current_user)
redirect_to order, notice: "Die Bestellung wurde beendet."
redirect_to order, notice: I18n.t('orders.finish.notice')
end
# Renders the fax-text-file
@ -106,14 +106,14 @@ class OrdersController < ApplicationController
order = Order.find(params[:id])
supplier = order.supplier
contact = FoodsoftConfig[:contact].symbolize_keys
text = "Bestellung für" + " #{FoodsoftConfig[: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 += "****** " + "Versandadresse" + "\n\n"
text = I18n.t('orders.fax.heading', :name => FoodsoftConfig[:name])
text += "\n" + I18n.t('orders.fax.customer_number') + ': #{supplier.customer_number}' unless supplier.customer_number.blank?
text += "\n" + I18n.t('orders.fax.delivery_day')
text += "\n\n#{supplier.name}\n#{supplier.address}\n" + I18n.t('simple_form.labels.supplier.fax') + ": #{supplier.fax}\n\n"
text += "****** " + I18n.t('orders.fax.to_address') + "\n\n"
text += "#{FoodsoftConfig[:name]}\n#{contact[:street]}\n#{contact[:zip_code]} #{contact[:city]}\n\n"
text += "****** " + "Artikel" + "\n\n"
text += "Nummer" + " " + "Menge" + " " + "Name" + "\n"
text += "****** " + I18n.t('orders.fax.articles') + "\n\n"
text += I18n.t('orders.fax.number') + " " + I18n.t('orders.fax.amount') + " " + I18n.t('orders.fax.name') + "\n"
# now display all ordered articles
order.order_articles.ordered.all(:include => [:article, :article_price]).each do |oa|
number = oa.article.order_number

View file

@ -17,7 +17,7 @@ class PagesController < ApplicationController
elsif params[:id]
page = Page.find_by_id(params[:id])
if page.nil?
flash[:error] = "Seite existiert nicht!"
flash[:error] = I18n.t('pages.cshow.error_noexist')
redirect_to all_pages_path and return
else
redirect_to wiki_page_path(page.permalink) and return
@ -29,7 +29,7 @@ class PagesController < ApplicationController
elsif @page.redirect?
page = Page.find_by_id(@page.redirect)
unless page.nil?
flash[:notice] = "Weitergeleitet von #{@page.title} ..."
flash[:notice] = I18n.t('pages.cshow.redirect_notice', :page => @page.title)
redirect_to wiki_page_path(page.permalink)
end
end
@ -57,7 +57,7 @@ class PagesController < ApplicationController
render :action => 'new'
else
if @page.save
flash[:notice] = 'Seite wurde angelegt.'
flash[:notice] = I18n.t('pages.create.notice')
redirect_to(wiki_page_path(@page.permalink))
else
render :action => "new"
@ -76,7 +76,7 @@ class PagesController < ApplicationController
if @page.save
@page.parent_id = parent_id if (!params[:parent_id].blank? \
and params[:parent_id] != @page_id)
flash[:notice] = 'Seite wurde aktualisiert.'
flash[:notice] = I18n.t('pages.update.notice')
redirect_to wiki_page_path(@page.permalink)
else
render :action => "edit"
@ -84,7 +84,7 @@ class PagesController < ApplicationController
end
rescue ActiveRecord::StaleObjectError
flash[:error] = "Achtung, die Seite wurde gerade von jemand anderes bearbeitet. Bitte versuche es erneut."
flash[:error] = I18n.t('pages.error_stale_object')
redirect_to wiki_page_path(@page.permalink)
end
@ -92,7 +92,7 @@ class PagesController < ApplicationController
@page = Page.find(params[:id])
@page.destroy
flash[:notice] = "Die Seite '#{@page.title}' und alle Unterseiten wurden erfolgreich gelöscht."
flash[:notice] = I18n.t('pages.destroy.notice', :page => @page.title)
redirect_to wiki_path
end

View file

@ -17,15 +17,15 @@ class SessionsController < ApplicationController
else
redirect_to_url = root_url
end
redirect_to redirect_to_url, :notice => "Logged in!"
redirect_to redirect_to_url, :notice => I18n.t('sessions.logged_in')
else
flash.now.alert = "Invalid email or password"
flash.now.alert = I18n.t('sessions.login_invalid')
render "new"
end
end
def destroy
session[:user_id] = nil
redirect_to login_url, :notice => "Logged out!"
redirect_to login_url, :notice => I18n.t('sessions.logged_out')
end
end

View file

@ -7,15 +7,15 @@ class StockTakingsController < ApplicationController
def new
@stock_taking = StockTaking.new
StockArticle.all.each { |a| @stock_taking.stock_changes.build(:stock_article => a) }
StockArticle.undeleted.each { |a| @stock_taking.stock_changes.build(:stock_article => a) }
end
def create
create!(:notice => "Inventur wurde erfolgreich angelegt.")
create!(:notice => I18n.t('stock_takings.create.notice'))
end
def update
update!(:notice => "Inventur wurde aktualisiert.")
update!(:notice => I18n.t('stock_takings.update.notice'))
end
def fill_new_stock_article_form

View file

@ -1,7 +1,7 @@
class StockitController < ApplicationController
def index
@stock_articles = StockArticle.includes(:supplier, :article_category).
@stock_articles = StockArticle.undeleted.includes(:supplier, :article_category).
order('suppliers.name, article_categories.name, articles.name')
end
@ -12,7 +12,7 @@ class StockitController < ApplicationController
def create
@stock_article = StockArticle.new(params[:stock_article])
if @stock_article.save
redirect_to stock_articles_path, :notice => "Lagerartikel wurde gespeichert."
redirect_to stock_articles_path, :notice => I18n.t('stockit.stock_create.notice')
else
render :action => 'new'
end
@ -25,7 +25,7 @@ class StockitController < ApplicationController
def update
@stock_article = StockArticle.find(params[:id])
if @stock_article.update_attributes(params[:stock_article])
redirect_to stock_articles_path, :notice => "Lagerartikel wurde gespeichert."
redirect_to stock_articles_path, :notice => I18n.t('stockit.stock_update.notice')
else
render :action => 'edit'
end
@ -33,11 +33,11 @@ class StockitController < ApplicationController
def destroy
@article = StockArticle.find(params[:id])
@article.destroy
@article.mark_as_deleted
render :layout => false
rescue => error
render :partial => "destroy_fail", :layout => false,
:locals => { :fail_msg => "Ein Fehler ist aufgetreten: " + error.message }
:locals => { :fail_msg => I18n.t('errors.general_msg', :msg => error.message) }
end
#TODO: Fix this!!

View file

@ -4,7 +4,7 @@ class SuppliersController < ApplicationController
helper :deliveries
def index
@suppliers = Supplier.order(:name)
@suppliers = Supplier.undeleted.order(:name)
@deliveries = Delivery.recent
end
@ -18,7 +18,7 @@ class SuppliersController < ApplicationController
def new
if params[:shared_supplier_id]
shared_supplier = SharedSupplier.find(params[:shared_supplier_id])
@supplier = shared_supplier.build_supplier(shared_supplier.attributes)
@supplier = shared_supplier.build_supplier(shared_supplier.autofill_attributes)
else
@supplier = Supplier.new
end
@ -27,7 +27,7 @@ class SuppliersController < ApplicationController
def create
@supplier = Supplier.new(params[:supplier])
if @supplier.save
flash[:notice] = "Lieferant wurde erstellt"
flash[:notice] = I18n.t('suppliers.create.notice')
redirect_to suppliers_path
else
render :action => 'new'
@ -41,7 +41,7 @@ class SuppliersController < ApplicationController
def update
@supplier = Supplier.find(params[:id])
if @supplier.update_attributes(params[:supplier])
flash[:notice] = 'Lieferant wurde aktualisiert'
flash[:notice] = I18n.t('suppliers.update.notice')
redirect_to @supplier
else
render :action => 'edit'
@ -50,11 +50,11 @@ class SuppliersController < ApplicationController
def destroy
@supplier = Supplier.find(params[:id])
@supplier.destroy
flash[:notice] = "Lieferant wurde gelöscht"
@supplier.mark_as_deleted
flash[:notice] = I18n.t('suppliers.destroy.notice')
redirect_to suppliers_path
rescue => e
flash[:error] = "Ein Fehler ist aufgetreten: " + e.message
flash[:error] = I18n.t('errors.general_msg', :msg => e.message)
redirect_to @supplier
end

View file

@ -19,7 +19,7 @@ class TasksController < ApplicationController
def create
@task = Task.new(params[:task])
if @task.save
redirect_to tasks_url, :notice => "Aufgabe wurde erstellt"
redirect_to tasks_url, :notice => I18n.t('tasks.create.notice')
else
render :template => "tasks/new"
end
@ -38,7 +38,7 @@ class TasksController < ApplicationController
@task = Task.find(params[:id])
@task.attributes=(params[:task])
if @task.errors.empty? && @task.save
flash[:notice] = "Aufgabe wurde aktualisiert"
flash[:notice] = I18n.t('tasks.update.notice')
if @task.workgroup
redirect_to workgroup_tasks_url(workgroup_id: @task.workgroup_id)
else
@ -56,7 +56,7 @@ class TasksController < ApplicationController
task.destroy
task.update_ordergroup_stats(user_ids)
redirect_to tasks_url, :notice => "Aufgabe wurde gelöscht"
redirect_to tasks_url, :notice => I18n.t('tasks.destroy.notice')
end
# assign current_user to the task and set the assignment to "accepted"
@ -68,7 +68,7 @@ class TasksController < ApplicationController
else
task.assignments.create(:user => current_user, :accepted => true)
end
redirect_to user_tasks_path, :notice => "Du hast die Aufgabe übernommen"
redirect_to user_tasks_path, :notice => I18n.t('tasks.accept.notice')
end
# deletes assignment between current_user and given task
@ -79,7 +79,7 @@ class TasksController < ApplicationController
def set_done
Task.find(params[:id]).update_attribute :done, true
redirect_to tasks_url, :notice => "Aufgabenstatus wurde aktualisiert"
redirect_to tasks_url, :notice => I18n.t('tasks.set_done.notice')
end
# Shows all tasks, which are already done
@ -91,7 +91,7 @@ class TasksController < ApplicationController
def workgroup
@group = Group.find(params[:workgroup_id])
if @group.is_a? Ordergroup
redirect_to tasks_url, :alert => "Keine Arbeitsgruppe gefunden"
redirect_to tasks_url, :alert => I18n.t('tasks.error_not_found')
end
end
end

View file

@ -2,11 +2,12 @@
class OrderByArticles < OrderPdf
def filename
"Bestellung #{@order.name}-#{@order.ends.to_date} - Artikelsortierung.pdf"
I18n.t('documents.order_by_articles.filename', :name => @order.name, :date => @order.ends.to_date) + '.pdf'
end
def title
"Artikelsortierung der Bestellung: #{@order.name}, beendet am #{@order.ends.strftime('%d.%m.%Y')}"
I18n.t('documents.order_by_articles.title', :name => @order.name,
:date => @order.ends.strftime(I18n.t('date.formats.default')))
end
def body
@ -14,7 +15,7 @@ class OrderByArticles < OrderPdf
text "#{order_article.article.name} (#{order_article.article.unit} | #{order_article.price.unit_quantity.to_s} | #{number_with_precision(order_article.price.fc_price, precision: 2)})",
style: :bold, size: 10
rows = []
rows << %w(Bestellgruppe Menge Preis)
rows << I18n.t('documents.order_by_articles.rows')
for goa in order_article.group_order_articles
rows << [goa.group_order.ordergroup.name,
goa.result,

View file

@ -2,11 +2,12 @@
class OrderByGroups < OrderPdf
def filename
"Bestellung #{@order.name}-#{@order.ends.to_date} - Gruppensortierung.pdf"
I18n.t('documents.order_by_groups.filename', :name => @order.name, :date => @order.ends.to_date) + '.pdf'
end
def title
"Gruppensortierung der Bestellung: #{@order.name}, beendet am #{@order.ends.strftime('%d.%m.%Y')}"
I18n.t('documents.order_by_groups.title', :name => @order.name,
:date => @order.ends.strftime(I18n.t('date.formats.default')))
end
def body
@ -16,7 +17,7 @@ class OrderByGroups < OrderPdf
total = 0
rows = []
rows << %w(Artikel Menge Preis GebGr Einheit Summe) # Table Header
rows << I18n.t('documents.order_by_groups.rows') # Table Header
group_order_articles = group_order.group_order_articles.ordered
group_order_articles.each do |goa|
@ -30,7 +31,7 @@ class OrderByGroups < OrderPdf
goa.order_article.article.unit,
number_with_precision(sub_total, precision: 2)]
end
rows << [ "Summe", nil, nil, nil, nil, number_with_precision(total, precision: 2)]
rows << [ I18n.t('documents.order_by_groups.sum'), nil, nil, nil, nil, number_with_precision(total, precision: 2)]
table rows, column_widths: [250,50,50,50,50,50], cell_style: {size: 8, overflow: :shrink_to_fit} do |table|
# borders

View file

@ -2,7 +2,7 @@
class OrderFax < OrderPdf
def filename
"Bestellung #{@order.name}-#{@order.ends.to_date} - Fax.pdf"
I18n.t('documents.order_fax.filename', :name => @order.name, :date => @order.ends.to_date) + '.pdf'
end
def title
@ -14,42 +14,40 @@ class OrderFax < OrderPdf
# From paragraph
bounding_box [margin_box.right-200,margin_box.top], width: 200 do
text FoodsoftConfig[:name], align: :right
text FoodsoftConfig[:name], size: 9, align: :right
move_down 5
text contact[:street], align: :right
text contact[:street], size: 9, align: :right
move_down 5
text "#{contact[:zip_code]} #{contact[:city]}", align: :right
text "#{contact[:zip_code]} #{contact[:city]}", size: 9, align: :right
move_down 5
if @order.supplier.customer_number != ''
text "Kundennummer: #{@order.supplier.customer_number}", align: :right
end
move_down 10
text contact[:phone], size: 9, align: :right
text "#{I18n.t('simple_form.labels.supplier.customer_number')}: #{@order.supplier.try(:customer_number)}", size: 9, align: :right
move_down 5
text contact[:email], size: 9, align: :right
text "#{I18n.t('simple_form.labels.supplier.phone')}: #{contact[:phone]}", size: 9, align: :right
move_down 5
text "#{I18n.t('simple_form.labels.supplier.email')}: #{contact[:email]}", size: 9, align: :right
end
# Recipient
bounding_box [margin_box.left,margin_box.top-60], width: 200 do
text @order.name
move_down 5
text @order.supplier.address
text @order.supplier.try(:address).to_s
move_down 5
text "Fax: " + @order.supplier.fax
text "#{I18n.t('simple_form.labels.supplier.fax')}: #{@order.supplier.try(:fax)}"
end
move_down 5
text Date.today.strftime('%d.%m.%Y'), align: :right
text Date.today.strftime(I18n.t('date.formats.default')), align: :right
move_down 10
text "Lieferdatum:"
text "#{I18n.t('simple_form.labels.delivery.delivered_on')}:"
move_down 10
text "Ansprechpartner: " + @order.supplier.contact_person
text "#{I18n.t('simple_form.labels.supplier.contact_person')}: #{@order.supplier.try(:contact_person)}"
move_down 10
# Articles
data = [["BestellNr.", "Menge","Name", "Gebinde", "Einheit","Preis/Einheit"]]
data = @order.order_articles.ordered.all(include: :article).collect do |a|
data = [I18n.t('documents.order_fax.rows')]
data += @order.order_articles.ordered.all(include: :article).collect do |a|
[a.article.order_number,
a.units_to_order,
a.article.name,

View file

@ -4,22 +4,23 @@ class OrderMatrix < OrderPdf
MAX_ARTICLES_PER_PAGE = 16 # How many order_articles shoud written on a page
def filename
"Bestellung #{@order.name}-#{@order.ends.to_date} - Sortiermatrix.pdf"
I18n.t('documents.order_matrix.filename', :name => @order.name, :date => @order.ends.to_date) + '.pdf'
end
def title
"Sortiermatrix der Bestellung: #{@order.name}, beendet am #{@order.ends.strftime('%d.%m.%Y')}"
I18n.t('documents.order_matrix.title', :name => @order.name,
:date => @order.ends.strftime(I18n.t('date.formats.default')))
end
def body
order_articles = @order.order_articles.ordered
text "Artikelübersicht", style: :bold
text I18n.t('documents.order_matrix.heading'), style: :bold
move_down 5
text "Insgesamt #{order_articles.size} Artikel", size: 8
text I18n.t('documents.order_matrix.total', :count => order_articles.size), size: 8
move_down 10
order_articles_data = [%w(Artikel Einheit Gebinde FC-Preis Menge)]
order_articles_data = [I18n.t('documents.order_matrix.rows')]
order_articles.each do |a|
order_articles_data << [a.article.name,

View file

@ -58,7 +58,7 @@ module ApplicationHelper
nil
end
html_options = {
:title => "Nach #{text} sortieren",
:title => I18n.t('helpers.application.sort_by', text: text),
:remote => remote,
:class => class_name
}
@ -83,7 +83,7 @@ module ApplicationHelper
# Returns the weekday. 0 is sunday, 1 is monday and so on
def weekday(dayNumber)
weekdays = ["Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"]
weekdays = I18n.t('date.day_names')
return weekdays[dayNumber]
end
@ -103,9 +103,9 @@ module ApplicationHelper
def icon(name, options={})
icons = {
:delete => { :file => 'b_drop.png', :alt => 'Löschen'},
:edit => { :file => 'b_edit.png', :alt => 'Bearbeiten'},
:members => { :file => 'b_users.png', :alt => 'Mitlglieder bearbeiten'}
:delete => { :file => 'b_drop.png', :alt => I18n.t('ui.delete')},
:edit => { :file => 'b_edit.png', :alt => I18n.t('ui.edit')},
:members => { :file => 'b_users.png', :alt => I18n.t('helpers.application.edit_user')}
}
options[:alt] ||= icons[name][:alt]
options[:title] ||= icons[name][:title]
@ -126,16 +126,16 @@ module ApplicationHelper
def format_roles(record)
roles = []
roles << 'Admin' if record.role_admin?
roles << 'Finanzen' if record.role_finance?
roles << 'Lieferanten' if record.role_suppliers?
roles << 'Artikel' if record.role_article_meta?
roles << 'Bestellung' if record.role_orders?
roles << I18n.t('helpers.application.role_admin') if record.role_admin?
roles << I18n.t('helpers.application.role_finance') if record.role_finance?
roles << I18n.t('helpers.application.role_suppliers') if record.role_suppliers?
roles << I18n.t('helpers.application.role_article_meta') if record.role_article_meta?
roles << I18n.t('helpers.application.role_orders') if record.role_orders?
roles.join(', ')
end
def link_to_gmaps(address)
link_to h(address), "http://maps.google.de/?q=#{h(address)}", :title => "Show it on google maps",
link_to h(address), "http://maps.google.com/?q=#{h(address)}", :title => I18n.t('helpers.application.show_google_maps'),
:target => "_blank"
end
@ -143,7 +143,7 @@ module ApplicationHelper
# checks for nil (useful for relations)
def link_to_user_message_if_valid(user)
user.nil? ? '??' : link_to(user.nick, new_message_path('message[mail_to]' => user.id),
:title => 'Nachricht schreiben')
:title => I18n.t('helpers.application.write_message'))
end
def bootstrap_flash
@ -152,7 +152,7 @@ module ApplicationHelper
type = :success if type == :notice
type = :error if type == :alert
text = content_tag(:div,
content_tag(:button, raw("&times;"), :class => "close", "data-dismiss" => "alert") +
content_tag(:button, I18n.t('ui.marks.close').html_safe, :class => "close", "data-dismiss" => "alert") +
message, :class => "alert fade in alert-#{type}")
flash_messages << text if message
end

View file

@ -3,15 +3,15 @@ module DeliveriesHelper
def link_to_invoice(delivery)
if delivery.invoice
link_to number_to_currency(delivery.invoice.amount), [:finance, delivery.invoice],
title: "Rechnung anzeigen"
title: I18n.t('helpers.deliveries.show_invoice')
else
link_to "Rechnung anlegen", new_finance_invoice_path(supplier_id: delivery.supplier.id, delivery_id: delivery.id),
link_to I18n.t('helpers.deliveries.new_invoice'), new_finance_invoice_path(supplier_id: delivery.supplier.id, delivery_id: delivery.id),
class: 'btn btn-mini'
end
end
def stock_articles_for_select(supplier)
supplier.stock_articles.map {|a| ["#{a.name} (#{number_to_currency a.price}/#{a.unit})", a.id] }
supplier.stock_articles.undeleted.reorder('articles.name ASC').map {|a| ["#{a.name} (#{number_to_currency a.price}/#{a.unit})", a.id] }
end
end

View file

@ -15,6 +15,6 @@ module MessagesHelper
link_text = content_tag :id, nil, class: 'icon-envelope'
link_text << " #{options[:text]}" if options[:text].present?
link_to(link_text.html_safe, new_message_path(message: messages_params), class: 'btn',
title: 'Nachricht verschicken')
title: I18n.t('helpers.submit.message.create'))
end
end

View file

@ -6,13 +6,13 @@ module OrdersHelper
end
def order_pdf(order, document, text)
link_to text, order_path(order, document: document, format: :pdf), title: "PDF erstellen"
link_to text, order_path(order, document: document, format: :pdf), title: I18n.t('helpers.orders.order_pdf')
end
def options_for_suppliers_to_select
options = [["Lieferantin/Lager auswählen"]]
options = [[I18n.t('helpers.orders.option_choose')]]
options += Supplier.all.map {|s| [ s.name, url_for(action: "new", supplier_id: s)] }
options += [["Lager", url_for(action: 'new', supplier_id: 0)]]
options += [[I18n.t('helpers.orders.option_stock'), url_for(action: 'new', supplier_id: 0)]]
options_for_select(options)
end
end

View file

@ -10,7 +10,7 @@ module TasksHelper
def highlighted_required_users(task)
unless task.enough_users_assigned?
content_tag :span, task.still_required_users, class: 'badge badge-important',
title: "Es fehlen #{task.still_required_users} Mitstreiterinnen!"
title: I18n.t('helpers.tasks.required_users', :count => task.still_required_users)
end
end
end

View file

@ -26,7 +26,7 @@ class Mailer < ActionMailer::Base
@link = new_password_url(id: @user.id, token: @user.reset_password_token)
mail :to => @user.email,
:subject => "[#{FoodsoftConfig[:name]}] Neues Passwort für/ New password for #{@user.nick}"
:subject => "[#{FoodsoftConfig[:name]}] " + I18n.t('mailer.reset_password.subject', :username => @user.nick)
end
# Sends an invite email.
@ -36,7 +36,7 @@ class Mailer < ActionMailer::Base
@link = accept_invitation_url(token: @invite.token)
mail :to => @invite.email,
:subject => "Einladung in die Foodcoop #{FoodsoftConfig[:name]} - Invitation to the Foodcoop"
:subject => I18n.t('mailer.invite.subject')
end
# Notify user of upcoming task.
@ -46,7 +46,7 @@ class Mailer < ActionMailer::Base
@task = task
mail :to => user.email,
:subject => "[#{FoodsoftConfig[:name]}] Aufgaben werden fällig!"
:subject => "[#{FoodsoftConfig[:name]}] " + I18n.t('mailer.upcoming_tasks.subject')
end
# Sends order result for specific Ordergroup
@ -56,7 +56,7 @@ class Mailer < ActionMailer::Base
@group_order = group_order
mail :to => user.email,
:subject => "[#{FoodsoftConfig[:name]}] Bestellung beendet: #{group_order.order.name}"
:subject => "[#{FoodsoftConfig[:name]}] " + I18n.t('mailer.order_result.subject', :name => group_order.order.name)
end
# Notify user if account balance is less than zero
@ -66,7 +66,7 @@ class Mailer < ActionMailer::Base
@transaction = transaction
mail :to => user.email,
:subject => "[#{FoodsoftConfig[:name]}] Gruppenkonto im Minus"
:subject => "[#{FoodsoftConfig[:name]}] " + I18n.t('mailer.negative_balance')
end
def feedback(user, feedback)
@ -78,7 +78,7 @@ class Mailer < ActionMailer::Base
:from => "#{user.nick} <#{user.email}>",
:sender => FoodsoftConfig[:notification]["sender_address"],
:errors_to => FoodsoftConfig[:notification]["sender_address"],
:subject => "[Foodsoft] Feeback von #{user.email}"
:subject => "[#{FoodsoftConfig[:name]}] " + I18n.t('mailer.feedback.subject', :email => user.email)
end
def not_enough_users_assigned(task, user)
@ -87,7 +87,7 @@ class Mailer < ActionMailer::Base
@user = user
mail :to => user.email,
:subject => "[#{FoodsoftConfig[:name]}] \"#{task.name}\" braucht noch Leute!"
:subject => "[#{FoodsoftConfig[:name]}] " + I18n.t('mailer.not_enough_users_assigned.subject', :task => task.name)
end
private

View file

@ -1,24 +1,25 @@
# encoding: utf-8
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
# Replace numeric seperator with database format
localize_input_of :price, :tax, :deposit
# Associations
belongs_to :supplier, :with_deleted => true
belongs_to :supplier
belongs_to :article_category
has_many :article_prices, :order => "created_at DESC"
scope :available, :conditions => {:availability => true}
scope :undeleted, -> { where(deleted_at: nil) }
scope :available, -> { undeleted.where(availability: true) }
scope :not_in_stock, :conditions => {:type => nil}
# Validations
validates_presence_of :name, :unit, :price, :tax, :deposit, :unit_quantity, :supplier_id, :article_category
validates_length_of :name, :in => 4..60
validates_length_of :unit, :in => 2..15
validates_numericality_of :price, :unit_quantity, :greater_than => 0
validates_numericality_of :price, :greater_than_or_equal_to => 0
validates_numericality_of :unit_quantity, :greater_than => 0
validates_numericality_of :deposit, :tax
validates_uniqueness_of :name, :scope => [:supplier_id, :deleted_at, :type]
@ -49,6 +50,11 @@ class Article < ActiveRecord::Base
end
memoize :in_open_order
# Returns true if the article has been ordered in the given order at least once
def ordered_in_order?(order)
order.order_articles.where(article_id: id).where('quantity > 0').one?
end
# this method checks, if the shared_article has been changed
# unequal attributes will returned in array
# if only the timestamps differ and the attributes are equal,
@ -136,11 +142,20 @@ class Article < ActiveRecord::Base
end
end
def deleted?
deleted_at.present?
end
def mark_as_deleted
check_article_in_use
update_column :deleted_at, Time.now
end
protected
# Checks if the article is in use before it will deleted
def check_article_in_use
raise self.name.to_s + " kann nicht gelöscht werden. Der Artikel befindet sich in einer laufenden Bestellung!" if self.in_open_order
raise I18n.t('articles.model.error_in_use', :article => self.name.to_s) if self.in_open_order
end
# Create an ArticlePrice, when the price-attr are changed.

View file

@ -8,7 +8,7 @@ class ArticleCategory < ActiveRecord::Base
protected
def check_for_associated_articles
raise I18n.t('activerecord.errors.has_many_left', collection: Article.model_name.human) if articles.exists?
raise I18n.t('activerecord.errors.has_many_left', collection: Article.model_name.human) if articles.undeleted.exists?
end
end

View file

@ -1,10 +1,11 @@
class ArticlePrice < ActiveRecord::Base
belongs_to :article, :with_deleted => true
belongs_to :article
has_many :order_articles
validates_presence_of :price, :tax, :deposit, :unit_quantity
validates_numericality_of :price, :unit_quantity, :greater_than => 0
validates_numericality_of :price, :greater_than_or_equal_to => 0
validates_numericality_of :unit_quantity, :greater_than => 0
validates_numericality_of :deposit, :tax
localize_input_of :price, :tax, :deposit

View file

@ -1,6 +1,6 @@
class Delivery < ActiveRecord::Base
belongs_to :supplier, :with_deleted => true
belongs_to :supplier
has_one :invoice
has_many :stock_changes, :dependent => :destroy

View file

@ -1,7 +1,7 @@
# financial transactions are the foodcoop internal financial transactions
# only ordergroups have an account balance and are happy to transfer money
class FinancialTransaction < ActiveRecord::Base
belongs_to :ordergroup, :with_deleted => true
belongs_to :ordergroup
belongs_to :user
validates_presence_of :amount, :note, :user_id, :ordergroup_id

View file

@ -1,13 +1,15 @@
# Groups organize the User.
# A Member gets the roles from the Group
class Group < ActiveRecord::Base
has_many :memberships, :dependent => :destroy
has_many :memberships
has_many :users, :through => :memberships
validates :name, :presence => true, :length => {:in => 1..25}
attr_reader :user_tokens
scope :undeleted, -> { where(deleted_at: nil) }
# Returns true if the given user if is an member of this group.
def member?(user)
memberships.find_by_user_id(user.id)
@ -22,6 +24,18 @@ class Group < ActiveRecord::Base
self.user_ids = ids.split(",")
end
def deleted?
deleted_at.present?
end
def mark_as_deleted
# TODO: Checks for participating in not closed orders
transaction do
memberships.destroy_all
# TODO: What should happen to users?
update_column :deleted_at, Time.now
end
end
end

View file

@ -4,7 +4,7 @@ class GroupOrder < ActiveRecord::Base
attr_accessor :group_order_articles_attributes
belongs_to :order
belongs_to :ordergroup, :with_deleted => true
belongs_to :ordergroup
has_many :group_order_articles, :dependent => :destroy
has_many :order_articles, :through => :group_order_articles
belongs_to :updated_by, :class_name => "User", :foreign_key => "updated_by_user_id"

View file

@ -27,7 +27,7 @@ class Invite < ActiveRecord::Base
# Custom validation: check that email does not already belong to a registered user.
def email_not_already_registered
unless User.find_by_email(self.email).nil?
errors.add(:email, 'ist bereits in Verwendung. Person ist schon Mitglied der Foodcoop.')
errors.add(:email, I18n.t('invites.errors.already_member'))
end
end

View file

@ -1,6 +1,6 @@
class Invoice < ActiveRecord::Base
belongs_to :supplier, :with_deleted => true
belongs_to :supplier
belongs_to :delivery
belongs_to :order

View file

@ -6,7 +6,7 @@ class Membership < ActiveRecord::Base
before_destroy :check_last_admin
# messages
ERR_NO_ADMIN_MEMBER_DELETE = "Mitgliedschaft kann nicht beendet werden. Du bist die letzte Administratorin"
ERR_NO_ADMIN_MEMBER_DELETE = I18n.t('model.membership.no_admin_delete')
protected

View file

@ -2,7 +2,7 @@ class Message < ActiveRecord::Base
belongs_to :sender, :class_name => "User", :foreign_key => "sender_id"
serialize :recipients_ids, Array
attr_accessor :sent_to_all, :group_id, :recipient_tokens
attr_accessor :sent_to_all, :group_id, :recipient_tokens, :reply_to
scope :pending, where(:email_state => 0)
scope :sent, where(:email_state => 1)
@ -46,11 +46,11 @@ class Message < ActiveRecord::Base
end
def reply_to=(message_id)
message = Message.find(message_id)
add_recipients([message.sender])
self.subject = "Re: #{message.subject}"
self.body = "#{message.sender.nick} schrieb am #{I18n.l(message.created_at, :format => :short)}:\n"
message.body.each_line{ |l| self.body += "> #{l}" }
@reply_to = Message.find(message_id)
add_recipients([@reply_to.sender])
self.subject = I18n.t('messages.model.reply_subject', :subject => @reply_to.subject)
self.body = I18n.t('messages.model.reply_header', :user => @reply_to.sender.nick, :when => I18n.l(@reply_to.created_at, :format => :short)) + "\n"
@reply_to.body.each_line{ |l| self.body += I18n.t('messages.model.reply_indent', :line => l) }
end
def mail_to=(user_id)
@ -64,7 +64,7 @@ class Message < ActiveRecord::Base
end
def sender_name
system_message? ? 'Foodsoft' : sender.nick rescue "??"
system_message? ? I18n.t('layouts.foodsoft') : sender.nick rescue "??"
end
def recipients
@ -83,6 +83,10 @@ class Message < ActiveRecord::Base
end
update_attribute(:email_state, 1)
end
def is_readable_for?(user)
!private || sender == user || recipients_ids.include?(user.id)
end
end

View file

@ -10,7 +10,7 @@ class Order < ActiveRecord::Base
has_one :invoice
has_many :comments, :class_name => "OrderComment", :order => "created_at"
has_many :stock_changes
belongs_to :supplier, :with_deleted => true
belongs_to :supplier
belongs_to :updated_by, :class_name => 'User', :foreign_key => 'updated_by_user_id'
belongs_to :created_by, :class_name => 'User', :foreign_key => 'created_by_user_id'
@ -38,9 +38,11 @@ class Order < ActiveRecord::Base
def articles_for_ordering
if stockit?
# make sure to include those articles which are no longer available
# but which have already been ordered in this stock order
StockArticle.available.all(:include => :article_category,
:order => 'article_categories.name, articles.name').reject{ |a|
a.quantity_available <= 0
a.quantity_available <= 0 and not a.ordered_in_order?(self)
}.group_by { |a| a.article_category.name }
else
supplier.articles.available.all.group_by { |a| a.article_category.name }
@ -113,25 +115,25 @@ class Order < ActiveRecord::Base
def sum(type = :gross)
total = 0
if type == :net || type == :gross || type == :fc
for oa in order_articles.ordered.all(:include => [:article,:article_price])
for oa in order_articles.ordered.includes(:article, :article_price)
quantity = oa.units_to_order * oa.price.unit_quantity
case type
when :net
total += quantity * oa.price.price
when :gross
total += quantity * oa.price.gross_price
when :fc
total += quantity * oa.price.fc_price
when :net
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.all(:include => :group_order_articles)
for goa in go.group_order_articles.all(:include => [:order_article])
for go in group_orders.includes(group_order_articles: {order_article: [:article, :article_price]})
for goa in go.group_order_articles
case type
when :groups
total += goa.result * goa.order_article.price.fc_price
when :groups_without_markup
total += goa.result * goa.order_article.price.gross_price
when :groups
total += goa.result * goa.order_article.price.fc_price
when :groups_without_markup
total += goa.result * goa.order_article.price.gross_price
end
end
end
@ -156,7 +158,7 @@ class Order < ActiveRecord::Base
goa.save_results!
# Delete no longer required order-history (group_order_article_quantities) and
# TODO: Do we need articles, which aren't ordered? (units_to_order == 0 ?)
goa.group_order_article_quantities.clear
#goa.group_order_article_quantities.clear
end
end
@ -174,8 +176,9 @@ class Order < ActiveRecord::Base
# Sets order.status to 'close' and updates all Ordergroup.account_balances
def close!(user)
raise "Bestellung wurde schon abgerechnet" if closed?
transaction_note = "Bestellung: #{name}, bis #{ends.strftime('%d.%m.%Y')}"
raise I18n.t('orders.model.error_closed') if closed?
transaction_note = I18n.t('orders.model.notice_close', :name => name,
:ends => ends.strftime(I18n.t('date.formats.default')))
gos = group_orders.all(:include => :ordergroup) # Fetch group_orders
gos.each { |group_order| group_order.update_price! } # Update prices of group_orders
@ -199,18 +202,18 @@ class Order < ActiveRecord::Base
# Close the order directly, without automaticly updating ordergroups account balances
def close_direct!(user)
raise "Bestellung wurde schon abgerechnet" if closed?
raise I18n.t('orders.model.error_closed') if closed?
update_attributes! state: 'closed', updated_by: user
end
protected
def starts_before_ends
errors.add(:ends, "muss nach dem Bestellstart liegen (oder leer bleiben)") if (ends && starts && ends <= starts)
errors.add(:ends, I18n.t('articles.model.error_starts_before_ends')) if (ends && starts && ends <= starts)
end
def include_articles
errors.add(:articles, "Es muss mindestens ein Artikel ausgewählt sein") if article_ids.empty?
errors.add(:articles, I18n.t('articles.model.error_nosel')) if article_ids.empty?
end
def save_order_articles

View file

@ -4,7 +4,7 @@ class OrderArticle < ActiveRecord::Base
attr_reader :update_current_price
belongs_to :order
belongs_to :article, :with_deleted => true
belongs_to :article
belongs_to :article_price
has_many :group_order_articles, :dependent => :destroy
@ -93,7 +93,7 @@ class OrderArticle < ActiveRecord::Base
end
# Updates order_article and belongings during balancing process
def update_article_and_price!(article_attributes, price_attributes, order_article_attributes)
def update_article_and_price!(order_article_attributes, article_attributes, price_attributes = nil)
OrderArticle.transaction do
# Updates self
self.update_attributes!(order_article_attributes)
@ -102,20 +102,22 @@ class OrderArticle < ActiveRecord::Base
article.update_attributes!(article_attributes)
# Updates article_price belonging to current order article
article_price.attributes = price_attributes
if article_price.changed?
# Updates also price attributes of article if update_current_price is selected
if update_current_price
article.update_attributes!(price_attributes)
self.article_price = article.article_prices.first # Assign new created article price to order article
else
# Creates a new article_price if neccessary
# Set created_at timestamp to order ends, to make sure the current article price isn't changed
create_article_price!(price_attributes.merge(created_at: order.ends)) and save
end
if price_attributes.present?
article_price.attributes = price_attributes
if article_price.changed?
# Updates also price attributes of article if update_current_price is selected
if update_current_price
article.update_attributes!(price_attributes)
self.article_price = article.article_prices.first # Assign new created article price to order article
else
# Creates a new article_price if neccessary
# Set created_at timestamp to order ends, to make sure the current article price isn't changed
create_article_price!(price_attributes.merge(created_at: order.ends)) and save
end
# Updates ordergroup values
update_ordergroup_prices
# Updates ordergroup values
update_ordergroup_prices
end
end
end
end
@ -134,7 +136,7 @@ class OrderArticle < ActiveRecord::Base
private
def article_and_price_exist
errors.add(:article, "muss angegeben sein und einen aktuellen Preis haben") if !(article = Article.find(article_id)) || article.fc_price.nil?
errors.add(:article, I18n.t('model.order_article.error_price')) if !(article = Article.find(article_id)) || article.fc_price.nil?
end
# Associate with current article price if created in a finished order
@ -146,7 +148,10 @@ class OrderArticle < ActiveRecord::Base
end
def update_ordergroup_prices
group_order_articles.each { |goa| goa.group_order.update_price! }
# updates prices of ALL ordergroups - these are actually too many
# in case of performance issues, update only ordergroups, which ordered this article
# CAUTION: in after_destroy callback related records (e.g. group_order_articles) are already non-existent
order.group_orders.each { |go| go.update_price! }
end
end

View file

@ -8,14 +8,13 @@ class Ordergroup < Group
APPLE_MONTH_AGO = 6 # How many month back we will count tasks and orders sum
acts_as_paranoid # Avoid deleting the ordergroup for consistency of order-results
serialize :stats
has_many :financial_transactions
has_many :group_orders
has_many :orders, :through => :group_orders
validates_numericality_of :account_balance, :message => 'ist keine gültige Zahl'
validates_numericality_of :account_balance, :message => I18n.t('ordergroups.model.invalid_balance')
validate :uniqueness_of_name, :uniqueness_of_members
after_create :update_stats!
@ -103,7 +102,7 @@ class Ordergroup < Group
# Make sure, that a user can only be in one ordergroup
def uniqueness_of_members
users.each do |user|
errors.add :user_tokens, "#{user.nick} ist schon in einer anderen Bestellgruppe" if user.groups.where(:type => 'Ordergroup').size > 1
errors.add :user_tokens, I18n.t('ordergroups.model.error_single_group', :user => user.nick) if user.groups.where(:type => 'Ordergroup').size > 1
end
end
@ -117,5 +116,15 @@ class Ordergroup < Group
end
end
# Make sure, the name is uniq, add usefull message if uniq group is already deleted
def uniqueness_of_name
id = new_record? ? '' : self.id
group = Ordergroup.where('groups.id != ? AND groups.name = ?', id, name).first
if group.present?
message = group.deleted? ? :taken_with_deleted : :taken
errors.add :name, message
end
end
end

View file

@ -47,7 +47,7 @@ class Page < ActiveRecord::Base
unless old_title.blank?
Page.create :redirect => id,
:title => old_title,
:body => "Weiterleitung auf [[#{title}]]..",
:body => I18n.t('model.page.redirect', :title => title),
:permalink => Page.permalink(old_title),
:updated_by => updated_by
end

View file

@ -8,5 +8,11 @@ class SharedSupplier < ActiveRecord::Base
has_one :supplier
has_many :shared_articles, :foreign_key => :supplier_id
# These set of attributes are used to autofill attributes of new supplier,
# when created by import from shared supplier feature.
def autofill_attributes
whitelist = %w(name address phone fax email url delivery_days note)
attributes.select { |k,_v| whitelist.include?(k) }
end
end

View file

@ -1,10 +1,9 @@
# encoding: utf-8
class StockArticle < Article
acts_as_paranoid
has_many :stock_changes
scope :available, :conditions => "quantity > 0"
scope :available, -> { undeleted.where'quantity > 0' }
before_destroy :check_quantity
@ -23,10 +22,15 @@ class StockArticle < Article
available.collect { |a| a.quantity * a.gross_price }.sum
end
def mark_as_deleted
check_quantity
super
end
protected
def check_quantity
raise "#{name} kann nicht gelöscht werden. Der Lagerbestand ist nicht null." unless quantity == 0
raise I18n.t('stockit.check.not_empty', :name => name) unless quantity == 0
end
# Overwrite Price history of Article. For StockArticles isn't it necessary.

View file

@ -1,7 +1,7 @@
class StockChange < ActiveRecord::Base
belongs_to :delivery
belongs_to :order
belongs_to :stock_article, with_deleted: true
belongs_to :stock_article
validates_presence_of :stock_article_id, :quantity
validates_numericality_of :quantity

View file

@ -1,7 +1,7 @@
# encoding: utf-8
class Supplier < ActiveRecord::Base
acts_as_paranoid # Avoid deleting the supplier for consistency of order-results
has_many :articles, :dependent => :destroy, :conditions => {:type => nil},
has_many :articles, :conditions => {:type => nil},
:include => [:article_category], :order => 'article_categories.name, articles.name'
has_many :stock_articles, :include => [:article_category], :order => 'article_categories.name, articles.name'
has_many :orders
@ -20,13 +20,15 @@ class Supplier < ActiveRecord::Base
validates_length_of :address, :in => 8..50
validate :uniqueness_of_name
scope :undeleted, -> { where(deleted_at: nil) }
# sync all articles with the external database
# returns an array with articles(and prices), which should be updated (to use in a form)
# also returns an array with outlisted_articles, which should be deleted
def sync_all
updated_articles = Array.new
outlisted_articles = Array.new
for article in articles
for article in articles.undeleted
# try to find the associated shared_article
shared_article = article.shared_article
@ -65,12 +67,23 @@ class Supplier < ActiveRecord::Base
return [updated_articles, outlisted_articles]
end
def deleted?
deleted_at.present?
end
def mark_as_deleted
transaction do
update_column :deleted_at, Time.now
articles.each(&:mark_as_deleted)
end
end
protected
# Make sure, the name is uniq, add usefull message if uniq group is already deleted
def uniqueness_of_name
id = new_record? ? '' : self.id
supplier = Supplier.with_deleted.where('suppliers.id != ? AND suppliers.name = ?', id, name).first
supplier = Supplier.where('suppliers.id != ? AND suppliers.name = ?', id, name).first
if supplier.present?
message = supplier.deleted? ? :taken_with_deleted : :taken
errors.add :name, message

View file

@ -75,13 +75,10 @@ class Task < ActiveRecord::Base
# and makes the users responsible for the task
# TODO: check for maximal number of users
def user_list=(ids)
list = ids.split(",")
list = ids.split(",").map(&:to_i)
new_users = (list - users.collect(&:id)).uniq
old_users = users.reject { |user| list.include?(user.id) }
logger.debug "[debug] New users: #{new_users}"
logger.debug "Old users: #{old_users}"
self.class.transaction do
# delete old assignments
if old_users.any?
@ -93,7 +90,7 @@ class Task < ActiveRecord::Base
if user.blank?
errors.add(:user_list)
else
if id == current_user_id
if id == current_user_id.to_i
# current_user will accept, when he puts himself to the list of users
self.assignments.build :user => user, :accepted => true
else

View file

@ -44,13 +44,13 @@ class User < ActiveRecord::Base
# returns the User-settings and the translated description
def self.setting_keys
{
"notify.orderFinished" => 'Informier mich über meine Bestellergebnisse (nach Ende der Bestellung).',
"notify.negativeBalance" => 'Informiere mich, falls meine Bestellgruppe ins Minus rutscht.',
"notify.upcoming_tasks" => 'Erinnere mich an anstehende Aufgaben.',
"messages.sendAsEmail" => 'Bekomme Nachrichten als Emails.',
"profile.phoneIsPublic" => 'Telefon ist für Mitglieder sichtbar',
"profile.emailIsPublic" => 'E-Mail ist für Mitglieder sichtbar',
"profile.nameIsPublic" => 'Name ist für Mitglieder sichtbar'
"notify.orderFinished" => I18n.t('model.user.notify.order_finished'),
"notify.negativeBalance" => I18n.t('model.user.notify.negative_balance'),
"notify.upcoming_tasks" => I18n.t('model.user.notify.upcoming_tasks'),
"messages.sendAsEmail" => I18n.t('model.user.notify.send_as_email'),
"profile.phoneIsPublic" => I18n.t('model.user.notify.phone_is_public'),
"profile.emailIsPublic" => I18n.t('model.user.notify.email_is_public'),
"profile.nameIsPublic" => I18n.t('model.user.notify.name_is_public')
}
end
# retuns the default setting for a NEW user
@ -132,7 +132,7 @@ class User < ActiveRecord::Base
end
def ordergroup_name
ordergroup ? ordergroup.name : "keine Bestellgruppe"
ordergroup ? ordergroup.name : I18n.t('model.user.no_ordergroup')
end
# returns true if user is a member of a given group

View file

@ -15,7 +15,8 @@ class Workgroup < Group
before_destroy :check_last_admin_group
def self.weekdays
[["Montag", "1"], ["Dienstag", "2"], ["Mittwoch","3"],["Donnerstag","4"],["Freitag","5"],["Samstag","6"],["Sonntag","0"]]
days = I18n.t('date.day_names')
(0..days.length-1).map {|i| [days[i], i.to_s]}
end
# Returns an Array with date-objects to represent the next weekly-tasks
@ -55,7 +56,7 @@ class Workgroup < Group
# Check before destroy a group, if this is the last group with admin role
def check_last_admin_group
if role_admin && Workgroup.where(:role_admin => true).size == 1
raise "Die letzte Gruppe mit Admin-Rechten darf nicht gelöscht werden"
raise I18n.t('workgroups.error_last_admin_group')
end
end
@ -63,7 +64,7 @@ class Workgroup < Group
# Return an error if this is the last group with admin role and role_admin should set to false
def last_admin_on_earth
if !role_admin && !Workgroup.where('role_admin = ? AND id != ?', true, id).exists?
errors.add(:role_admin, "Der letzten Gruppe mit Admin-Rechten darf die Admin-Rolle nicht entzogen werden")
errors.add(:role_admin, I18n.t('workgroups.error_last_admin_role'))
end
end

View file

@ -1,43 +1,43 @@
- title "Administration"
- title t '.title'
%p
%i Hier kannst Du die Gruppen und Benutzerinnen der Foodsoft verwalten.
%i= t '.first_paragraph'
.row-fluid
.span6
%section
%h2 Neuste Benutzerinnen
%h2= t '.newest_users'
%table.table.table-striped
%thead
%tr
%th Benutzername
%th Name
%th Erstellt am
%th= t '.username'
%th= t '.name'
%th= t '.created_at'
- for user in @users
%tr{:class => cycle('even','odd', :name => 'users')}
%td= link_to user.nick, [:admin, user]
%td=h user.name
%td= format_date(user.created_on)
= link_to 'Alle Benutzerinnen', admin_users_path
= link_to t('.all_users'), admin_users_path
|
= link_to "Neue Benutzerin", new_admin_user_path, class: 'btn btn-primary btn-small'
= link_to t('.new_user'), new_admin_user_path, class: 'btn btn-primary btn-small'
.span6
%section
%h2 Neuste Gruppen
%h2= t '.newest_groups'
%table.table.table-striped
%thead
%tr
%th Gruppenname
%th Typ
%th Mitglieder
%th= t '.groupname'
%th= t '.type'
%th= t '.members'
- for group in @groups
%tr{:class => cycle('even','odd', :name => 'groups')}
%td= link_to group.name, [:admin, group]
%td= group.class.model_name.human
%td= group.users.size
= link_to 'Alle Bestellgruppen', admin_ordergroups_path
= link_to t('.all_ordergroups'), admin_ordergroups_path
|
= link_to "Neue Bestellgruppe", new_admin_ordergroup_path, class: 'btn btn-primary btn-small'
= link_to t('.new_ordergroup'), new_admin_ordergroup_path, class: 'btn btn-primary btn-small'
|
= link_to 'Alle Arbeitsgruppen', admin_workgroups_path
= link_to t('.all_workgroups'), admin_workgroups_path
|
= link_to "Neue Arbeitsgruppe", new_admin_workgroup_path, class: 'btn btn-primary btn-small'
= link_to t('.new_workgroup'), new_admin_workgroup_path, class: 'btn btn-primary btn-small'

View file

@ -1,8 +1,5 @@
- unless @ordergroup.new_record?
%p
Neue Mitglieder kannst du
= link_to "hier", new_invite_path(id: @ordergroup.id), remote: true
einladen.
%p= t('.first_paragraph', url: link_to(t('.here'), new_invite_path(id: @ordergroup.id), remote: true)).html_safe
= simple_form_for [:admin, @ordergroup] do |f|
= render :layout => 'shared/group_form_fields', :locals => {:f => f} do
= f.input :contact_person
@ -11,4 +8,4 @@
= f.input :ignore_apple_restriction
.form-actions
= f.button :submit
= link_to "oder abbrechen", :back
= link_to t('ui.or_cancel'), :back

View file

@ -4,11 +4,11 @@
%table.table.table-striped
%thead
%tr
%th Name
%th Kontakt
%th Adresse
%th Mitglieder
%th Aktionen
%th= t '.name'
%th= t '.contact'
%th= t '.address'
%th= t '.members'
%th= t 'admin.actions'
%tbody
- for ordergroup in @ordergroups
%tr{:class => cycle('even','odd', :name => 'groups')}
@ -17,6 +17,6 @@
%td= link_to_gmaps ordergroup.contact_address
%td= ordergroup.users.size
%td
= link_to "Bearbeiten", edit_admin_ordergroup_path(ordergroup), class: 'btn btn-mini'
= link_to "Löschen", [:admin, ordergroup], :confirm => "Willst du #{ordergroup.name} wirklich löschen?",
= link_to t('ui.edit'), edit_admin_ordergroup_path(ordergroup), class: 'btn btn-mini'
= link_to t('ui.delete'), [:admin, ordergroup], :confirm => t('admin.confirm', name: ordergroup.name),
:method => :delete, class: 'btn btn-mini btn-danger'

View file

@ -1,3 +1,3 @@
- title "Bestellgruppe bearbeiten"
- title t '.title'
= render :partial => 'form'
= render 'form'

View file

@ -1,25 +1,15 @@
- title "Bestellgruppen"
- title t('.title')
- content_for :actionbar do
= link_to "Neue Bestellgruppe anlegen", new_admin_ordergroup_path, class: 'btn btn-primary'
= link_to t('.new_ordergroup'), new_admin_ordergroup_path, class: 'btn btn-primary'
- content_for :sidebar do
%p
Hier kannst du
= link_to 'neue Bestellgruppen', new_admin_ordergroup_path
anlegen, Gruppen bearbeiten und löschen.
%p
Beachte dabei den <em>Unterschied zwischen Gruppe und Bestellgruppe</em>:
Eine Bestellgruppe hat ein Konto und kann Essen bestellen. In einer
%em= link_to 'Arbeitsgruppe', admin_workgroups_path
(z.b. 'Soritiergruppe')
koordinieren sich die Mitglieder mittels Aufgaben und Nachrichten.
Nutzer_innen können immer nur einer Bestellgruppe, aber beliebig vielen anderen Gruppen angehören.
%p= t('.first_paragraph', url: link_to(t('.new_ordergroups'), new_admin_ordergroup_path)).html_safe
%p= t('.second_paragraph', url: link_to(t('.workgroup'), admin_workgroups_path)).html_safe
.well.well-small
= form_tag admin_ordergroups_path, :method => :get, :remote => true,
'data-submit-onchange' => true, class: 'form-search' do
= text_field_tag :query, params[:query], class: 'input-medium search-query',
placeholder: 'Name ...'
placeholder: t('admin.search_placeholder')
#ordergroups
= render "ordergroups"

View file

@ -1,3 +1,3 @@
- title "Bestellgruppe anlegen"
- title t '.title'
= render 'form'

View file

@ -1,6 +1,6 @@
- title "Bestellgruppe #{@ordergroup.name}"
- title t '.title', name: @ordergroup.name
%section= render 'shared/group', group: @ordergroup
= link_to 'Gruppe/Mitglieder bearbeiten', edit_admin_ordergroup_path(@ordergroup), class: 'btn'
= link_to 'Löschen', [:admin, @ordergroup], :confirm => 'Bist Du sicher?', :method => :delete, class: 'btn btn-danger'
= link_to 'Nachricht senden', new_message_path(:message => {:group_id => @ordergroup.id}), class: 'btn'
= link_to t('ui.edit'), edit_admin_ordergroup_path(@ordergroup), class: 'btn'
= link_to t('ui.delete'), [:admin, @ordergroup], :confirm => t('.confirm'), :method => :delete, class: 'btn btn-danger'
= link_to t('.send_message'), new_message_path(:message => {:group_id => @ordergroup.id}), class: 'btn'

View file

@ -1,5 +1,5 @@
= simple_form_for([:admin, @user]) do |f|
= render :partial => 'shared/user_form_fields', :locals => {:f => f}
= render 'shared/user_form_fields', f: f
.form-actions
= f.submit
= link_to 'oder abbrechen', :back
= link_to t('ui.or_cancel'), :back

View file

@ -4,12 +4,12 @@
%table.table.table-striped
%thead
%tr
%th Login
%th Name
%th Email
%th Zugriff auf
%th Letzter login
%th(colspan="2") Aktionen
%th= t '.login'
%th= t '.name'
%th= t '.email'
%th= t 'admin.access_to'
%th= t '.last_login'
%th(colspan="2")= t 'admin.actions'
%tbody
- for user in @users
%tr
@ -18,6 +18,6 @@
%td= user.email
%td= format_roles(user)
%td= format_time(user.last_login)
%td= link_to 'Bearbeiten', edit_admin_user_path(user), class: 'btn btn-mini'
%td= link_to 'Löschen', [:admin, user], :confirm => "Willst du #{user.name} wirklich löschen?",
%td= link_to t('ui.edit'), edit_admin_user_path(user), class: 'btn btn-mini'
%td= link_to t('ui.delete'), [:admin, user], :confirm => t('admin.confirm', name: user.name),
:method => :delete, class: 'btn btn-danger btn-mini'

View file

@ -1,3 +1,3 @@
- title "Benutzerin bearbeiten"
- title t '.title'
= render 'form'

View file

@ -1,18 +1,16 @@
- title "Admin/Benutzerinnen"
- title t '.title'
- content_for :actionbar do
= link_to 'Neue Benutzerin anlegen', new_admin_user_path, class: 'btn btn-primary'
= link_to t('.new_user'), new_admin_user_path, class: 'btn btn-primary'
- content_for :sidebar do
%p
Hier kannst du Benutzer_innen #{link_to 'neu Anlegen', new_admin_user_path},
bearbeiten und natürlich auch löschen.
%p= t('.first_paragraph', url: link_to(t('.new_users'), new_admin_user_path)).html_safe
.well.well-small
= form_tag admin_users_path, :method => :get, :remote => true,
'data-submit-onchange' => true, class: 'form-search' do
= text_field_tag :user_name, params[:user_name], class: 'input-medium search-query',
placeholder: 'Name ...'
placeholder: t('admin.search_placeholder')
#users
= render "users"

View file

@ -1,3 +1,3 @@
- title "Neue Benutzerin anlegen"
- title t '.title'
= render 'form'

View file

@ -3,37 +3,37 @@
.row-fluid
.span3
.well
%h4 Person
%p Mitglied seit #{distance_of_time_in_words(Time.now, @user.created_on)}
%h4= t '.person'
%p= t '.member_since', time: distance_of_time_in_words(Time.now, @user.created_on)
%dl
%dt Nick
%dt= t '.nick'
%dd= @user.nick
%dt Name
%dt= t '.name'
%dd= h @user.name
%dt Email
%dt= t '.email'
%dd= @user.email
%dt Telefon
%dt= t '.phone'
%dd= @user.phone
%dt Zugriff auf
%dt= t 'admin.access_to'
%dd= format_roles(@user)
.span5
.well
%h4 Einstellungen
%h4= t '.preference'
%table.table
- for setting in User::setting_keys.keys
%tr
%td= User::setting_keys[setting]
%td= @user.settings[setting] == '1' ? 'ja' : 'nein'
%td= @user.settings[setting] == '1' ? t('simple_form.yes') : t('simple_form.no')
.span3
.well
%h4 Gruppenabos
%h4= t '.groupabos'
%ul.unstyled
- for membership in Membership.find_all_by_user_id(@user.id)
%li= link_to(membership.group.name, [:admin, membership.group])
%hr/
%p
= link_to 'Bearbeiten', edit_admin_user_path(@user), class: 'btn'
= link_to 'Löschen', [:admin, @user], :confirm => "Willst du #{@user.first_name} wirklich rausschmeißen?",
= link_to t('ui.edit'), edit_admin_user_path(@user), class: 'btn'
= link_to t('ui.delete'), [:admin, @user], :confirm => t('.confirm', user: @user.first_name),
:method => :delete, class: 'btn btn-danger'
= link_to "Nachricht senden", new_message_path(:message => {:mail_to => @user.id}), class: 'btn'
= link_to t('.send_message'), new_message_path(:message => {:mail_to => @user.id}), class: 'btn'

View file

@ -1,10 +1,7 @@
%p
Neue Mitglieder kannst du
= link_to "hier", new_invite_path(id: @workgroup.id)
einladen.
%p= t('.first_paragraph', url: link_to(t('.here'), new_invite_path(id: @workgroup.id), remote: true)).html_safe
= simple_form_for [:admin, @workgroup] do |f|
= render :layout => 'shared/group_form_fields', :locals => {:f => f} do
%h4 Zugriff auf
%h4= t 'admin.access_to'
= f.input :role_admin
= f.input :role_finance
= f.input :role_suppliers
@ -12,4 +9,4 @@
= f.input :role_orders
.form-actions
= f.button :submit
= link_to "oder abbrechen", :back
= link_to t('ui.or_cancel'), :back

View file

@ -4,10 +4,10 @@
%table.table.table-striped
%thead
%tr
%th Name
%th Mitglieder
%th Zugriff auf
%th Aktionen
%th= t '.name'
%th= t '.members'
%th= t 'admin.access_to'
%th= t 'admin.actions'
%tbody
- for workgroup in @workgroups
%tr
@ -15,6 +15,6 @@
%td= workgroup.users.size
%td= format_roles(workgroup)
%td
= link_to "Bearbeiten", edit_admin_workgroup_path(workgroup), class: 'btn btn-mini'
= link_to "Löschen", [:admin, workgroup], :confirm => 'Willst du ' + workgroup.name + ' wirklich löschen?',
= link_to t('ui.edit'), edit_admin_workgroup_path(workgroup), class: 'btn btn-mini'
= link_to t('ui.delete'), [:admin, workgroup], :confirm => t('admin.confirm', name: workgroup.name),
:method => :delete, class: 'btn btn-mini btn-danger'

View file

@ -1,3 +1,3 @@
- title "Arbeitsgruppe bearbeiten"
- title t '.title'
= render 'form'

View file

@ -1,24 +1,15 @@
- title "Arbeitsgruppen"
- title t '.title'
- content_for :actionbar do
= link_to "Neue Arbeitsgruppe anlegen", new_admin_workgroup_path, class: 'btn btn-primary'
= link_to t('.new_workgroup'), new_admin_workgroup_path, class: 'btn btn-primary'
- content_for :sidebar do
%p
Hier kannst du
= link_to 'neue Arbeitsgruppen', new_admin_workgroup_path
anlegen, Gruppen bearbeiten und löschen.
%p
Beachte dabei den <strong>Unterschied zwischen Gruppe und Bestellgruppe</strong>:
Eine #{link_to 'Bestellgruppe', '/admin/ordergroups'}
hat ein Konto und kann Essen bestellen. In einer Arbeitsgruppe (z.b. 'Soritiergruppe')
koordinieren sich die Mitglieder mittels Aufgaben und Nachrichten.
Nutzer_innen können immer nur einer Bestellgruppe, aber beliebig vielen anderen Gruppen angehören.
%p= t('.first_paragraph', url: link_to(t('.new_workgroups'), new_admin_workgroup_path)).html_safe
%p= t('.second_paragraph', url: link_to(t('.ordergroup'), admin_ordergroups_path)).html_safe
.well.well-small
= form_tag admin_workgroups_path, :method => :get, :remote => true,
'data-submit-onchange' => true, class: 'form-search' do
= text_field_tag :query, params[:query], class: 'input-medium search-query',
placeholder: 'Name ...'
placeholder: t('admin.search_placeholder')
#workgroups
= render "workgroups"

View file

@ -1,3 +1,3 @@
- title "Arbeitsgruppe anlegen"
- title t '.title'
= render 'form'

View file

@ -1,6 +1,6 @@
- title "Arbeitsgruppe #{@workgroup.name}"
- title t '.title', name: @workgroup.name
%section= render :partial => 'shared/group', :locals => { :group => @workgroup }
= link_to 'Gruppe/Mitglieder bearbeiten', edit_admin_workgroup_path(@workgroup), class: 'btn'
= link_to 'Löschen', [:admin, @workgroup], :confirm => 'Bist Du sicher?', :method => :delete, class: 'btn btn-danger'
%section= render 'shared/group', group: @workgroup
= link_to t('ui.edit'), edit_admin_workgroup_path(@workgroup), class: 'btn'
= link_to t('ui.delete'), [:admin, @workgroup], :confirm => t('.confirm'), :method => :delete, class: 'btn btn-danger'
= link_to_new_message(message_params: {group_id: @workgroup.id})

View file

@ -3,4 +3,4 @@
= f.input :description
.form-actions
= f.submit class: 'btn'
= link_to 'oder abbrechen', article_categories_path
= link_to t('ui.or_cancel'), article_categories_path

View file

@ -1,3 +1,3 @@
- title "Kategorie ändern"
- title t('.title')
= render 'form'

View file

@ -1,12 +1,12 @@
- title "Artikelkategorien"
- title t('.title')
%p= link_to "Neue Kategorie anlegen", new_article_category_path, class: 'btn btn-primary'
%p= link_to t('.new'), new_article_category_path, class: 'btn btn-primary'
%table.table.table-striped
%thead
%tr
%th Name
%th Beschreibung
%th= t('simple_form.labels.article_category.name')
%th= t('simple_form.labels.article_category.description')
%th
%tbody
- @article_categories.each do |article_category|
@ -14,6 +14,6 @@
%td= article_category.name
%td= article_category.description
%td
= link_to "Bearbeiten", edit_article_category_path(article_category), class: 'btn btn-mini'
= link_to "Löschen", article_category, :method => :delete, :confirm => 'Are you sure?',
= link_to t('ui.edit'), edit_article_category_path(article_category), class: 'btn btn-mini'
= link_to t('ui.delete'), article_category, :method => :delete, :confirm => t('.confirm_delete'),
class: 'btn btn-mini btn-danger'

View file

@ -1,3 +1,3 @@
- title "Neue Kategorie anlegen"
- title t('.title')
= render 'form'

View file

@ -7,11 +7,11 @@
%td= truncate(article.note, :length => 11)
%td= article.unit_quantity
%td{:class => "currency"}
%acronym{:title => "zuletzt geändert: #{format_date(article.updated_at)} | Brutto: #{number_to_currency(article.gross_price)}"}
%acronym{:title => t('.last_update', last_update: format_date(article.updated_at), gross_price: number_to_currency(article.gross_price))}
= number_to_currency(article.price)
%td= number_to_percentage(article.tax) if article.tax != 0
%td= number_to_currency(article.deposit) if article.deposit != 0
%td= link_to "Bearbeiten", edit_supplier_article_path(@supplier, article),
%td= link_to t('ui.edit'), edit_supplier_article_path(@supplier, article),
:remote => true, class: 'btn btn-mini'
%td= link_to "Löschen", [@supplier, article],
:method => :delete, :confirm => 'Bist du sicher?', :remote => true, class: 'btn btn-mini btn-danger'
%td= link_to t('ui.delete'), [@supplier, article],
:method => :delete, :confirm => t('.confirm_delete'), :remote => true, class: 'btn btn-mini btn-danger'

View file

@ -6,15 +6,16 @@
%thead
%tr
%th
%th= sort_link_helper "Name", "name"
%th= sort_link_helper t('simple_form.labels.article.name'), "name"
%th
%th= sort_link_helper "Kategorie", "category"
%th= sort_link_helper "Einheit", "unit"
%th= sort_link_helper "Notiz", "note"
%th{:style => "width: 4em;"} Gebgr.
%th{:style => "width: 5em;"} Preis
%th{:style => "width: 3.5em;"} MwSt
%th{:style => "width: 4em;"} Pfand
%th= sort_link_helper t('simple_form.labels.article.article_category'), "category"
%th= sort_link_helper t('simple_form.labels.article.unit'), "unit"
%th= sort_link_helper t('simple_form.labels.article.note'), "note"
%th{:style => "width: 4em;"}
%acronym{:title => t('.unit_quantity_desc')}= t '.unit_quantity_short'
%th{:style => "width: 5em;"}= t '.price_netto'
%th{:style => "width: 3.5em;"}= t 'simple_form.labels.defaults.tax'
%th{:style => "width: 4em;"}= t 'simple_form.labels.defaults.deposit'
%th{:style => "width: 3em;"}
%tbody#listbody
@ -27,10 +28,10 @@
%td{:colspan => '11'}
= check_box_tag :checkall, 1, false, 'data-check-all' => '#articlesInListForm', 'data-ignore-onchange' => true
%select{:name => "selected_action", 'data-submit-onchange' => true}
%option{:value => '', :selected => 'selected'} Aktion wählen ...
%option{:value => "destroy", 'data-confirm' => 'Willst Du wirklich alle gewählten Artikel löschen?'} Artikel löschen
%option{:value => "setNotAvailable"} Artikel sind nicht mehr verfügbar
%option{:value => "setAvailable"} Artikel sind verfügbar
%option{:value => '', :selected => 'selected'}= t '.option_select'
%option{:value => "destroy", 'data-confirm' => t('.confirm_delete')}= t '.option_delete'
%option{:value => "setNotAvailable"}= t '.option_not_available'
%option{:value => "setAvailable"}= t '.option_available'
= hidden_field_tag 'supplier_id', @supplier.id
= pagination_links_remote @articles

View file

@ -1,7 +1,3 @@
%tr.edit_inline{:id=> "edit_"+@article.id.to_s}
%td{:colspan=>"10"}
=h @article.name
wird in laufenden Bestellungen verwendet und kann nicht gelöscht werden.
Bitte zuerst den Artikel aus den Bestellungen
= link_to "entfernen", :controller => 'orders', :action => 'edit', :id => @order
= t('.note', article: h(@article.name), drop_link: link_to(t('.drop'), :controller => 'orders', :action => 'edit', :id => @order)).html_safe

View file

@ -2,18 +2,19 @@
%thead
%tr
%th
%acronym{:title => "verfügbar"} verf.
%th Name
%th Einheit
%acronym{:title => t('.available_desc')}= t '.available_short'
%th= t 'simple_form.labels.article.name'
%th= t 'simple_form.labels.article.unit'
%th
%acronym{:title => "Netto!"} Preis
%acronym{:title => t('.price_desc')}= t '.price_short'
%th
%acronym{:title => "Gebindegröße"} GebGr
%th Best.Nr.
%th Notiz
%th Kategorie
%th MwSt.
%th Pfand
%acronym{:title => t('.unit_quantity_desc')}= t '.unit_quantity_short'
%th
%acronym{:title => t('.order_number_desc')}= t '.order_number_short'
%th= t 'simple_form.labels.article.note'
%th= t 'simple_form.labels.article.article_category'
%th= t 'simple_form.labels.defaults.tax'
%th= t 'simple_form.labels.defaults.deposit'
%tbody
- @articles.each_with_index do |article, index|
= fields_for "articles[#{article.id || index}]", article do |form|

View file

@ -2,8 +2,8 @@
= f.hidden_field :shared_updated_on
= f.hidden_field :supplier_id
.modal-header
= button_tag "x", class: 'close', data: {dismiss: 'modal'}
%h3 Neuen Artikel einfügen
= link_to t('ui.marks.close').html_safe, '#', class: 'close', data: {dismiss: 'modal'}
%h3= t '.title'
.modal-body
= f.input :availability
= f.input :name
@ -19,6 +19,6 @@
= f.input :tax
= f.input :deposit
.modal-footer
= button_tag "Schließen", class: 'btn', data: {dismiss: 'modal'}
= link_to t('ui.close'), '#', class: 'btn', data: {dismiss: 'modal'}
= f.submit class: 'btn btn-primary'

View file

@ -1,17 +1,17 @@
- if @articles.empty?
%p Keine Artikel gefunden
%p= t '.not_found'
- else
= pagination_links_remote @articles, :params => {:search => search_params}
%table.table.table-striped
%thead
%tr
%th Name
%th Herkunft
%th Hersteller
%th Notiz
%th{:style => "width:4em"} Preis
%th Einheit
%th GebGröße
%th= t 'simple_form.labels.article.name'
%th= t 'simple_form.labels.article.origin'
%th= t 'simple_form.labels.article.manufacturer'
%th= t 'simple_form.labels.article.note'
%th{:style => "width:4em"}= t 'simple_form.labels.defaults.price'
%th= t 'simple_form.labels.article.unit'
%th= t 'simple_form.labels.defaults.unit_quantity'
%th
%tbody
- for article in @articles
@ -25,9 +25,8 @@
%td= article.unit_quantity
%td
- logger.debug "[debug] #{article.attributes.inspect}"
- if @supplier.articles.where(order_number: article.number).exists?
%i.icon-ok
schon importiert
- if @supplier.articles.undeleted.where(order_number: article.number).exists?
%i.icon-ok= t '.already_imported'
- else
= link_to 'importieren', import_supplier_articles_path(@supplier, :shared_article_id => article.id),
= link_to t('.action_import'), import_supplier_articles_path(@supplier, :shared_article_id => article.id),
:remote => true, class: 'btn btn-small btn-success'

View file

@ -1,11 +1,10 @@
- title "Alle Artikel von #{@supplier.name} bearbeiten" |
- title t('.title', supplier: @supplier.name)
%p
%i
Pflichtfelder sind: Name, Einheit, (netto) Preis und Bestellnummer.
%i= t '.note'
= form_tag(update_all_supplier_articles_path(@supplier)) do
= render 'edit_all_table'
%br/
%i Achtung, alle Artikel werden aktualisiert!
%i= t '.warning'
.form-actions
= submit_tag 'Alle Artikel aktualisieren', class: 'btn btn-primary'
= link_to 'oder abbrechen', supplier_articles_path(@supplier)
= submit_tag t('.submit'), class: 'btn btn-primary'
= link_to t('ui.or_cancel'), supplier_articles_path(@supplier)

View file

@ -1,47 +1,48 @@
- title "Artikel von #{@supplier.name} (#{@supplier.articles.count})"
- title t('.title', supplier: @supplier.name, count: @supplier.articles.undeleted.count)
.well.well-small
.btn-toolbar
= form_tag supplier_articles_path(@supplier), method: :get, remote: true, class: 'form-search pull-right',
'data-submit-onchange' => true do
= text_field_tag :query, params[:query], class: 'input-medium search-query',
placeholder: 'Name ...'
placeholder: t('.search_placeholder')
.btn-group
= link_to "Neuer Artikel", new_supplier_article_path(@supplier), remote: true, class: 'btn btn-primary'
= link_to "Alle bearbeiten", edit_all_supplier_articles_path(@supplier), class: 'btn'
= link_to "Artikel hochladen", upload_supplier_articles_path(@supplier), class: 'btn'
= link_to t('.new'), new_supplier_article_path(@supplier), remote: true, class: 'btn btn-primary'
= link_to t('.edit_all'), edit_all_supplier_articles_path(@supplier), class: 'btn'
= link_to t('.upload'), upload_supplier_articles_path(@supplier), class: 'btn'
- if current_user.role_orders?
= link_to "Bestellung anlegen", new_order_path(supplier_id: @supplier), class: 'btn'
= link_to t('.new_order'), new_order_path(supplier_id: @supplier), class: 'btn'
- unless @supplier.shared_supplier.nil?
.btn-group
= link_to '#', data: {toggle: 'dropdown'}, class: 'btn btn-success dropdown-toggle' do
Externe Datenbank
= t '.ext_db.title'
%span.caret
%ul.dropdown-menu
%li= link_to "Suchen/Importieren", "#import", 'data-toggle-this' => '#import'
%li= link_to "Synchronisieren", sync_supplier_articles_path(@supplier), method: :post
%li= link_to t('.ext_db.import'), "#import", 'data-toggle-this' => '#import'
%li= link_to t('.ext_db.sync'), sync_supplier_articles_path(@supplier), method: :post
.btn-group
= link_to '#', data: {toggle: 'dropdown'}, class: 'btn dropdown-toggle' do
Lieferant wechseln ..
= t '.change_supplier'
%span.caret
%ul.dropdown-menu
- Supplier.where('id != ?', @supplier.id).order('name ASC').each do |supplier|
- Supplier.undeleted.where('id != ?', @supplier.id).order('suppliers.name ASC').each do |supplier|
%li= link_to supplier.name, supplier_articles_path(supplier), tabindex: -1
- unless @supplier.shared_supplier.nil?
#import.well.well-small(style="display:none;")
= form_tag shared_supplier_articles_path(@supplier), method: :get, remote: true, class: 'form-search',
'data-submit-onchange' => true do
%h3 Artikel importieren
= text_field_tag "search[name_contains_all]", "", class: 'input-medium search-query', placeholder: 'Name ...'
%h3= t '.import.title'
= text_field_tag "search[name_contains_all]", "", class: 'input-medium search-query',
placeholder: t('.import.placeholder')
%label.checkbox
= check_box_tag "search[origin_equals]", "REG", false
Nur aus der Region
= t '.import.restrict_region'
#search_results.clearfix
= link_to "Schließen", "#import", 'data-toggle-this' => '#import'
= link_to t('ui.close'), "#import", 'data-toggle-this' => '#import'
= form_tag update_selected_supplier_articles_path(@supplier), id: "articlesInListForm",
'data-submit-onchange' => true do

View file

@ -1,13 +1,9 @@
- title "#{@supplier.name} / Artikel hochladen"
%p
%i
Bitte überprüfe die eingelesenen Artikel.
%br/
Achtung, momentan gibt es keine Überprüfung auf doppelte Artikel.
- title t('.title', supplier: @supplier.name)
%p= t('.body').html_safe
= form_tag(create_from_upload_supplier_articles_path(@supplier)) do
= render 'edit_all_table'
.form-actions
= submit_tag "Speichere neue Artikel für #{@supplier.name}", class: 'btn btn-primary'
= link_to "order abbrechen", upload_supplier_articles_path(@supplier)
= submit_tag t('.submit', supplier: @supplier.name), class: 'btn btn-primary'
= link_to t('ui.or_cancel'), upload_supplier_articles_path(@supplier)

View file

@ -1,71 +1,70 @@
%h1 Artikel mit externer Datenbank synchronisieren
- title 'Artikel mit externer Datenbank synchronisieren'
- form_tag update_all_supplier_articles_path(@supplier, :sync => "1") do
%h2 Auslisten ...
= form_tag update_synchronized_supplier_articles_path(@supplier) do
%h2= t '.outlist.title'
%p
- unless @outlisted_articles.empty?
Folgende Artikel wurden ausgelistet und werden
%b gelöscht:
= t('.outlist.body').html_safe
%ul
- for article in @outlisted_articles
%li
= hidden_field_tag "outlisted_articles[#{article.id}]", '1'
= article.name
- if article.in_open_order
.alert
Achtung, #{article.name} wird gerade in einer laufenden Bestellung verwendet. Bitte erst Bestellung anpassen.
- else
%i Es müssen keine Artikel gelöscht werden.
%i= t '.outlist.body_skip'
%hr/
%h2 Aktualisieren ...
%h2= t '.update.title'
%p
%i
%b= @updated_articles.size
Artikel müssen aktualisiert werden:
%p
%i
Jeder Artikel wird doppelt angezeigt. Die alten Werte sind grau und die Textfelder sind mit den aktuellen
Werten vorausgefüllt.
%br/
Abweichungen zu den alten Artikeln sind gelb markiert.
%table
%tr
%th Name
%th Notiz
%th Hersteller
%th Herkunft
%th Einheit
%th GebGr
%th Preis
%th MwSt.
%th Pfand
%th Kategorie
- @updated_articles.each do |@article, unequal_attributes|
- article = Article.find(@article.id)
%tr{:style => 'color:grey'}
%td= article.name
%td= article.note
%td= article.manufacturer
%td= article.origin
%td= article.unit
%td= article.unit_quantity
%td= article.price
%td= article.tax
%td= article.deposit
%td= article.article_category.name if article.article_category
= t '.update.update_msg'
= t('.update.body').html_safe
%table.table
%thead
%tr
- fields_for 'articles[]', @article do |form|
%td{:style => highlight_new(unequal_attributes, :name)}
= form.text_field 'name', :size => 0
= form.hidden_field 'shared_updated_on'
%td{:style => highlight_new(unequal_attributes, :note)}= form.text_field 'note', :size => 15
%td{:style => highlight_new(unequal_attributes, :manufacturer)}= form.text_field 'manufacturer', :size => 10
%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, :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 }
%th= t 'simple_form.labels.article.name'
%th= t 'simple_form.labels.article.note'
%th= t 'simple_form.labels.article.manufacturer'
%th= t 'simple_form.labels.article.origin'
%th= t 'simple_form.labels.article.unit'
%th= t '.unit_quantity_short'
%th= t '.price_short'
%th= t 'simple_form.labels.defaults.tax'
%th= t 'simple_form.labels.defaults.deposit'
%th= t 'simple_form.labels.article.article_category'
%tbody
- @updated_articles.each do |updated_article, attrs|
- article = Article.find(updated_article.id)
%tr{:style => 'color:grey'}
%td= article.name
%td= article.note
%td= article.manufacturer
%td= article.origin
%td= article.unit
%td= article.unit_quantity
%td= article.price
%td= article.tax
%td= article.deposit
%td= article.article_category.name if article.article_category
%tr
= fields_for 'articles[]', updated_article do |form|
%td{:style => highlight_new(attrs, :name)}
= form.text_field 'name', :size => 0
= form.hidden_field 'shared_updated_on'
%td{:style => highlight_new(attrs, :note)}= form.text_field 'note', class: 'input-small'
%td{:style => highlight_new(attrs, :manufacturer)}= form.text_field 'manufacturer', class: 'input-small'
%td{:style => highlight_new(attrs, :origin)}= form.text_field 'origin', class: 'input-mini'
%td{:style => highlight_new(attrs, :unit)}= form.text_field 'unit', class: 'input-mini'
%td{:style => highlight_new(attrs, :unit_quantity)}= form.text_field 'unit_quantity', class: 'input-mini'
%td{:style => highlight_new(attrs, :price)}= form.text_field 'price', class: 'input-mini'
%td{:style => highlight_new(attrs, :tax)}= form.text_field 'tax', class: 'input-mini'
%td{:style => highlight_new(attrs, :deposit)}= form.text_field 'deposit', class: 'input-mini'
%td= form.select :article_category_id, ArticleCategory.all.map {|a| [ a.name, a.id ] },
{include_blank: true}, class: 'input-small'
%hr/
= hidden_field 'supplier', 'id'
= submit_tag 'Alle löschen/aktualisieren'
|
= link_to 'Abbrechen', supplier_articles_path(@supplier)
= submit_tag t('.submit'), class: 'btn btn-primary'
= link_to t('ui.or_cancel'), supplier_articles_path(@supplier)

View file

@ -1,21 +1,24 @@
- title "#{@supplier.name} / Artikel hochladen"
%p
Die Datei muss eine Textdatei mit der Endung '.csv' sein. Die erste Zeile
wird beim Einlesen ignoriert.
%br/
Die Felder müssen mit einem Semikolon (';') getrennt und der Text mit doppelten
Anführungszeichen ("Text...") umklammert werden.
%br/
Als Zeichensatz wird UTF-8 erwartet. Korrekte Reihenfolge der Spalten:
%pre
= ["Status (x=ausgelistet)", "Bestellnummer", "Name", "Notiz", "Hersteller", "Herkunft",
"Einheit", "Preis(netto)", "MwSt", "Pfand", "Gebindegröße",
"Staffelmenge", "Staffelpreis", "Kategorie"].join(" | ")
- title t('.title', supplier: @supplier.name)
= t('.body').html_safe
%pre
= [t('.fields.status'),
t('simple_form.labels.defaults.order_number'),
t('simple_form.labels.article.name'),
t('simple_form.labels.article.note'),
t('simple_form.labels.article.manufacturer'),
t('simple_form.labels.article.origin'),
t('simple_form.labels.article.unit'),
t('simple_form.labels.defaults.price'),
t('simple_form.labels.defaults.tax'),
t('simple_form.labels.defaults.deposit'),
t('simple_form.labels.defaults.unit_quantity'),
t('.fields.season_amount'),
t('.fields.season_price'),
t('simple_form.labels.article.article_category')].join(" | ")
= form_for :articles, :url => parse_upload_supplier_articles_path(@supplier),
:html => { :multipart => true } do |f|
%label(for="articles_file")
Bitte wähle eine kompatible Datei aus
%label(for="articles_file")= t '.file_label'
= f.file_field "file"
.form-actions
= submit_tag "Datei hochladen", class: 'btn'
= submit_tag t('.submit'), class: 'btn'

View file

@ -21,28 +21,24 @@
Menge
= stock_change_form.text_field :quantity, size: 5, autocomplete: 'off'
= stock_change_form.hidden_field :_destroy
= link_to "Artikel aus Lieferung entfernen", "#", class: 'destroy_stock_change'
= link_to t('.remove_article'), "#", class: 'destroy_stock_change'
%p
= link_to "Lagerartikel der Lieferung hinzufügen", {action: 'add_stock_change', supplier_id: @supplier.id}, remote: true
= link_to t('.add_article'), {action: 'add_stock_change', supplier_id: @supplier.id}, remote: true
%p
%small
Ist ein Artikel noch nicht in der Lagerverwaltung, muss er erst
#{link_to("neu angelegt", new_stock_article_path)} werden.
%small= t('.note_new_article', new_link: link_to(t('.note_new_article_link'), new_stock_article_path)).html_safe
%hr/
= f.input :delivered_on, as: :date_picker
= f.input :note, input_html: {size: '35x4'}
.form-actions
= f.submit class: 'btn btn-primary'
= link_to "oder abbrechen", supplier_deliveries_path(@supplier)
= link_to t('ui.or_cancel'), supplier_deliveries_path(@supplier)
/
TODO: Fix this!!
.span6
%h2 Neuen Lagerartikel anlegen
%h2= t '.new_article.title'
%p
Suche nach Artikeln aus dem
%i= @supplier.name
Katalog:
= t('.new_article.search', supplier: @supplier.name).html_safe + ': '
= text_field_tag 'article_name'
%hr/
#stock_article_form

View file

@ -3,4 +3,4 @@
= form.select :stock_article_id, stock_articles_for_select(supplier)
Menge
= form.text_field :quantity, :size => 5, :autocomplete => 'off'
= link_to "Artikel aus Lieferung entfernen", "#", :class => 'remove_new_stock_change'
= link_to t('.remove_article'), "#", :class => 'remove_new_stock_change'

Some files were not shown because too many files have changed in this diff Show more