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

23
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,15 +37,16 @@ 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'
gem 'binding_of_caller'
@ -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
@ -26,4 +31,4 @@ but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
(See file LICENSE for the full text of the GPL)
(See file LICENSE for the full text of the GPL)

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,
@ -30,4 +31,4 @@ class OrderByArticles < OrderPdf
end
end
end
end

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
@ -48,4 +49,4 @@ class OrderByGroups < OrderPdf
end
end
end
end

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,
@ -83,4 +84,4 @@ class OrderMatrix < OrderPdf
end
end
end
end

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)
@ -21,7 +23,19 @@ class Group < ActiveRecord::Base
def user_tokens=(ids)
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
@ -116,6 +115,16 @@ class Ordergroup < Group
errors.add :name, message
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

@ -7,6 +7,12 @@ 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?",
:method => :delete, class: 'btn btn-mini btn-danger'
= 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'
= link_to_new_message(message_params: {group_id: @workgroup.id})
%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'
= 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'
= 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
= 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|
@ -31,4 +32,4 @@
%td= form.text_field 'deposit', class: 'input-mini'
- unless article.errors.empty?
%tr.alert
%td(colspan="10")= article.errors.full_messages.join(", ")
%td(colspan="10")= article.errors.full_messages.join(", ")

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